diff --git a/src/liballoc/Cargo.toml b/src/liballoc/Cargo.toml
index d1119f7b7c0a7..914195f015b5a 100644
--- a/src/liballoc/Cargo.toml
+++ b/src/liballoc/Cargo.toml
@@ -25,6 +25,7 @@ path = "../liballoc/tests/lib.rs"
 [[bench]]
 name = "collectionsbenches"
 path = "../liballoc/benches/lib.rs"
+test = true
 
 [[bench]]
 name = "vec_deque_append_bench"
diff --git a/src/libcore/Cargo.toml b/src/libcore/Cargo.toml
index ac07ffb14febd..42c555cafac86 100644
--- a/src/libcore/Cargo.toml
+++ b/src/libcore/Cargo.toml
@@ -19,6 +19,7 @@ path = "../libcore/tests/lib.rs"
 [[bench]]
 name = "corebenches"
 path = "../libcore/benches/lib.rs"
+test = true
 
 [dev-dependencies]
 rand = "0.7"
diff --git a/src/libcore/mem/mod.rs b/src/libcore/mem/mod.rs
index 8bce980cadd1e..066bb8b3dc787 100644
--- a/src/libcore/mem/mod.rs
+++ b/src/libcore/mem/mod.rs
@@ -581,11 +581,12 @@ pub const fn needs_drop<T>() -> bool {
 /// This means that, for example, the padding byte in `(u8, u16)` is not
 /// necessarily zeroed.
 ///
-/// There is no guarantee that an all-zero byte-pattern represents a valid value of
-/// some type `T`. For example, the all-zero byte-pattern is not a valid value
-/// for reference types (`&T` and `&mut T`). Using `zeroed` on such types
-/// causes immediate [undefined behavior][ub] because [the Rust compiler assumes][inv]
-/// that there always is a valid value in a variable it considers initialized.
+/// There is no guarantee that an all-zero byte-pattern represents a valid value
+/// of some type `T`. For example, the all-zero byte-pattern is not a valid value
+/// for reference types (`&T`, `&mut T`) and functions pointers. Using `zeroed`
+/// on such types causes immediate [undefined behavior][ub] because [the Rust
+/// compiler assumes][inv] that there always is a valid value in a variable it
+/// considers initialized.
 ///
 /// This has the same effect as [`MaybeUninit::zeroed().assume_init()`][zeroed].
 /// It is useful for FFI sometimes, but should generally be avoided.
@@ -612,6 +613,7 @@ pub const fn needs_drop<T>() -> bool {
 /// use std::mem;
 ///
 /// let _x: &i32 = unsafe { mem::zeroed() }; // Undefined behavior!
+/// let _y: fn() = unsafe { mem::zeroed() }; // And again!
 /// ```
 #[inline(always)]
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libcore/result.rs b/src/libcore/result.rs
index c7b5777a16e7f..2080ae193667e 100644
--- a/src/libcore/result.rs
+++ b/src/libcore/result.rs
@@ -1145,45 +1145,69 @@ impl<T, E: Into<!>> Result<T, E> {
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+#[unstable(feature = "inner_deref", issue = "50264")]
 impl<T: Deref, E> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T::Target, &E>`.
+    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&<T as Deref>::Target, &E>`.
     ///
-    /// Leaves the original `Result` in-place, creating a new one containing a reference to the
-    /// `Ok` type's `Deref::Target` type.
+    /// Coerces the [`Ok`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
+    /// and returns the new [`Result`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let x: Result<String, u32> = Ok("hello".to_string());
+    /// let y: Result<&str, &u32> = Ok("hello");
+    /// assert_eq!(x.as_deref(), y);
+    ///
+    /// let x: Result<String, u32> = Err(42);
+    /// let y: Result<&str, &u32> = Err(&42);
+    /// assert_eq!(x.as_deref(), y);
+    /// ```
     pub fn as_deref(&self) -> Result<&T::Target, &E> {
         self.as_ref().map(|t| t.deref())
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+#[unstable(feature = "inner_deref", issue = "50264")]
 impl<T, E: Deref> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &E::Target>`.
+    /// Converts from `Result<T, E>` (or `&Result<T, E>`) to `Result<&T, &<E as Deref>::Target>`.
     ///
-    /// Leaves the original `Result` in-place, creating a new one containing a reference to the
-    /// `Err` type's `Deref::Target` type.
+    /// Coerces the [`Err`] variant of the original [`Result`] via [`Deref`](crate::ops::Deref)
+    /// and returns the new [`Result`].
     pub fn as_deref_err(&self) -> Result<&T, &E::Target> {
         self.as_ref().map_err(|e| e.deref())
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+#[unstable(feature = "inner_deref", issue = "50264")]
 impl<T: DerefMut, E> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T::Target, &mut E>`.
+    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut <T as DerefMut>::Target, &mut E>`.
     ///
-    /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
-    /// the `Ok` type's `Deref::Target` type.
+    /// Coerces the [`Ok`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
+    /// and returns the new [`Result`].
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let mut x: Result<String, u32> = Ok("hello".to_string());
+    /// let y: Result<&mut str, &mut u32> = Ok("HELLO");
+    /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
+    ///
+    /// let mut x: Result<String, u32> = Err(42);
+    /// let y: Result<&mut str, &mut u32> = Err(&42);
+    /// assert_eq!(x.as_deref_mut().map(|x| { x.make_ascii_uppercase(); x }), y);
+    /// ```
     pub fn as_deref_mut(&mut self) -> Result<&mut T::Target, &mut E> {
         self.as_mut().map(|t| t.deref_mut())
     }
 }
 
-#[unstable(feature = "inner_deref", reason = "newly added", issue = "50264")]
+#[unstable(feature = "inner_deref", issue = "50264")]
 impl<T, E: DerefMut> Result<T, E> {
-    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut E::Target>`.
+    /// Converts from `Result<T, E>` (or `&mut Result<T, E>`) to `Result<&mut T, &mut <E as DerefMut>::Target>`.
     ///
-    /// Leaves the original `Result` in-place, creating a new one containing a mutable reference to
-    /// the `Err` type's `Deref::Target` type.
+    /// Coerces the [`Err`] variant of the original [`Result`] via [`DerefMut`](crate::ops::DerefMut)
+    /// and returns the new [`Result`].
     pub fn as_deref_mut_err(&mut self) -> Result<&mut T, &mut E::Target> {
         self.as_mut().map_err(|e| e.deref_mut())
     }
diff --git a/src/libcore/tests/array.rs b/src/libcore/tests/array.rs
index c2a816f0a7d90..4bc44e98fc802 100644
--- a/src/libcore/tests/array.rs
+++ b/src/libcore/tests/array.rs
@@ -241,3 +241,52 @@ fn iterator_drops() {
     }
     assert_eq!(i.get(), 5);
 }
+
+// This test does not work on targets without panic=unwind support.
+// To work around this problem, test is marked is should_panic, so it will
+// be automagically skipped on unsuitable targets, such as
+// wasm32-unknown-unkown.
+//
+// It means that we use panic for indicating success.
+#[test]
+#[should_panic(expected = "test succeeded")]
+fn array_default_impl_avoids_leaks_on_panic() {
+    use core::sync::atomic::{AtomicUsize, Ordering::Relaxed};
+    static COUNTER: AtomicUsize = AtomicUsize::new(0);
+    #[derive(Debug)]
+    struct Bomb(usize);
+
+    impl Default for Bomb {
+        fn default() -> Bomb {
+            if COUNTER.load(Relaxed) == 3 {
+                panic!("bomb limit exceeded");
+            }
+
+            COUNTER.fetch_add(1, Relaxed);
+            Bomb(COUNTER.load(Relaxed))
+        }
+    }
+
+    impl Drop for Bomb {
+        fn drop(&mut self) {
+            COUNTER.fetch_sub(1, Relaxed);
+        }
+    }
+
+    let res = std::panic::catch_unwind(|| <[Bomb; 5]>::default());
+    let panic_msg = match res {
+        Ok(_) => unreachable!(),
+        Err(p) => p.downcast::<&'static str>().unwrap(),
+    };
+    assert_eq!(*panic_msg, "bomb limit exceeded");
+    // check that all bombs are successfully dropped
+    assert_eq!(COUNTER.load(Relaxed), 0);
+    panic!("test succeeded")
+}
+
+#[test]
+fn empty_array_is_always_default() {
+    struct DoesNotImplDefault;
+
+    let _arr = <[DoesNotImplDefault; 0]>::default();
+}
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 37ebf4112808e..4e55452a4c31b 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -19,7 +19,7 @@
 #![feature(raw)]
 #![feature(sort_internals)]
 #![feature(slice_partition_at_index)]
-#![feature(specialization)]
+#![feature(min_specialization)]
 #![feature(step_trait)]
 #![feature(step_trait_ext)]
 #![feature(str_internals)]
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 62406552e318f..ce186c4834d72 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -5,7 +5,7 @@
 //! additional metadata), and [`ItemKind`] (which represents a concrete type and contains
 //! information specific to the type of the item).
 //!
-//! Other module items that worth mentioning:
+//! Other module items worth mentioning:
 //! - [`Ty`] and [`TyKind`]: A parsed Rust type.
 //! - [`Expr`] and [`ExprKind`]: A parsed Rust expression.
 //! - [`Pat`] and [`PatKind`]: A parsed Rust pattern. Patterns are often dual to expressions.
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_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_feature/active.rs b/src/librustc_feature/active.rs
index d186f35a12b5a..7aadf58243f31 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -596,4 +596,5 @@ pub const INCOMPLETE_FEATURES: &[Symbol] = &[
     sym::raw_dylib,
     sym::const_trait_impl,
     sym::const_trait_bound_opt_out,
+    sym::specialization,
 ];
diff --git a/src/librustc_hir/hir.rs b/src/librustc_hir/hir.rs
index 634ab32a28542..bed2044c70855 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2726,6 +2726,18 @@ impl Node<'_> {
         }
     }
 
+    pub fn body_id(&self) -> Option<BodyId> {
+        match self {
+            Node::TraitItem(TraitItem {
+                kind: TraitItemKind::Fn(_, TraitFn::Provided(body_id)),
+                ..
+            })
+            | Node::ImplItem(ImplItem { kind: ImplItemKind::Fn(_, body_id), .. })
+            | Node::Item(Item { kind: ItemKind::Fn(.., body_id), .. }) => Some(*body_id),
+            _ => None,
+        }
+    }
+
     pub fn generics(&self) -> Option<&Generics<'_>> {
         match self {
             Node::TraitItem(TraitItem { generics, .. })
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_metadata/creader.rs b/src/librustc_metadata/creader.rs
index b8ebcd6c8a8ff..57b14ac747f8d 100644
--- a/src/librustc_metadata/creader.rs
+++ b/src/librustc_metadata/creader.rs
@@ -452,6 +452,14 @@ impl<'a> CrateLoader<'a> {
         if dep.is_none() {
             self.used_extern_options.insert(name);
         }
+        if !name.as_str().is_ascii() {
+            self.sess
+                .struct_span_err(
+                    span,
+                    &format!("cannot load a crate with a non-ascii name `{}`", name,),
+                )
+                .emit();
+        }
         self.maybe_resolve_crate(name, span, dep_kind, dep).unwrap_or_else(|err| err.report())
     }
 
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 de2e1046f1cbb..a553630e4270a 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`.
@@ -803,7 +802,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)),
@@ -1142,6 +1140,31 @@ 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.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.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, "ty::ConstKind::Error constructed but no error reported.");
+        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)
@@ -1845,7 +1868,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..cf11adb0285ac 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -203,9 +203,15 @@ 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)]
+#[derive(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 +1990,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 +2022,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 +2146,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 +2173,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 +2378,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 +2438,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 7cf4fdfcf3c5b..730601ed5c03a 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/const_to_pat.rs b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
index 087c2c064cfaf..1aed8e844b60b 100644
--- a/src/librustc_mir_build/hair/pattern/const_to_pat.rs
+++ b/src/librustc_mir_build/hair/pattern/const_to_pat.rs
@@ -107,8 +107,15 @@ impl<'a, 'tcx> ConstToPat<'a, 'tcx> {
                 cv.ty, structural
             );
 
+            // This can occur because const qualification treats all associated constants as
+            // opaque, whereas `search_for_structural_match_violation` tries to monomorphize them
+            // before it runs.
+            //
+            // FIXME(#73448): Find a way to bring const qualification into parity with
+            // `search_for_structural_match_violation`.
             if structural.is_none() && mir_structural_match_violation {
-                bug!("MIR const-checker found novel structural match violation");
+                warn!("MIR const-checker found novel structural match violation. See #73448.");
+                return inlined_const_as_pat;
             }
 
             if let Some(non_sm_ty) = structural {
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_target/spec/x86_64_unknown_linux_musl.rs b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
index 34c628e8f67bd..3a22290da6858 100644
--- a/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
+++ b/src/librustc_target/spec/x86_64_unknown_linux_musl.rs
@@ -6,6 +6,7 @@ pub fn target() -> TargetResult {
     base.max_atomic_width = Some(64);
     base.pre_link_args.get_mut(&LinkerFlavor::Gcc).unwrap().push("-m64".to_string());
     base.stack_probes = true;
+    base.static_position_independent_executables = true;
 
     Ok(Target {
         llvm_target: "x86_64-unknown-linux-musl".to_string(),
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..dfd7dac72d8e1 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.
@@ -1992,8 +1992,8 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 /// Collect all the returned expressions within the input expression.
 /// Used to point at the return spans when we want to suggest some change to them.
 #[derive(Default)]
-struct ReturnsVisitor<'v> {
-    returns: Vec<&'v hir::Expr<'v>>,
+pub struct ReturnsVisitor<'v> {
+    pub returns: Vec<&'v hir::Expr<'v>>,
     in_block_tail: bool,
 }
 
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 90a9b876d8ddf..1825c159ff3fb 100644
--- a/src/librustc_trait_selection/traits/wf.rs
+++ b/src/librustc_trait_selection/traits/wf.rs
@@ -392,7 +392,7 @@ impl<'a, 'tcx> WfPredicates<'a, 'tcx> {
                                 ));
                             }
                         }
-                        ty::ConstKind::Error
+                        ty::ConstKind::Error(_)
                         | ty::ConstKind::Param(_)
                         | ty::ConstKind::Bound(..)
                         | ty::ConstKind::Placeholder(..) => {
@@ -412,7 +412,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 c26acd7a47703..b60b06567d6fa 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -138,6 +138,7 @@ use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::opaque_types::{InferCtxtExt as _, OpaqueTypeDecl};
 use rustc_trait_selection::traits::error_reporting::recursive_type_with_infinite_size_error;
+use rustc_trait_selection::traits::error_reporting::suggestions::ReturnsVisitor;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt as _;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
 use rustc_trait_selection::traits::{
@@ -967,8 +968,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)
 }
@@ -1711,6 +1711,173 @@ fn check_opaque_for_inheriting_lifetimes(tcx: TyCtxt<'tcx>, def_id: LocalDefId,
     }
 }
 
+/// Given a `DefId` for an opaque type in return position, find its parent item's return
+/// expressions.
+fn get_owner_return_paths(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+) -> Option<(hir::HirId, ReturnsVisitor<'tcx>)> {
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let id = tcx.hir().get_parent_item(hir_id);
+    tcx.hir()
+        .find(id)
+        .map(|n| (id, n))
+        .and_then(|(hir_id, node)| node.body_id().map(|b| (hir_id, b)))
+        .map(|(hir_id, body_id)| {
+            let body = tcx.hir().body(body_id);
+            let mut visitor = ReturnsVisitor::default();
+            visitor.visit_body(body);
+            (hir_id, visitor)
+        })
+}
+
+/// Emit an error for recursive opaque types.
+///
+/// If this is a return `impl Trait`, find the item's return expressions and point at them. For
+/// direct recursion this is enough, but for indirect recursion also point at the last intermediary
+/// `impl Trait`.
+///
+/// If all the return expressions evaluate to `!`, then we explain that the error will go away
+/// after changing it. This can happen when a user uses `panic!()` or similar as a placeholder.
+fn opaque_type_cycle_error(tcx: TyCtxt<'tcx>, def_id: LocalDefId, span: Span) {
+    let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
+
+    let mut label = false;
+    if let Some((hir_id, visitor)) = get_owner_return_paths(tcx, def_id) {
+        let tables = tcx.typeck_tables_of(tcx.hir().local_def_id(hir_id));
+        if visitor
+            .returns
+            .iter()
+            .filter_map(|expr| tables.node_type_opt(expr.hir_id))
+            .all(|ty| matches!(ty.kind, ty::Never))
+        {
+            let spans = visitor
+                .returns
+                .iter()
+                .filter(|expr| tables.node_type_opt(expr.hir_id).is_some())
+                .map(|expr| expr.span)
+                .collect::<Vec<Span>>();
+            let span_len = spans.len();
+            if span_len == 1 {
+                err.span_label(spans[0], "this returned value is of `!` type");
+            } else {
+                let mut multispan: MultiSpan = spans.clone().into();
+                for span in spans {
+                    multispan
+                        .push_span_label(span, "this returned value is of `!` type".to_string());
+                }
+                err.span_note(multispan, "these returned values have a concrete \"never\" type");
+            }
+            err.help("this error will resolve once the item's body returns a concrete type");
+        } else {
+            let mut seen = FxHashSet::default();
+            seen.insert(span);
+            err.span_label(span, "recursive opaque type");
+            label = true;
+            for (sp, ty) in visitor
+                .returns
+                .iter()
+                .filter_map(|e| tables.node_type_opt(e.hir_id).map(|t| (e.span, t)))
+                .filter(|(_, ty)| !matches!(ty.kind, ty::Never))
+            {
+                struct VisitTypes(Vec<DefId>);
+                impl<'tcx> ty::fold::TypeVisitor<'tcx> for VisitTypes {
+                    fn visit_ty(&mut self, t: Ty<'tcx>) -> bool {
+                        match t.kind {
+                            ty::Opaque(def, _) => {
+                                self.0.push(def);
+                                false
+                            }
+                            _ => t.super_visit_with(self),
+                        }
+                    }
+                }
+                let mut visitor = VisitTypes(vec![]);
+                ty.visit_with(&mut visitor);
+                for def_id in visitor.0 {
+                    let ty_span = tcx.def_span(def_id);
+                    if !seen.contains(&ty_span) {
+                        err.span_label(ty_span, &format!("returning this opaque type `{}`", ty));
+                        seen.insert(ty_span);
+                    }
+                    err.span_label(sp, &format!("returning here with type `{}`", ty));
+                }
+            }
+        }
+    }
+    if !label {
+        err.span_label(span, "cannot resolve opaque type");
+    }
+    err.emit();
+}
+
+/// Emit an error for recursive opaque types in a `let` binding.
+fn binding_opaque_type_cycle_error(
+    tcx: TyCtxt<'tcx>,
+    def_id: LocalDefId,
+    span: Span,
+    partially_expanded_type: Ty<'tcx>,
+) {
+    let mut err = struct_span_err!(tcx.sess, span, E0720, "cannot resolve opaque type");
+    err.span_label(span, "cannot resolve opaque type");
+    // Find the the owner that declared this `impl Trait` type.
+    let hir_id = tcx.hir().as_local_hir_id(def_id);
+    let mut prev_hir_id = hir_id;
+    let mut hir_id = tcx.hir().get_parent_node(hir_id);
+    while let Some(node) = tcx.hir().find(hir_id) {
+        match node {
+            hir::Node::Local(hir::Local {
+                pat,
+                init: None,
+                ty: Some(ty),
+                source: hir::LocalSource::Normal,
+                ..
+            }) => {
+                err.span_label(pat.span, "this binding might not have a concrete type");
+                err.span_suggestion_verbose(
+                    ty.span.shrink_to_hi(),
+                    "set the binding to a value for a concrete type to be resolved",
+                    " = /* value */".to_string(),
+                    Applicability::HasPlaceholders,
+                );
+            }
+            hir::Node::Local(hir::Local {
+                init: Some(expr),
+                source: hir::LocalSource::Normal,
+                ..
+            }) => {
+                let hir_id = tcx.hir().as_local_hir_id(def_id);
+                let tables =
+                    tcx.typeck_tables_of(tcx.hir().local_def_id(tcx.hir().get_parent_item(hir_id)));
+                if let Some(ty) = tables.node_type_opt(expr.hir_id) {
+                    err.span_label(
+                        expr.span,
+                        &format!(
+                            "this is of type `{}`, which doesn't constrain \
+                             `{}` enough to arrive to a concrete type",
+                            ty, partially_expanded_type
+                        ),
+                    );
+                }
+            }
+            _ => {}
+        }
+        if prev_hir_id == hir_id {
+            break;
+        }
+        prev_hir_id = hir_id;
+        hir_id = tcx.hir().get_parent_node(hir_id);
+    }
+    err.emit();
+}
+
+fn async_opaque_type_cycle_error(tcx: TyCtxt<'tcx>, span: Span) {
+    struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing")
+        .span_label(span, "recursive `async fn`")
+        .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
+        .emit();
+}
+
 /// Checks that an opaque type does not contain cycles.
 fn check_opaque_for_cycles<'tcx>(
     tcx: TyCtxt<'tcx>,
@@ -1721,21 +1888,12 @@ fn check_opaque_for_cycles<'tcx>(
 ) {
     if let Err(partially_expanded_type) = tcx.try_expand_impl_trait_type(def_id.to_def_id(), substs)
     {
-        if let hir::OpaqueTyOrigin::AsyncFn = origin {
-            struct_span_err!(tcx.sess, span, E0733, "recursion in an `async fn` requires boxing",)
-                .span_label(span, "recursive `async fn`")
-                .note("a recursive `async fn` must be rewritten to return a boxed `dyn Future`")
-                .emit();
-        } else {
-            let mut err =
-                struct_span_err!(tcx.sess, span, E0720, "opaque type expands to a recursive type",);
-            err.span_label(span, "expands to a recursive type");
-            if let ty::Opaque(..) = partially_expanded_type.kind {
-                err.note("type resolves to itself");
-            } else {
-                err.note(&format!("expanded type is `{}`", partially_expanded_type));
+        match origin {
+            hir::OpaqueTyOrigin::AsyncFn => async_opaque_type_cycle_error(tcx, span),
+            hir::OpaqueTyOrigin::Binding => {
+                binding_opaque_type_cycle_error(tcx, def_id, span, partially_expanded_type)
             }
-            err.emit();
+            _ => opaque_type_cycle_error(tcx, def_id, span),
         }
     }
 }
@@ -3387,7 +3545,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 +3659,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 +3932,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 +4319,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 +4463,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 +4600,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 +4728,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 +4948,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 +5536,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 +5696,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     }
                     err.emit();
 
-                    return (tcx.types.err, res);
+                    return (tcx.ty_error(), res);
                 }
             }
         } else {
@@ -5731,8 +5889,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/librustdoc/html/static/main.js b/src/librustdoc/html/static/main.js
index 953f61a3772dc..8d53b05795374 100644
--- a/src/librustdoc/html/static/main.js
+++ b/src/librustdoc/html/static/main.js
@@ -100,6 +100,8 @@ function defocusSearchBar() {
     // 2 for "In Return Types"
     var currentTab = 0;
 
+    var mouseMovedAfterSearch = true;
+
     var titleBeforeSearch = document.title;
 
     function clearInputTimeout() {
@@ -162,6 +164,7 @@ function defocusSearchBar() {
         }
         addClass(main, "hidden");
         removeClass(search, "hidden");
+        mouseMovedAfterSearch = false;
     }
 
     function hideSearchResults(search) {
@@ -424,6 +427,12 @@ function defocusSearchBar() {
     document.addEventListener("keypress", handleShortcut);
     document.addEventListener("keydown", handleShortcut);
 
+    function resetMouseMoved(ev) {
+        mouseMovedAfterSearch = true;
+    }
+
+    document.addEventListener("mousemove", resetMouseMoved);
+
     var handleSourceHighlight = (function() {
         var prev_line_id = 0;
 
@@ -1353,20 +1362,22 @@ function defocusSearchBar() {
                 }
             };
             var mouseover_func = function(e) {
-                var el = e.target;
-                // to retrieve the real "owner" of the event.
-                while (el.tagName !== "TR") {
-                    el = el.parentNode;
-                }
-                clearTimeout(hoverTimeout);
-                hoverTimeout = setTimeout(function() {
-                    onEachLazy(document.getElementsByClassName("search-results"), function(e) {
-                        onEachLazy(e.getElementsByClassName("result"), function(i_e) {
-                            removeClass(i_e, "highlighted");
+                if (mouseMovedAfterSearch) {
+                    var el = e.target;
+                    // to retrieve the real "owner" of the event.
+                    while (el.tagName !== "TR") {
+                        el = el.parentNode;
+                    }
+                    clearTimeout(hoverTimeout);
+                    hoverTimeout = setTimeout(function() {
+                        onEachLazy(document.getElementsByClassName("search-results"), function(e) {
+                            onEachLazy(e.getElementsByClassName("result"), function(i_e) {
+                                removeClass(i_e, "highlighted");
+                            });
                         });
-                    });
-                    addClass(el, "highlighted");
-                }, 20);
+                        addClass(el, "highlighted");
+                    }, 20);
+                }
             };
             onEachLazy(document.getElementsByClassName("search-results"), function(e) {
                 onEachLazy(e.getElementsByClassName("result"), function(i_e) {
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 82d6cda986a9a..95d113166e001 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -165,9 +165,8 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optmulti(
                 "",
                 "passes",
-                "list of passes to also run, you might want \
-                        to pass it multiple times; a value of `list` \
-                        will print available passes",
+                "list of passes to also run, you might want to pass it multiple times; a value of \
+                        `list` will print available passes",
                 "PASSES",
             )
         }),
@@ -248,8 +247,8 @@ fn opts() -> Vec<RustcOptGroup> {
                 "e",
                 "extend-css",
                 "To add some CSS rules with a given file to generate doc with your \
-                      own theme. However, your theme might break if the rustdoc's generated HTML \
-                      changes, so be careful!",
+                        own theme. However, your theme might break if the rustdoc's generated HTML \
+                        changes, so be careful!",
                 "PATH",
             )
         }),
@@ -262,7 +261,7 @@ fn opts() -> Vec<RustcOptGroup> {
                 "",
                 "playground-url",
                 "URL to send code snippets to, may be reset by --markdown-playground-url \
-                      or `#![doc(html_playground_url=...)]`",
+                        or `#![doc(html_playground_url=...)]`",
                 "URL",
             )
         }),
@@ -276,8 +275,7 @@ fn opts() -> Vec<RustcOptGroup> {
             o.optflag(
                 "",
                 "sort-modules-by-appearance",
-                "sort modules by where they appear in the \
-                                                         program, rather than alphabetically",
+                "sort modules by where they appear in the program, rather than alphabetically",
             )
         }),
         stable("theme", |o| {
@@ -358,7 +356,7 @@ fn opts() -> Vec<RustcOptGroup> {
                 "",
                 "static-root-path",
                 "Path string to force loading static files from in output pages. \
-                      If not set, uses combinations of '../' to reach the documentation root.",
+                        If not set, uses combinations of '../' to reach the documentation root.",
                 "PATH",
             )
         }),
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 83029a8642097..490afb5a0438f 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -74,3 +74,8 @@ std_detect_dlsym_getauxval = []
 threads = 125
 # Maximum heap size
 heap_size = 0x8000000
+
+[[bench]]
+name = "stdbenches"
+path = "benches/lib.rs"
+test = true
diff --git a/src/libstd/time.rs b/src/libstd/time.rs
index bc3bfde6d7559..295ebcbb72939 100644
--- a/src/libstd/time.rs
+++ b/src/libstd/time.rs
@@ -60,6 +60,21 @@ pub use core::time::Duration;
 /// }
 /// ```
 ///
+/// # OS-specific behaviors
+///
+/// An `Instant` is a wrapper around system-specific types and it may behave
+/// differently depending on the underlying operating system. For example,
+/// the following snippet is fine on Linux but panics on macOS:
+///
+/// ```no_run
+/// use std::time::{Instant, Duration};
+///
+/// let now = Instant::now();
+/// let max_nanoseconds = u64::MAX / 1_000_000_000;
+/// let duration = Duration::new(max_nanoseconds, 0);
+/// println!("{:?}", now + duration);
+/// ```
+///
 /// # Underlying System calls
 /// Currently, the following system calls are being used to get the current time using `now()`:
 ///
diff --git a/src/rustllvm/PassWrapper.cpp b/src/rustllvm/PassWrapper.cpp
index 3d252fe70afeb..323bd26c698a3 100644
--- a/src/rustllvm/PassWrapper.cpp
+++ b/src/rustllvm/PassWrapper.cpp
@@ -424,6 +424,12 @@ extern "C" void LLVMRustPrintTargetFeatures(LLVMTargetMachineRef TM) {
   printf("Available features for this target:\n");
   for (auto &Feature : FeatTable)
     printf("    %-*s - %s.\n", MaxFeatLen, Feature.Key, Feature.Desc);
+  printf("\nRust-specific features:\n");
+  printf("    %-*s - %s.\n",
+    MaxFeatLen,
+    "crt-static",
+    "Enables libraries with C Run-time Libraries(CRT) to be statically linked"
+  );
   printf("\n");
 
   printf("Use +feature to enable a feature, or -feature to disable it.\n"
diff --git a/src/test/compile-fail/specialization/issue-50452.rs b/src/test/compile-fail/specialization/issue-50452.rs
index d9e5280c7e11d..958f0eb266801 100644
--- a/src/test/compile-fail/specialization/issue-50452.rs
+++ b/src/test/compile-fail/specialization/issue-50452.rs
@@ -1,6 +1,6 @@
 // compile-fail
-
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn foo();
diff --git a/src/test/run-make/static-pie/Makefile b/src/test/run-make/static-pie/Makefile
new file mode 100644
index 0000000000000..1d3cc82138927
--- /dev/null
+++ b/src/test/run-make/static-pie/Makefile
@@ -0,0 +1,15 @@
+-include ../../run-make-fulldeps/tools.mk
+
+# only-x86_64-unknown-linux-musl
+
+# How to manually run this
+# $ ./x.py test --target x86_64-unknown-linux-musl src/test/run-make/static-pie
+
+all:
+	$(RUSTC) --target $(TARGET) -C target-feature=+crt-static test-aslr.rs
+	# Check that no dynamic interpreter is set
+	! readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) INTERP
+	# Check that we have a dynamic executable
+	readelf -l $(call RUN_BINFILE,test-aslr) | $(CGREP) DYNAMIC
+	# Check for address space layout randomization
+	$(call RUN,test-aslr) --test-aslr
diff --git a/src/test/run-make/static-pie/test-aslr.rs b/src/test/run-make/static-pie/test-aslr.rs
new file mode 100644
index 0000000000000..f28e00f7f4cf9
--- /dev/null
+++ b/src/test/run-make/static-pie/test-aslr.rs
@@ -0,0 +1,43 @@
+const NUM_RUNS: usize = 10;
+
+fn run_self(exe: &str) -> usize {
+    use std::process::Command;
+    let mut set = std::collections::HashSet::new();
+
+    let mut cmd = Command::new(exe);
+    cmd.arg("--report");
+    (0..NUM_RUNS).for_each(|_| {
+        set.insert(cmd.output().expect("failed to execute process").stdout);
+    });
+    set.len()
+}
+
+fn main() {
+    let mut args = std::env::args();
+    let arg0 = args.next().unwrap();
+    match args.next() {
+        Some(s) if s.eq("--report") => {
+            println!("main = {:#?}", &main as *const _);
+        }
+        Some(s) if s.eq("--test-no-aslr") => {
+            let cnt = run_self(&arg0);
+            if cnt != 1 {
+                eprintln!("FAIL: {} most likely ASLR", arg0);
+                std::process::exit(1);
+            }
+            println!("PASS: {} does no ASLR", arg0);
+        }
+        Some(s) if s.eq("--test-aslr") => {
+            let cnt = run_self(&arg0);
+            if cnt != NUM_RUNS {
+                eprintln!("FAIL: {} most likely no ASLR", arg0);
+                std::process::exit(1);
+            }
+            println!("PASS: {} does ASLR", arg0);
+        }
+        Some(_) | None => {
+            println!("Usage: {} --test-no-aslr | --test-aslr", arg0);
+            std::process::exit(1);
+        }
+    }
+}
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>`
diff --git a/src/test/ui/associated-types/defaults-specialization.rs b/src/test/ui/associated-types/defaults-specialization.rs
index d0ed718b83923..553705b2a4fab 100644
--- a/src/test/ui/associated-types/defaults-specialization.rs
+++ b/src/test/ui/associated-types/defaults-specialization.rs
@@ -1,6 +1,7 @@
 //! Tests the interaction of associated type defaults and specialization.
 
 #![feature(associated_type_defaults, specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Tr {
     type Ty = u8;
diff --git a/src/test/ui/associated-types/defaults-specialization.stderr b/src/test/ui/associated-types/defaults-specialization.stderr
index 37a4d9b60fdfd..09a8c8f8a88a2 100644
--- a/src/test/ui/associated-types/defaults-specialization.stderr
+++ b/src/test/ui/associated-types/defaults-specialization.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/defaults-specialization.rs:3:38
+   |
+LL | #![feature(associated_type_defaults, specialization)]
+   |                                      ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:18:18
+  --> $DIR/defaults-specialization.rs:19:18
    |
 LL |     fn make() -> Self::Ty {
    |                  -------- type in trait
@@ -11,7 +20,7 @@ LL |     fn make() -> u8 { 0 }
               found fn pointer `fn() -> u8`
 
 error[E0053]: method `make` has an incompatible type for trait
-  --> $DIR/defaults-specialization.rs:34:18
+  --> $DIR/defaults-specialization.rs:35:18
    |
 LL |     fn make() -> Self::Ty {
    |                  -------- type in trait
@@ -26,7 +35,7 @@ LL |     fn make() -> bool { true }
               found fn pointer `fn() -> bool`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:9:9
+  --> $DIR/defaults-specialization.rs:10:9
    |
 LL |     type Ty = u8;
    |     ------------- associated type defaults can't be assumed inside the trait defining them
@@ -40,7 +49,7 @@ LL |         0u8
                          found type `u8`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:25:29
+  --> $DIR/defaults-specialization.rs:26:29
    |
 LL |     fn make() -> Self::Ty { 0u8 }
    |                  --------   ^^^ expected associated type, found `u8`
@@ -53,7 +62,7 @@ LL |     fn make() -> Self::Ty { 0u8 }
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:43:29
+  --> $DIR/defaults-specialization.rs:44:29
    |
 LL |     default type Ty = bool;
    |     ----------------------- expected this associated type
@@ -67,7 +76,7 @@ LL |     fn make() -> Self::Ty { true }
                          found type `bool`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:86:32
+  --> $DIR/defaults-specialization.rs:87:32
    |
 LL |     let _: <B<()> as Tr>::Ty = 0u8;
    |            -----------------   ^^^ expected associated type, found `u8`
@@ -77,13 +86,13 @@ LL |     let _: <B<()> as Tr>::Ty = 0u8;
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:87:32
+  --> $DIR/defaults-specialization.rs:88:32
    |
 LL |     let _: <B<()> as Tr>::Ty = true;
    |            -----------------   ^^^^ expected associated type, found `bool`
@@ -93,13 +102,13 @@ LL |     let _: <B<()> as Tr>::Ty = true;
    = note: expected associated type `<B<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:88:33
+  --> $DIR/defaults-specialization.rs:89:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = 0u8;
    |            ------------------   ^^^ expected associated type, found `u8`
@@ -109,13 +118,13 @@ LL |     let _: <B2<()> as Tr>::Ty = 0u8;
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `u8`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
 error[E0308]: mismatched types
-  --> $DIR/defaults-specialization.rs:89:33
+  --> $DIR/defaults-specialization.rs:90:33
    |
 LL |     let _: <B2<()> as Tr>::Ty = true;
    |            ------------------   ^^^^ expected associated type, found `bool`
@@ -125,12 +134,12 @@ LL |     let _: <B2<()> as Tr>::Ty = true;
    = note: expected associated type `<B2<()> as Tr>::Ty`
                          found type `bool`
 help: a method is available that returns `<B2<()> as Tr>::Ty`
-  --> $DIR/defaults-specialization.rs:8:5
+  --> $DIR/defaults-specialization.rs:9:5
    |
 LL |     fn make() -> Self::Ty {
    |     ^^^^^^^^^^^^^^^^^^^^^ consider calling `Tr::make`
 
-error: aborting due to 9 previous errors
+error: aborting due to 9 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0053, E0308.
 For more information about an error, try `rustc --explain E0053`.
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
index 7f0e5472c3c2e..d74d3a2a52351 100644
--- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.rs
@@ -4,6 +4,7 @@
 //
 // No we expect to run into a more user-friendly cycle error instead.
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Trait<T> { type Assoc; }
 //~^ ERROR E0391
diff --git a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
index 71f997c54c6f2..7e140480b77d4 100644
--- a/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
+++ b/src/test/ui/coherence/coherence-inherited-assoc-ty-cycle-err.stderr
@@ -1,16 +1,25 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0391]: cycle detected when building specialization graph of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
    |
    = note: ...which again requires building specialization graph of trait `Trait`, completing the cycle
 note: cycle used when coherence checking all impls of trait `Trait`
-  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:8:1
+  --> $DIR/coherence-inherited-assoc-ty-cycle-err.rs:9:1
    |
 LL | trait Trait<T> { type Assoc; }
    | ^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0391`.
diff --git a/src/test/ui/consts/const_in_pattern/issue-73431.rs b/src/test/ui/consts/const_in_pattern/issue-73431.rs
new file mode 100644
index 0000000000000..fa18a3af1b09f
--- /dev/null
+++ b/src/test/ui/consts/const_in_pattern/issue-73431.rs
@@ -0,0 +1,29 @@
+// run-pass
+
+// Regression test for https://github.com/rust-lang/rust/issues/73431.
+
+pub trait Zero {
+    const ZERO: Self;
+}
+
+impl Zero for usize {
+    const ZERO: Self = 0;
+}
+
+impl<T: Zero> Zero for Wrapper<T> {
+    const ZERO: Self = Wrapper(T::ZERO);
+}
+
+#[derive(Debug, PartialEq, Eq)]
+pub struct Wrapper<T>(T);
+
+fn is_zero(x: Wrapper<usize>) -> bool {
+    match x {
+        Zero::ZERO => true,
+        _ => false,
+    }
+}
+
+fn main() {
+    let _ = is_zero(Wrapper(42));
+}
diff --git a/src/test/ui/consts/trait_specialization.rs b/src/test/ui/consts/trait_specialization.rs
index 8010d2fe1aee9..3adbbb5304634 100644
--- a/src/test/ui/consts/trait_specialization.rs
+++ b/src/test/ui/consts/trait_specialization.rs
@@ -5,7 +5,7 @@
 // Tests that specialization does not cause optimizations running on polymorphic MIR to resolve
 // to a `default` implementation.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Marker {}
 
diff --git a/src/test/ui/consts/trait_specialization.stderr b/src/test/ui/consts/trait_specialization.stderr
new file mode 100644
index 0000000000000..03da7d512e592
--- /dev/null
+++ b/src/test/ui/consts/trait_specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait_specialization.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/error-codes/E0520.rs b/src/test/ui/error-codes/E0520.rs
index b746ca63590ec..ead78b7ffa2c4 100644
--- a/src/test/ui/error-codes/E0520.rs
+++ b/src/test/ui/error-codes/E0520.rs
@@ -1,4 +1,5 @@
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait SpaceLlama {
     fn fly(&self);
diff --git a/src/test/ui/error-codes/E0520.stderr b/src/test/ui/error-codes/E0520.stderr
index 72fc85ab1e74b..1041ccee93704 100644
--- a/src/test/ui/error-codes/E0520.stderr
+++ b/src/test/ui/error-codes/E0520.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/E0520.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `fly` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/E0520.rs:16:5
+  --> $DIR/E0520.rs:17:5
    |
 LL | / impl<T: Clone> SpaceLlama for T {
 LL | |     fn fly(&self) {}
@@ -11,6 +20,6 @@ LL |       default fn fly(&self) {}
    |
    = note: to specialize, `fly` in the parent `impl` must be marked `default`
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/impl-trait/binding-without-value.rs b/src/test/ui/impl-trait/binding-without-value.rs
new file mode 100644
index 0000000000000..6a97f28ff552b
--- /dev/null
+++ b/src/test/ui/impl-trait/binding-without-value.rs
@@ -0,0 +1,9 @@
+#![allow(incomplete_features)]
+#![feature(impl_trait_in_bindings)]
+
+fn foo() {
+    let _ : impl Copy;
+    //~^ ERROR cannot resolve opaque type
+}
+
+fn main() {}
diff --git a/src/test/ui/impl-trait/binding-without-value.stderr b/src/test/ui/impl-trait/binding-without-value.stderr
new file mode 100644
index 0000000000000..0d2faeaf85d10
--- /dev/null
+++ b/src/test/ui/impl-trait/binding-without-value.stderr
@@ -0,0 +1,16 @@
+error[E0720]: cannot resolve opaque type
+  --> $DIR/binding-without-value.rs:5:13
+   |
+LL |     let _ : impl Copy;
+   |         -   ^^^^^^^^^ cannot resolve opaque type
+   |         |
+   |         this binding might not have a concrete type
+   |
+help: set the binding to a value for a concrete type to be resolved
+   |
+LL |     let _ : impl Copy = /* value */;
+   |                       ^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/src/test/ui/impl-trait/equality-rpass.rs b/src/test/ui/impl-trait/equality-rpass.rs
index 05c9e4173b0e4..607b4a49661cc 100644
--- a/src/test/ui/impl-trait/equality-rpass.rs
+++ b/src/test/ui/impl-trait/equality-rpass.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: std::fmt::Debug + Eq {}
 
diff --git a/src/test/ui/impl-trait/equality-rpass.stderr b/src/test/ui/impl-trait/equality-rpass.stderr
new file mode 100644
index 0000000000000..1abf05dca8270
--- /dev/null
+++ b/src/test/ui/impl-trait/equality-rpass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality-rpass.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/impl-trait/equality.rs b/src/test/ui/impl-trait/equality.rs
index 14b0eeb739ae5..828b5aac896be 100644
--- a/src/test/ui/impl-trait/equality.rs
+++ b/src/test/ui/impl-trait/equality.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: Copy + ToString {}
 
diff --git a/src/test/ui/impl-trait/equality.stderr b/src/test/ui/impl-trait/equality.stderr
index 9178358b60a9c..628dfb13d4ca8 100644
--- a/src/test/ui/impl-trait/equality.stderr
+++ b/src/test/ui/impl-trait/equality.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/equality.rs:15:5
    |
@@ -24,7 +33,7 @@ LL |         n + sum_to(n - 1)
    |
    = help: the trait `std::ops::Add<impl Foo>` is not implemented for `u32`
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0277, E0308.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/equality2.rs b/src/test/ui/impl-trait/equality2.rs
index abce8c8c204bd..2e325867da86e 100644
--- a/src/test/ui/impl-trait/equality2.rs
+++ b/src/test/ui/impl-trait/equality2.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo: Copy + ToString {}
 
diff --git a/src/test/ui/impl-trait/equality2.stderr b/src/test/ui/impl-trait/equality2.stderr
index 2454c218ffc8b..1780931efc541 100644
--- a/src/test/ui/impl-trait/equality2.stderr
+++ b/src/test/ui/impl-trait/equality2.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality2.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/equality2.rs:25:18
    |
@@ -58,6 +67,6 @@ LL |          x.0);
    = note: expected opaque type `impl Foo` (`i32`)
               found opaque type `impl Foo` (`u32`)
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
index 150a8015cbc75..451ddb3cce0e0 100644
--- a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.rs
@@ -5,13 +5,13 @@
 
 trait Quux {}
 
-fn foo() -> impl Quux { //~ opaque type expands to a recursive type
+fn foo() -> impl Quux { //~ ERROR cannot resolve opaque type
     struct Foo<T>(T);
     impl<T> Quux for Foo<T> {}
     Foo(bar())
 }
 
-fn bar() -> impl Quux { //~ opaque type expands to a recursive type
+fn bar() -> impl Quux { //~ ERROR cannot resolve opaque type
     struct Bar<T>(T);
     impl<T> Quux for Bar<T> {}
     Bar(foo())
diff --git a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
index d10001e8a8e53..c538b77098a2d 100644
--- a/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
+++ b/src/test/ui/impl-trait/issues/infinite-impl-trait-issue-38064.stderr
@@ -1,18 +1,26 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/infinite-impl-trait-issue-38064.rs:8:13
    |
 LL | fn foo() -> impl Quux {
-   |             ^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `foo::Foo<bar::Bar<impl Quux>>`
+   |             ^^^^^^^^^ recursive opaque type
+...
+LL |     Foo(bar())
+   |     ---------- returning here with type `foo::Foo<impl Quux>`
+...
+LL | fn bar() -> impl Quux {
+   |             --------- returning this opaque type `foo::Foo<impl Quux>`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/infinite-impl-trait-issue-38064.rs:14:13
    |
+LL | fn foo() -> impl Quux {
+   |             --------- returning this opaque type `bar::Bar<impl Quux>`
+...
 LL | fn bar() -> impl Quux {
-   |             ^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `bar::Bar<foo::Foo<impl Quux>>`
+   |             ^^^^^^^^^ recursive opaque type
+...
+LL |     Bar(foo())
+   |     ---------- returning here with type `bar::Bar<impl Quux>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
index 5a95e2969d1b0..5a3027ec751a9 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-direct.stderr
@@ -1,10 +1,11 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-direct.rs:5:14
    |
 LL | fn test() -> impl Sized {
-   |              ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |              ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     test()
+   |     ------ returning here with type `impl Sized`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
index 6573b00870c5b..75ff9e078cc2c 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-indirect.stderr
@@ -1,114 +1,147 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:7:22
    |
 LL | fn option(i: i32) -> impl Sized {
-   |                      ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `std::option::Option<(impl Sized, i32)>`
+   |                      ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     if i < 0 { None } else { Some((option(i - 1), i)) }
+   |                ----          ------------------------ returning here with type `std::option::Option<(impl Sized, i32)>`
+   |                |
+   |                returning here with type `std::option::Option<(impl Sized, i32)>`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:12:15
    |
 LL | fn tuple() -> impl Sized {
-   |               ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `(impl Sized,)`
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (tuple(),)
+   |     ---------- returning here with type `(impl Sized,)`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:17:15
    |
 LL | fn array() -> impl Sized {
-   |               ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[impl Sized; 1]`
+   |               ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     [array()]
+   |     --------- returning here with type `[impl Sized; 1]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:22:13
    |
 LL | fn ptr() -> impl Sized {
-   |             ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `*const impl Sized`
+   |             ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     &ptr() as *const _
+   |     ------------------ returning here with type `*const impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:27:16
    |
 LL | fn fn_ptr() -> impl Sized {
-   |                ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `fn() -> impl Sized`
+   |                ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     fn_ptr as fn() -> _
+   |     ------------------- returning here with type `fn() -> impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:32:25
    |
-LL | fn closure_capture() -> impl Sized {
-   |                         ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
+LL |   fn closure_capture() -> impl Sized {
+   |                           ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:35:5: 37:6 x:impl Sized]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:40:29
    |
-LL | fn closure_ref_capture() -> impl Sized {
-   |                             ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
+LL |   fn closure_ref_capture() -> impl Sized {
+   |                               ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         &x;
+LL | |     }
+   | |_____- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:43:5: 45:6 x:impl Sized]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:48:21
    |
 LL | fn closure_sig() -> impl Sized {
-   |                     ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
+   |                     ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || closure_sig()
+   |     ---------------- returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:50:5: 50:21]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:53:23
    |
 LL | fn generator_sig() -> impl Sized {
-   |                       ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
+   |                       ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     || generator_sig()
+   |     ------------------ returning here with type `[closure@$DIR/recursive-impl-trait-type-indirect.rs:55:5: 55:23]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:58:27
    |
-LL | fn generator_capture() -> impl Sized {
-   |                           ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
+LL |   fn generator_capture() -> impl Sized {
+   |                             ^^^^^^^^^^ recursive opaque type
+...
+LL | /     move || {
+LL | |         yield;
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:61:5: 64:6 x:impl Sized {()}]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:67:35
    |
 LL | fn substs_change<T: 'static>() -> impl Sized {
-   |                                   ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `(impl Sized,)`
+   |                                   ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     (substs_change::<&T>(),)
+   |     ------------------------ returning here with type `(impl Sized,)`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:72:24
    |
-LL | fn generator_hold() -> impl Sized {
-   |                        ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
+LL |   fn generator_hold() -> impl Sized {
+   |                          ^^^^^^^^^^ recursive opaque type
+LL |
+LL | /     move || {
+LL | |         let x = generator_hold();
+LL | |         yield;
+LL | |         x;
+LL | |     }
+   | |_____- returning here with type `[generator@$DIR/recursive-impl-trait-type-indirect.rs:74:5: 78:6 {impl Sized, ()}]`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:86:26
    |
 LL | fn mutual_recursion() -> impl Sync {
-   |                          ^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                          ^^^^^^^^^ recursive opaque type
+LL |
+LL |     mutual_recursion_b()
+   |     -------------------- returning here with type `impl Sized`
+...
+LL | fn mutual_recursion_b() -> impl Sized {
+   |                            ---------- returning this opaque type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-indirect.rs:91:28
    |
+LL | fn mutual_recursion() -> impl Sync {
+   |                          --------- returning this opaque type `impl std::marker::Sync`
+...
 LL | fn mutual_recursion_b() -> impl Sized {
-   |                            ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                            ^^^^^^^^^^ recursive opaque type
+LL |
+LL |     mutual_recursion()
+   |     ------------------ returning here with type `impl std::marker::Sync`
 
 error: aborting due to 14 previous errors
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
index cfd9c0ec5b45b..818e40365394d 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.rs
@@ -4,21 +4,21 @@
 
 fn id<T>(t: T) -> impl Sized { t }
 
-fn recursive_id() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_id() -> impl Sized { //~ ERROR cannot resolve opaque type
     id(recursive_id2())
 }
 
-fn recursive_id2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_id2() -> impl Sized { //~ ERROR cannot resolve opaque type
     id(recursive_id())
 }
 
 fn wrap<T>(t: T) -> impl Sized { (t,) }
 
-fn recursive_wrap() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_wrap() -> impl Sized { //~ ERROR cannot resolve opaque type
     wrap(recursive_wrap2())
 }
 
-fn recursive_wrap2() -> impl Sized { //~ ERROR opaque type expands to a recursive type
+fn recursive_wrap2() -> impl Sized { //~ ERROR cannot resolve opaque type
     wrap(recursive_wrap())
 }
 
diff --git a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
index 73c12f6137d24..fbc58837a8e94 100644
--- a/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
+++ b/src/test/ui/impl-trait/recursive-impl-trait-type-through-non-recursive.stderr
@@ -1,34 +1,46 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:7:22
    |
+LL | fn id<T>(t: T) -> impl Sized { t }
+   |                   ---------- returning this opaque type `impl Sized`
+LL | 
 LL | fn recursive_id() -> impl Sized {
-   |                      ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                      ^^^^^^^^^^ recursive opaque type
+LL |     id(recursive_id2())
+   |     ------------------- returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:11:23
    |
+LL | fn id<T>(t: T) -> impl Sized { t }
+   |                   ---------- returning this opaque type `impl Sized`
+...
 LL | fn recursive_id2() -> impl Sized {
-   |                       ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: type resolves to itself
+   |                       ^^^^^^^^^^ recursive opaque type
+LL |     id(recursive_id())
+   |     ------------------ returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:17:24
    |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+   |                     ---------- returning this opaque type `impl Sized`
+LL | 
 LL | fn recursive_wrap() -> impl Sized {
-   |                        ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `((impl Sized,),)`
+   |                        ^^^^^^^^^^ recursive opaque type
+LL |     wrap(recursive_wrap2())
+   |     ----------------------- returning here with type `impl Sized`
 
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/recursive-impl-trait-type-through-non-recursive.rs:21:25
    |
+LL | fn wrap<T>(t: T) -> impl Sized { (t,) }
+   |                     ---------- returning this opaque type `impl Sized`
+...
 LL | fn recursive_wrap2() -> impl Sized {
-   |                         ^^^^^^^^^^ expands to a recursive type
-   |
-   = note: expanded type is `((impl Sized,),)`
+   |                         ^^^^^^^^^^ recursive opaque type
+LL |     wrap(recursive_wrap())
+   |     ---------------------- returning here with type `impl Sized`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/impl-trait/where-allowed-2.rs b/src/test/ui/impl-trait/where-allowed-2.rs
index f7744ef1b3eae..462508f306ef3 100644
--- a/src/test/ui/impl-trait/where-allowed-2.rs
+++ b/src/test/ui/impl-trait/where-allowed-2.rs
@@ -3,7 +3,6 @@
 use std::fmt::Debug;
 
 // Disallowed
-fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-//~^ ERROR opaque type expands to a recursive type
+fn in_adt_in_return() -> Vec<impl Debug> { panic!() } //~ ERROR cannot resolve opaque type
 
 fn main() {}
diff --git a/src/test/ui/impl-trait/where-allowed-2.stderr b/src/test/ui/impl-trait/where-allowed-2.stderr
index 1de15014c1f8d..b8e06725cbcdd 100644
--- a/src/test/ui/impl-trait/where-allowed-2.stderr
+++ b/src/test/ui/impl-trait/where-allowed-2.stderr
@@ -1,10 +1,12 @@
-error[E0720]: opaque type expands to a recursive type
+error[E0720]: cannot resolve opaque type
   --> $DIR/where-allowed-2.rs:6:30
    |
 LL | fn in_adt_in_return() -> Vec<impl Debug> { panic!() }
-   |                              ^^^^^^^^^^ expands to a recursive type
+   |                              ^^^^^^^^^^    -------- this returned value is of `!` type
+   |                              |
+   |                              cannot resolve opaque type
    |
-   = note: type resolves to itself
+   = help: this error will resolve once the item's body returns a concrete type
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-35376.rs b/src/test/ui/issues/issue-35376.rs
index eb139ec4d7f43..cc35213b93d68 100644
--- a/src/test/ui/issues/issue-35376.rs
+++ b/src/test/ui/issues/issue-35376.rs
@@ -1,5 +1,6 @@
 // check-pass
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/issues/issue-35376.stderr b/src/test/ui/issues/issue-35376.stderr
new file mode 100644
index 0000000000000..06c31f3bae062
--- /dev/null
+++ b/src/test/ui/issues/issue-35376.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-35376.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-38091.rs b/src/test/ui/issues/issue-38091.rs
index 00aa810f8308c..c126243050244 100644
--- a/src/test/ui/issues/issue-38091.rs
+++ b/src/test/ui/issues/issue-38091.rs
@@ -1,5 +1,6 @@
 // run-pass
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Iterate<'a> {
     type Ty: Valid;
diff --git a/src/test/ui/issues/issue-38091.stderr b/src/test/ui/issues/issue-38091.stderr
new file mode 100644
index 0000000000000..a9855445f6668
--- /dev/null
+++ b/src/test/ui/issues/issue-38091.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-38091.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-55380.rs b/src/test/ui/issues/issue-55380.rs
index 862218e219279..f7cb296d3b8bb 100644
--- a/src/test/ui/issues/issue-55380.rs
+++ b/src/test/ui/issues/issue-55380.rs
@@ -1,6 +1,6 @@
 // run-pass
-
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn abc() -> u32;
diff --git a/src/test/ui/issues/issue-55380.stderr b/src/test/ui/issues/issue-55380.stderr
new file mode 100644
index 0000000000000..451beebd1061e
--- /dev/null
+++ b/src/test/ui/issues/issue-55380.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-55380.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
index dd09d68367ec3..1e413120a3717 100644
--- a/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
+++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 #![feature(marker_trait_attr)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 #[marker]
 trait MyMarker {}
diff --git a/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
new file mode 100644
index 0000000000000..16df31ba2a88b
--- /dev/null
+++ b/src/test/ui/overlap-doesnt-conflict-with-specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-doesnt-conflict-with-specialization.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.rs b/src/test/ui/parser/assoc-static-semantic-fail.rs
index 215a292131521..a8759d2090d0f 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.rs
+++ b/src/test/ui/parser/assoc-static-semantic-fail.rs
@@ -1,6 +1,7 @@
 // Semantically, we do not allow e.g., `static X: u8 = 0;` as an associated item.
 
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/parser/assoc-static-semantic-fail.stderr b/src/test/ui/parser/assoc-static-semantic-fail.stderr
index 612297c9cd8b1..bc3054c3e3062 100644
--- a/src/test/ui/parser/assoc-static-semantic-fail.stderr
+++ b/src/test/ui/parser/assoc-static-semantic-fail.stderr
@@ -1,17 +1,17 @@
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:9:5
+  --> $DIR/assoc-static-semantic-fail.rs:10:5
    |
 LL |     static IA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:11:5
+  --> $DIR/assoc-static-semantic-fail.rs:12:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:14:5
+  --> $DIR/assoc-static-semantic-fail.rs:15:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -19,13 +19,13 @@ LL |     default static IC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:14:5
+  --> $DIR/assoc-static-semantic-fail.rs:15:5
    |
 LL |     default static IC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:17:16
+  --> $DIR/assoc-static-semantic-fail.rs:18:16
    |
 LL |     pub(crate) default static ID: u8;
    |                ^^^^^^^ `default` because of this
@@ -33,25 +33,25 @@ LL |     pub(crate) default static ID: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:17:5
+  --> $DIR/assoc-static-semantic-fail.rs:18:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:24:5
+  --> $DIR/assoc-static-semantic-fail.rs:25:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:26:5
+  --> $DIR/assoc-static-semantic-fail.rs:27:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:28:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -59,13 +59,13 @@ LL |     default static TC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:28:5
+  --> $DIR/assoc-static-semantic-fail.rs:29:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:31:16
+  --> $DIR/assoc-static-semantic-fail.rs:32:16
    |
 LL |     pub(crate) default static TD: u8;
    |                ^^^^^^^ `default` because of this
@@ -73,25 +73,25 @@ LL |     pub(crate) default static TD: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:31:5
+  --> $DIR/assoc-static-semantic-fail.rs:32:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:38:5
+  --> $DIR/assoc-static-semantic-fail.rs:39:5
    |
 LL |     static TA: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:41:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:44:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^ `default` because of this
@@ -99,13 +99,13 @@ LL |     default static TC: u8 = 0;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:43:5
+  --> $DIR/assoc-static-semantic-fail.rs:44:5
    |
 LL |     default static TC: u8 = 0;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: a static item cannot be `default`
-  --> $DIR/assoc-static-semantic-fail.rs:46:9
+  --> $DIR/assoc-static-semantic-fail.rs:47:9
    |
 LL |     pub default static TD: u8;
    |         ^^^^^^^ `default` because of this
@@ -113,13 +113,13 @@ LL |     pub default static TD: u8;
    = note: only associated `fn`, `const`, and `type` items can be `default`
 
 error: associated `static` items are not allowed
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:11:5
+  --> $DIR/assoc-static-semantic-fail.rs:12:5
    |
 LL |     static IB: u8;
    |     ^^^^^^^^^^^^^-
@@ -127,7 +127,7 @@ LL |     static IB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:17:5
+  --> $DIR/assoc-static-semantic-fail.rs:18:5
    |
 LL |     pub(crate) default static ID: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -135,13 +135,13 @@ LL |     pub(crate) default static ID: u8;
    |                                     help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:31:5
+  --> $DIR/assoc-static-semantic-fail.rs:32:5
    |
 LL |     pub(crate) default static TD: u8;
    |     ^^^^^^^^^^
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:40:5
+  --> $DIR/assoc-static-semantic-fail.rs:41:5
    |
 LL |     static TB: u8;
    |     ^^^^^^^^^^^^^-
@@ -149,7 +149,7 @@ LL |     static TB: u8;
    |                  help: provide a definition for the constant: `= <expr>;`
 
 error: associated constant in `impl` without body
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^-
@@ -157,11 +157,20 @@ LL |     pub default static TD: u8;
    |                              help: provide a definition for the constant: `= <expr>;`
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/assoc-static-semantic-fail.rs:46:5
+  --> $DIR/assoc-static-semantic-fail.rs:47:5
    |
 LL |     pub default static TD: u8;
    |     ^^^ `pub` not permitted here because it's implied
 
-error: aborting due to 24 previous errors
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/assoc-static-semantic-fail.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error: aborting due to 24 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0449`.
diff --git a/src/test/ui/parser/default.rs b/src/test/ui/parser/default.rs
index 64ba4b5531184..52338c1f13aad 100644
--- a/src/test/ui/parser/default.rs
+++ b/src/test/ui/parser/default.rs
@@ -1,6 +1,7 @@
 // Test successful and unsuccessful parsing of the `default` contextual keyword
 
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo<T: Default>() -> T;
diff --git a/src/test/ui/parser/default.stderr b/src/test/ui/parser/default.stderr
index 15c49e8b6270b..dea35666f37b5 100644
--- a/src/test/ui/parser/default.stderr
+++ b/src/test/ui/parser/default.stderr
@@ -1,5 +1,5 @@
 error: `default` is not followed by an item
-  --> $DIR/default.rs:22:5
+  --> $DIR/default.rs:23:5
    |
 LL |     default pub fn foo<T: Default>() -> T { T::default() }
    |     ^^^^^^^ the `default` qualifier
@@ -7,7 +7,7 @@ LL |     default pub fn foo<T: Default>() -> T { T::default() }
    = note: only `fn`, `const`, `type`, or `impl` items may be prefixed by `default`
 
 error: non-item in item list
-  --> $DIR/default.rs:22:13
+  --> $DIR/default.rs:23:13
    |
 LL | impl Foo for u32 {
    |                  - item list starts here
@@ -18,13 +18,22 @@ LL | }
    | - item list ends here
 
 error[E0449]: unnecessary visibility qualifier
-  --> $DIR/default.rs:16:5
+  --> $DIR/default.rs:17:5
    |
 LL |     pub default fn foo<T: Default>() -> T {
    |     ^^^ `pub` not permitted here because it's implied
 
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/default.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0046]: not all trait items implemented, missing: `foo`
-  --> $DIR/default.rs:21:1
+  --> $DIR/default.rs:22:1
    |
 LL |     fn foo<T: Default>() -> T;
    |     -------------------------- `foo` from trait
@@ -32,7 +41,7 @@ LL |     fn foo<T: Default>() -> T;
 LL | impl Foo for u32 {
    | ^^^^^^^^^^^^^^^^ missing `foo` in implementation
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 Some errors have detailed explanations: E0046, E0449.
 For more information about an error, try `rustc --explain E0046`.
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
index 09f967f161ede..34aee7f69359e 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
index 6bb946d5b6470..e8ff93f63237d 100644
--- a/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
+++ b/src/test/ui/parser/trait-item-with-defaultness-fail-semantic.stderr
@@ -46,5 +46,14 @@ LL |     default fn f2() {}
    |     |
    |     `default` because of this
 
-error: aborting due to 6 previous errors
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/trait-item-with-defaultness-fail-semantic.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+error: aborting due to 6 previous errors; 1 warning emitted
 
diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs
new file mode 100644
index 0000000000000..3fb1cf9f557b2
--- /dev/null
+++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.rs
@@ -0,0 +1,6 @@
+#![feature(non_ascii_idents)]
+
+extern crate ьаг; //~ ERROR cannot load a crate with a non-ascii name `ьаг`
+//~| ERROR can't find crate for `ьаг`
+
+fn main() {}
diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr
new file mode 100644
index 0000000000000..1e424237fd238
--- /dev/null
+++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-1.stderr
@@ -0,0 +1,15 @@
+error: cannot load a crate with a non-ascii name `ьаг`
+  --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1
+   |
+LL | extern crate ьаг;
+   | ^^^^^^^^^^^^^^^^^
+
+error[E0463]: can't find crate for `ьаг`
+  --> $DIR/crate_name_nonascii_forbidden-1.rs:3:1
+   |
+LL | extern crate ьаг;
+   | ^^^^^^^^^^^^^^^^^ can't find crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs
new file mode 100644
index 0000000000000..e1acdbff06189
--- /dev/null
+++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.rs
@@ -0,0 +1,9 @@
+// compile-flags:--extern му_сгате
+// edition:2018
+#![feature(non_ascii_idents)]
+
+use му_сгате::baz; //~  ERROR cannot load a crate with a non-ascii name `му_сгате`
+                   //~| can't find crate for `му_сгате`
+
+
+fn main() {}
diff --git a/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr
new file mode 100644
index 0000000000000..c06405ebb37ec
--- /dev/null
+++ b/src/test/ui/rfc-2457/crate_name_nonascii_forbidden-2.stderr
@@ -0,0 +1,15 @@
+error: cannot load a crate with a non-ascii name `му_сгате`
+  --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5
+   |
+LL | use му_сгате::baz;
+   |     ^^^^^^^^
+
+error[E0463]: can't find crate for `му_сгате`
+  --> $DIR/crate_name_nonascii_forbidden-2.rs:5:5
+   |
+LL | use му_сгате::baz;
+   |     ^^^^^^^^ can't find crate
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0463`.
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.rs b/src/test/ui/specialization/assoc-ty-graph-cycle.rs
index 54d51492ab349..fc39b553a61ac 100644
--- a/src/test/ui/specialization/assoc-ty-graph-cycle.rs
+++ b/src/test/ui/specialization/assoc-ty-graph-cycle.rs
@@ -2,7 +2,7 @@
 
 // Make sure we don't crash with a cycle error during coherence.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Trait<T> {
     type Assoc;
diff --git a/src/test/ui/specialization/assoc-ty-graph-cycle.stderr b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
new file mode 100644
index 0000000000000..250f48f8e5932
--- /dev/null
+++ b/src/test/ui/specialization/assoc-ty-graph-cycle.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/assoc-ty-graph-cycle.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/cross-crate-defaults.rs b/src/test/ui/specialization/cross-crate-defaults.rs
index 79cb659439721..fc28d0c815eb3 100644
--- a/src/test/ui/specialization/cross-crate-defaults.rs
+++ b/src/test/ui/specialization/cross-crate-defaults.rs
@@ -2,7 +2,7 @@
 
 // aux-build:cross_crates_defaults.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate cross_crates_defaults;
 
diff --git a/src/test/ui/specialization/cross-crate-defaults.stderr b/src/test/ui/specialization/cross-crate-defaults.stderr
new file mode 100644
index 0000000000000..f18bc99d73916
--- /dev/null
+++ b/src/test/ui/specialization/cross-crate-defaults.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/cross-crate-defaults.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
index 15550bcce2a8a..5d67160eb96ad 100644
--- a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
+++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 // aux-build:go_trait.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate go_trait;
 
diff --git a/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
new file mode 100644
index 0000000000000..1b50329719d01
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/allowed-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.rs b/src/test/ui/specialization/defaultimpl/out-of-order.rs
index f9c73a19cfa46..13258ac8c9fe6 100644
--- a/src/test/ui/specialization/defaultimpl/out-of-order.rs
+++ b/src/test/ui/specialization/defaultimpl/out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     type Out;
diff --git a/src/test/ui/specialization/defaultimpl/out-of-order.stderr b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
new file mode 100644
index 0000000000000..deae021a8914d
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/out-of-order.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.rs b/src/test/ui/specialization/defaultimpl/overlap-projection.rs
index ed38bb3fc3a12..0add4d5516c7b 100644
--- a/src/test/ui/specialization/defaultimpl/overlap-projection.rs
+++ b/src/test/ui/specialization/defaultimpl/overlap-projection.rs
@@ -4,7 +4,7 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Assoc {
     type Output;
diff --git a/src/test/ui/specialization/defaultimpl/overlap-projection.stderr b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
new file mode 100644
index 0000000000000..46899ca995490
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/overlap-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/projection.rs b/src/test/ui/specialization/defaultimpl/projection.rs
index 897a7aade2fe1..4a9140969324d 100644
--- a/src/test/ui/specialization/defaultimpl/projection.rs
+++ b/src/test/ui/specialization/defaultimpl/projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we *can* project non-defaulted associated types
 // cf compile-fail/specialization-default-projection.rs
diff --git a/src/test/ui/specialization/defaultimpl/projection.stderr b/src/test/ui/specialization/defaultimpl/projection.stderr
new file mode 100644
index 0000000000000..8629c6c52d4a7
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
index 37005f839d488..661724eef8a43 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
index 13636b28b126c..7958eddbeba25 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-no-default.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -65,6 +74,6 @@ LL |       fn redundant(&self) {}
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
index 2b8ca6bb1ddbb..89fef5b5ef969 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.rs
@@ -3,7 +3,7 @@
 // Tests that we can combine a default impl that supplies one method with a
 // full impl that supplies the other, and they can invoke one another.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
new file mode 100644
index 0000000000000..dc377dd10c868
--- /dev/null
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented-rpass.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented-rpass.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
index 2a121e61aaa97..3c5414469fac2 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.rs
@@ -1,6 +1,6 @@
 // Tests that default impls do not have to supply all items but regular impls do.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
index b862a937066d4..9d1eca1d6af76 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-item-not-implemented.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-item-not-implemented.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0046]: not all trait items implemented, missing: `foo_two`
   --> $DIR/specialization-trait-item-not-implemented.rs:18:1
    |
@@ -7,6 +16,6 @@ LL |     fn foo_two(&self) -> &'static str;
 LL | impl Foo for MyStruct {}
    | ^^^^^^^^^^^^^^^^^^^^^ missing `foo_two` in implementation
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0046`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
index 5c104449fe9c0..35e3b8725a82a 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.rs
@@ -2,7 +2,7 @@
 // - default impls do not have to supply all items and
 // - a default impl does not count as an impl (in this case, an incomplete default impl).
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo_one(&self) -> &'static str;
diff --git a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
index a55d79ee03534..6b8e559bc3634 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-trait-not-implemented.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-trait-not-implemented.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0599]: no method named `foo_one` found for struct `MyStruct` in the current scope
   --> $DIR/specialization-trait-not-implemented.rs:22:29
    |
@@ -19,6 +28,6 @@ note: `Foo` defines an item `foo_one`, perhaps you need to implement it
 LL | trait Foo {
    | ^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0599`.
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
index 232338d9d4d99..afd634725e365 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.rs
@@ -1,6 +1,6 @@
 // Tests that a default impl still has to have a WF trait ref.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo<'a, T: Eq + 'a> { }
 
diff --git a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
index f499c1f569859..d45825651a8e2 100644
--- a/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
+++ b/src/test/ui/specialization/defaultimpl/specialization-wfcheck.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-wfcheck.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0277]: the trait bound `U: std::cmp::Eq` is not satisfied
   --> $DIR/specialization-wfcheck.rs:7:17
    |
@@ -12,6 +21,6 @@ help: consider restricting type parameter `U`
 LL | default impl<U: std::cmp::Eq> Foo<'static, U> for () {}
    |               ^^^^^^^^^^^^^^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/specialization/defaultimpl/validation.rs b/src/test/ui/specialization/defaultimpl/validation.rs
index 8134333c58f73..8558a1efb82f3 100644
--- a/src/test/ui/specialization/defaultimpl/validation.rs
+++ b/src/test/ui/specialization/defaultimpl/validation.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 struct S;
 struct Z;
diff --git a/src/test/ui/specialization/defaultimpl/validation.stderr b/src/test/ui/specialization/defaultimpl/validation.stderr
index 254eaf51a646b..2449849725f38 100644
--- a/src/test/ui/specialization/defaultimpl/validation.stderr
+++ b/src/test/ui/specialization/defaultimpl/validation.stderr
@@ -8,6 +8,15 @@ LL | default impl S {}
    |
    = note: only trait implementations may be annotated with `default`
 
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/validation.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error: impls of auto traits cannot be default
   --> $DIR/validation.rs:9:21
    |
@@ -36,6 +45,6 @@ error[E0750]: negative impls cannot be default impls
 LL | default impl !Tr for S {}
    | ^^^^^^^      ^
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0750`.
diff --git a/src/test/ui/specialization/issue-36804.rs b/src/test/ui/specialization/issue-36804.rs
index 9546a5dd5f516..89350602f3652 100644
--- a/src/test/ui/specialization/issue-36804.rs
+++ b/src/test/ui/specialization/issue-36804.rs
@@ -1,5 +1,5 @@
 // check-pass
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 pub struct Cloned<I>(I);
 
diff --git a/src/test/ui/specialization/issue-36804.stderr b/src/test/ui/specialization/issue-36804.stderr
new file mode 100644
index 0000000000000..744d88204247b
--- /dev/null
+++ b/src/test/ui/specialization/issue-36804.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-36804.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-39448.rs b/src/test/ui/specialization/issue-39448.rs
index 8ac6d8e9311fc..9dd47a4a17e43 100644
--- a/src/test/ui/specialization/issue-39448.rs
+++ b/src/test/ui/specialization/issue-39448.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for a specialization-related ICE (#39448).
 
diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr
index 861a1d9e8fc66..f3bb69b8f712a 100644
--- a/src/test/ui/specialization/issue-39448.stderr
+++ b/src/test/ui/specialization/issue-39448.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39448.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0275]: overflow evaluating the requirement `T: FromA<U>`
   --> $DIR/issue-39448.rs:45:13
    |
@@ -7,6 +16,6 @@ LL |     x.foo(y.to()).to()
    = note: required because of the requirements on the impl of `FromA<U>` for `T`
    = note: required because of the requirements on the impl of `ToA<T>` for `U`
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/specialization/issue-39618.rs b/src/test/ui/specialization/issue-39618.rs
index 20e81e4359bac..72630ee9c7055 100644
--- a/src/test/ui/specialization/issue-39618.rs
+++ b/src/test/ui/specialization/issue-39618.rs
@@ -4,7 +4,7 @@
 
 // check-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn foo(&self);
diff --git a/src/test/ui/specialization/issue-39618.stderr b/src/test/ui/specialization/issue-39618.stderr
new file mode 100644
index 0000000000000..d40d17d8f71ca
--- /dev/null
+++ b/src/test/ui/specialization/issue-39618.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-39618.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-50452.rs b/src/test/ui/specialization/issue-50452.rs
index 93f081d955819..29fc12066e875 100644
--- a/src/test/ui/specialization/issue-50452.rs
+++ b/src/test/ui/specialization/issue-50452.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 pub trait Foo {
     fn foo();
diff --git a/src/test/ui/specialization/issue-50452.stderr b/src/test/ui/specialization/issue-50452.stderr
new file mode 100644
index 0000000000000..c01817e0b2793
--- /dev/null
+++ b/src/test/ui/specialization/issue-50452.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-50452.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-52050.rs b/src/test/ui/specialization/issue-52050.rs
index 1e1bfe9cf0755..8046587020661 100644
--- a/src/test/ui/specialization/issue-52050.rs
+++ b/src/test/ui/specialization/issue-52050.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for #52050: when inserting the blanket impl `I`
 // into the tree, we had to replace the child node for `Foo`, which
diff --git a/src/test/ui/specialization/issue-52050.stderr b/src/test/ui/specialization/issue-52050.stderr
index 36f96b011983f..a7564ced055d5 100644
--- a/src/test/ui/specialization/issue-52050.stderr
+++ b/src/test/ui/specialization/issue-52050.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-52050.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0119]: conflicting implementations of trait `IntoPyDictPointer` for type `()`:
   --> $DIR/issue-52050.rs:28:1
    |
@@ -13,6 +22,6 @@ LL |   impl IntoPyDictPointer for ()
    |
    = note: upstream crates may add a new impl of trait `std::iter::Iterator` for type `()` in future versions
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/issue-63716-parse-async.rs b/src/test/ui/specialization/issue-63716-parse-async.rs
index c3764ffaab83f..10f185c335144 100644
--- a/src/test/ui/specialization/issue-63716-parse-async.rs
+++ b/src/test/ui/specialization/issue-63716-parse-async.rs
@@ -4,7 +4,7 @@
 // check-pass
 // edition:2018
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 fn main() {}
 
diff --git a/src/test/ui/specialization/issue-63716-parse-async.stderr b/src/test/ui/specialization/issue-63716-parse-async.stderr
new file mode 100644
index 0000000000000..43620e1ba51e1
--- /dev/null
+++ b/src/test/ui/specialization/issue-63716-parse-async.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-63716-parse-async.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/issue-70442.rs b/src/test/ui/specialization/issue-70442.rs
index 4371dd2e16747..d41b5355c2cde 100644
--- a/src/test/ui/specialization/issue-70442.rs
+++ b/src/test/ui/specialization/issue-70442.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // check-pass
 
diff --git a/src/test/ui/specialization/issue-70442.stderr b/src/test/ui/specialization/issue-70442.stderr
new file mode 100644
index 0000000000000..f71e4c7dd1cef
--- /dev/null
+++ b/src/test/ui/specialization/issue-70442.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-70442.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/non-defaulted-item-fail.rs b/src/test/ui/specialization/non-defaulted-item-fail.rs
index 403f718d7dd9f..b7d6ac829dd14 100644
--- a/src/test/ui/specialization/non-defaulted-item-fail.rs
+++ b/src/test/ui/specialization/non-defaulted-item-fail.rs
@@ -1,4 +1,5 @@
 #![feature(specialization, associated_type_defaults)]
+//~^ WARN the feature `specialization` is incomplete
 
 // Test that attempting to override a non-default method or one not in the
 // parent impl causes an error.
diff --git a/src/test/ui/specialization/non-defaulted-item-fail.stderr b/src/test/ui/specialization/non-defaulted-item-fail.stderr
index e6c5fc1441b2f..eae045b92c04d 100644
--- a/src/test/ui/specialization/non-defaulted-item-fail.stderr
+++ b/src/test/ui/specialization/non-defaulted-item-fail.stderr
@@ -1,5 +1,14 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/non-defaulted-item-fail.rs:1:12
+   |
+LL | #![feature(specialization, associated_type_defaults)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:29:5
+  --> $DIR/non-defaulted-item-fail.rs:30:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -14,7 +23,7 @@ LL |       type Ty = Vec<()>;
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:31:5
+  --> $DIR/non-defaulted-item-fail.rs:32:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -29,7 +38,7 @@ LL |       const CONST: u8 = 42;
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:33:5
+  --> $DIR/non-defaulted-item-fail.rs:34:5
    |
 LL | / impl<T> Foo for Box<T> {
 LL | |     type Ty = bool;
@@ -44,7 +53,7 @@ LL |       fn foo(&self) -> bool { true }
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
 error[E0520]: `Ty` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:45:5
+  --> $DIR/non-defaulted-item-fail.rs:46:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -55,7 +64,7 @@ LL |     type Ty = Vec<()>;
    = note: to specialize, `Ty` in the parent `impl` must be marked `default`
 
 error[E0520]: `CONST` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:47:5
+  --> $DIR/non-defaulted-item-fail.rs:48:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -66,7 +75,7 @@ LL |     const CONST: u8 = 42;
    = note: to specialize, `CONST` in the parent `impl` must be marked `default`
 
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
-  --> $DIR/non-defaulted-item-fail.rs:49:5
+  --> $DIR/non-defaulted-item-fail.rs:50:5
    |
 LL | impl<T> Foo for Vec<T> {}
    | ------------------------- parent `impl` is here
@@ -76,6 +85,6 @@ LL |     fn foo(&self) -> bool { true }
    |
    = note: to specialize, `foo` in the parent `impl` must be marked `default`
 
-error: aborting due to 6 previous errors
+error: aborting due to 6 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.rs b/src/test/ui/specialization/specialization-allowed-cross-crate.rs
index 15550bcce2a8a..5d67160eb96ad 100644
--- a/src/test/ui/specialization/specialization-allowed-cross-crate.rs
+++ b/src/test/ui/specialization/specialization-allowed-cross-crate.rs
@@ -5,7 +5,7 @@
 
 // aux-build:go_trait.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate go_trait;
 
diff --git a/src/test/ui/specialization/specialization-allowed-cross-crate.stderr b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
new file mode 100644
index 0000000000000..7d087545725be
--- /dev/null
+++ b/src/test/ui/specialization/specialization-allowed-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-allowed-cross-crate.rs:8:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-assoc-fns.rs b/src/test/ui/specialization/specialization-assoc-fns.rs
index b6a7a48972ac2..cbfcb4719f6a4 100644
--- a/src/test/ui/specialization/specialization-assoc-fns.rs
+++ b/src/test/ui/specialization/specialization-assoc-fns.rs
@@ -2,7 +2,7 @@
 
 // Test that non-method associated functions can be specialized
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     fn mk() -> Self;
diff --git a/src/test/ui/specialization/specialization-assoc-fns.stderr b/src/test/ui/specialization/specialization-assoc-fns.stderr
new file mode 100644
index 0000000000000..b12738604ea83
--- /dev/null
+++ b/src/test/ui/specialization/specialization-assoc-fns.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-assoc-fns.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-basics.rs b/src/test/ui/specialization/specialization-basics.rs
index 6c359e51bc2e4..721c934dbfab9 100644
--- a/src/test/ui/specialization/specialization-basics.rs
+++ b/src/test/ui/specialization/specialization-basics.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Tests a variety of basic specialization scenarios and method
 // dispatch for them.
diff --git a/src/test/ui/specialization/specialization-basics.stderr b/src/test/ui/specialization/specialization-basics.stderr
new file mode 100644
index 0000000000000..ad00cd81df13c
--- /dev/null
+++ b/src/test/ui/specialization/specialization-basics.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-basics.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-cross-crate.rs b/src/test/ui/specialization/specialization-cross-crate.rs
index fa63c86632985..4171505aa374c 100644
--- a/src/test/ui/specialization/specialization-cross-crate.rs
+++ b/src/test/ui/specialization/specialization-cross-crate.rs
@@ -2,7 +2,7 @@
 
 // aux-build:specialization_cross_crate.rs
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 extern crate specialization_cross_crate;
 
diff --git a/src/test/ui/specialization/specialization-cross-crate.stderr b/src/test/ui/specialization/specialization-cross-crate.stderr
new file mode 100644
index 0000000000000..7481eed796d96
--- /dev/null
+++ b/src/test/ui/specialization/specialization-cross-crate.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-cross-crate.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-default-methods.rs b/src/test/ui/specialization/specialization-default-methods.rs
index 9ae3d1e9f3931..dcf68afa945bf 100644
--- a/src/test/ui/specialization/specialization-default-methods.rs
+++ b/src/test/ui/specialization/specialization-default-methods.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Test that default methods are cascaded correctly
 
diff --git a/src/test/ui/specialization/specialization-default-methods.stderr b/src/test/ui/specialization/specialization-default-methods.stderr
new file mode 100644
index 0000000000000..4fa19adad066e
--- /dev/null
+++ b/src/test/ui/specialization/specialization-default-methods.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-methods.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-default-projection.rs b/src/test/ui/specialization/specialization-default-projection.rs
index e9343f2360170..7f3ae951287ca 100644
--- a/src/test/ui/specialization/specialization-default-projection.rs
+++ b/src/test/ui/specialization/specialization-default-projection.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we can't project defaulted associated types
 
diff --git a/src/test/ui/specialization/specialization-default-projection.stderr b/src/test/ui/specialization/specialization-default-projection.stderr
index ac15ab0681a02..456eb6d5ca553 100644
--- a/src/test/ui/specialization/specialization-default-projection.stderr
+++ b/src/test/ui/specialization/specialization-default-projection.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-projection.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/specialization-default-projection.rs:21:5
    |
@@ -28,6 +37,6 @@ LL |     generic::<()>()
    = help: consider constraining the associated type `<() as Foo>::Assoc` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-default-types.rs b/src/test/ui/specialization/specialization-default-types.rs
index acb86d889d43c..346471f11e4a8 100644
--- a/src/test/ui/specialization/specialization-default-types.rs
+++ b/src/test/ui/specialization/specialization-default-types.rs
@@ -2,7 +2,7 @@
 // associated type in the impl defining it -- otherwise, what happens
 // if it's overridden?
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Example {
     type Output;
diff --git a/src/test/ui/specialization/specialization-default-types.stderr b/src/test/ui/specialization/specialization-default-types.stderr
index 7233387eba1fa..5e0221f07882e 100644
--- a/src/test/ui/specialization/specialization-default-types.stderr
+++ b/src/test/ui/specialization/specialization-default-types.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-default-types.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0308]: mismatched types
   --> $DIR/specialization-default-types.rs:15:9
    |
@@ -24,6 +33,6 @@ LL |     Example::generate(t)
    = help: consider constraining the associated type `<T as Example>::Output` to `std::boxed::Box<T>`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/specialization/specialization-no-default.rs b/src/test/ui/specialization/specialization-no-default.rs
index 57346b26d24ec..ae739b2358d58 100644
--- a/src/test/ui/specialization/specialization-no-default.rs
+++ b/src/test/ui/specialization/specialization-no-default.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Check a number of scenarios in which one impl tries to override another,
 // without correctly using `default`.
diff --git a/src/test/ui/specialization/specialization-no-default.stderr b/src/test/ui/specialization/specialization-no-default.stderr
index 992e9abbd4ce2..bb8b2a6c98e09 100644
--- a/src/test/ui/specialization/specialization-no-default.stderr
+++ b/src/test/ui/specialization/specialization-no-default.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-no-default.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
   --> $DIR/specialization-no-default.rs:20:5
    |
@@ -65,6 +74,6 @@ LL |       default fn redundant(&self) {}
    |
    = note: to specialize, `redundant` in the parent `impl` must be marked `default`
 
-error: aborting due to 5 previous errors
+error: aborting due to 5 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0520`.
diff --git a/src/test/ui/specialization/specialization-on-projection.rs b/src/test/ui/specialization/specialization-on-projection.rs
index 5606eaea3073d..be8dcc4232e7b 100644
--- a/src/test/ui/specialization/specialization-on-projection.rs
+++ b/src/test/ui/specialization/specialization-on-projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Ensure that specialization works for impls defined directly on a projection
 
diff --git a/src/test/ui/specialization/specialization-on-projection.stderr b/src/test/ui/specialization/specialization-on-projection.stderr
new file mode 100644
index 0000000000000..d91668d10c5f3
--- /dev/null
+++ b/src/test/ui/specialization/specialization-on-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-on-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-out-of-order.rs b/src/test/ui/specialization/specialization-out-of-order.rs
index 94e764f76366e..cb7563e2760c2 100644
--- a/src/test/ui/specialization/specialization-out-of-order.rs
+++ b/src/test/ui/specialization/specialization-out-of-order.rs
@@ -2,7 +2,7 @@
 
 // Test that you can list the more specific impl before the more general one.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo {
     type Out;
diff --git a/src/test/ui/specialization/specialization-out-of-order.stderr b/src/test/ui/specialization/specialization-out-of-order.stderr
new file mode 100644
index 0000000000000..a17f9f11a3f31
--- /dev/null
+++ b/src/test/ui/specialization/specialization-out-of-order.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-out-of-order.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-overlap-negative.rs b/src/test/ui/specialization/specialization-overlap-negative.rs
index 90dbef3075b7f..550d370829539 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.rs
+++ b/src/test/ui/specialization/specialization-overlap-negative.rs
@@ -1,5 +1,5 @@
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait MyTrait {}
 
diff --git a/src/test/ui/specialization/specialization-overlap-negative.stderr b/src/test/ui/specialization/specialization-overlap-negative.stderr
index e2616534d2041..6141174ba8c03 100644
--- a/src/test/ui/specialization/specialization-overlap-negative.stderr
+++ b/src/test/ui/specialization/specialization-overlap-negative.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-negative.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `std::marker::Send` for type `TestType<_>`:
   --> $DIR/specialization-overlap-negative.rs:9:1
    |
@@ -6,6 +15,6 @@ LL | unsafe impl<T: Clone> Send for TestType<T> {}
 LL | impl<T: MyTrait> !Send for TestType<T> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/specialization/specialization-overlap-projection.rs b/src/test/ui/specialization/specialization-overlap-projection.rs
index 00b83c7e7a1b8..b07efb2a5c1cd 100644
--- a/src/test/ui/specialization/specialization-overlap-projection.rs
+++ b/src/test/ui/specialization/specialization-overlap-projection.rs
@@ -4,7 +4,7 @@
 // projections involve specialization, so long as the associated type is
 // provided by the most specialized impl.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Assoc {
     type Output;
diff --git a/src/test/ui/specialization/specialization-overlap-projection.stderr b/src/test/ui/specialization/specialization-overlap-projection.stderr
new file mode 100644
index 0000000000000..6f1a594bacb3a
--- /dev/null
+++ b/src/test/ui/specialization/specialization-overlap-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap-projection.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-overlap.rs b/src/test/ui/specialization/specialization-overlap.rs
index c8ef8d61c1e8f..6bee22ceb8b64 100644
--- a/src/test/ui/specialization/specialization-overlap.rs
+++ b/src/test/ui/specialization/specialization-overlap.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Foo { fn foo() {} }
 impl<T: Clone> Foo for T {}
diff --git a/src/test/ui/specialization/specialization-overlap.stderr b/src/test/ui/specialization/specialization-overlap.stderr
index 4275e7bdd85e2..cf0f186a18337 100644
--- a/src/test/ui/specialization/specialization-overlap.stderr
+++ b/src/test/ui/specialization/specialization-overlap.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-overlap.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0119]: conflicting implementations of trait `Foo` for type `std::vec::Vec<_>`:
   --> $DIR/specialization-overlap.rs:5:1
    |
@@ -30,6 +39,6 @@ LL | impl<T: Clone> Qux for T {}
 LL | impl<T: Eq> Qux for T {}
    | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
-error: aborting due to 4 previous errors
+error: aborting due to 4 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0119`.
diff --git a/src/test/ui/specialization/specialization-polarity.rs b/src/test/ui/specialization/specialization-polarity.rs
index e78035f171075..17897d8b803d9 100644
--- a/src/test/ui/specialization/specialization-polarity.rs
+++ b/src/test/ui/specialization/specialization-polarity.rs
@@ -2,7 +2,7 @@
 
 #![feature(optin_builtin_traits)]
 #![feature(negative_impls)]
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 auto trait Foo {}
 
diff --git a/src/test/ui/specialization/specialization-polarity.stderr b/src/test/ui/specialization/specialization-polarity.stderr
index 44e60cad67aa4..c44af22b8e63b 100644
--- a/src/test/ui/specialization/specialization-polarity.stderr
+++ b/src/test/ui/specialization/specialization-polarity.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-polarity.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `Foo` for type `u8`:
   --> $DIR/specialization-polarity.rs:10:1
    |
@@ -14,6 +23,6 @@ LL | impl<T> !Bar for T {}
 LL | impl Bar for u8 {}
    | ^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to 2 previous errors
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/specialization/specialization-projection-alias.rs b/src/test/ui/specialization/specialization-projection-alias.rs
index 0081ed455c960..f1f0b47bb6503 100644
--- a/src/test/ui/specialization/specialization-projection-alias.rs
+++ b/src/test/ui/specialization/specialization-projection-alias.rs
@@ -2,7 +2,7 @@
 #![allow(dead_code)]
 #![allow(unused_variables)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Regression test for ICE when combining specialized associated types and type
 // aliases
diff --git a/src/test/ui/specialization/specialization-projection-alias.stderr b/src/test/ui/specialization/specialization-projection-alias.stderr
new file mode 100644
index 0000000000000..0c3659a8f7a06
--- /dev/null
+++ b/src/test/ui/specialization/specialization-projection-alias.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection-alias.rs:5:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-projection.rs b/src/test/ui/specialization/specialization-projection.rs
index 86cdccf131e22..700975e3b828f 100644
--- a/src/test/ui/specialization/specialization-projection.rs
+++ b/src/test/ui/specialization/specialization-projection.rs
@@ -1,7 +1,7 @@
 // run-pass
 #![allow(dead_code)]
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Make sure we *can* project non-defaulted associated types
 // cf compile-fail/specialization-default-projection.rs
diff --git a/src/test/ui/specialization/specialization-projection.stderr b/src/test/ui/specialization/specialization-projection.stderr
new file mode 100644
index 0000000000000..c5c86f5108e6e
--- /dev/null
+++ b/src/test/ui/specialization/specialization-projection.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-projection.rs:4:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-super-traits.rs b/src/test/ui/specialization/specialization-super-traits.rs
index a0f71d876931e..fb85d8019218a 100644
--- a/src/test/ui/specialization/specialization-super-traits.rs
+++ b/src/test/ui/specialization/specialization-super-traits.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 // Test that you can specialize via an explicit trait hierarchy
 
diff --git a/src/test/ui/specialization/specialization-super-traits.stderr b/src/test/ui/specialization/specialization-super-traits.stderr
new file mode 100644
index 0000000000000..05bdfd40136a4
--- /dev/null
+++ b/src/test/ui/specialization/specialization-super-traits.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-super-traits.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
index 2e32e3ff02d3e..5c2781a9c63a6 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Iterator {
     fn next(&self);
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
new file mode 100644
index 0000000000000..6284dd8f3f7d7
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections-with-lifetimes.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-lifetimes.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.rs b/src/test/ui/specialization/specialization-translate-projections-with-params.rs
index bdc6501df44b8..62d63590a6688 100644
--- a/src/test/ui/specialization/specialization-translate-projections-with-params.rs
+++ b/src/test/ui/specialization/specialization-translate-projections-with-params.rs
@@ -4,7 +4,7 @@
 // type parameters *and* rely on projections, and the type parameters are input
 // types on the trait.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Trait<T> {
     fn convert(&self) -> T;
diff --git a/src/test/ui/specialization/specialization-translate-projections-with-params.stderr b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
new file mode 100644
index 0000000000000..b17794173c570
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections-with-params.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections-with-params.rs:7:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/specialization/specialization-translate-projections.rs b/src/test/ui/specialization/specialization-translate-projections.rs
index fcccb67902e58..92ea9e2b85d32 100644
--- a/src/test/ui/specialization/specialization-translate-projections.rs
+++ b/src/test/ui/specialization/specialization-translate-projections.rs
@@ -3,7 +3,7 @@
 // Ensure that provided items are inherited properly even when impls vary in
 // type parameters *and* rely on projections.
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 use std::convert::Into;
 
diff --git a/src/test/ui/specialization/specialization-translate-projections.stderr b/src/test/ui/specialization/specialization-translate-projections.stderr
new file mode 100644
index 0000000000000..fbb28e6064088
--- /dev/null
+++ b/src/test/ui/specialization/specialization-translate-projections.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/specialization-translate-projections.rs:6:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.rs b/src/test/ui/traits/negative-impls/negative-default-impls.rs
index 2d50bc83ec304..c68bca432fa86 100644
--- a/src/test/ui/traits/negative-impls/negative-default-impls.rs
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.rs
@@ -1,5 +1,6 @@
 #![feature(negative_impls)]
 #![feature(specialization)]
+//~^ WARN the feature `specialization` is incomplete
 
 trait MyTrait {
     type Foo;
diff --git a/src/test/ui/traits/negative-impls/negative-default-impls.stderr b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
index a70bbe6b948d1..50e74373b53bb 100644
--- a/src/test/ui/traits/negative-impls/negative-default-impls.stderr
+++ b/src/test/ui/traits/negative-impls/negative-default-impls.stderr
@@ -1,9 +1,18 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-default-impls.rs:2:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0750]: negative impls cannot be default impls
-  --> $DIR/negative-default-impls.rs:8:1
+  --> $DIR/negative-default-impls.rs:9:1
    |
 LL | default impl !MyTrait for u32 {}
    | ^^^^^^^      ^
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0750`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
index 877c3e8af4f1a..35297ab124ed0 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Test a negative impl that "specializes" another negative impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
new file mode 100644
index 0000000000000..8b536de378630
--- /dev/null
+++ b/src/test/ui/traits/negative-impls/negative-specializes-negative.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-negative.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
index da22e43377f52..4281eedaf631c 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
index 079546a7df40b..89ef15e89ac96 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive-item.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-positive-item.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive-item.rs:11:1
    |
@@ -7,6 +16,6 @@ LL | impl<T> MyTrait for T {
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
index 1939a098b50ee..0e227691e0404 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 // Negative impl for u32 cannot "specialize" the base impl.
diff --git a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
index ea005c1cbe0c6..e45d5a251ab26 100644
--- a/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
+++ b/src/test/ui/traits/negative-impls/negative-specializes-positive.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/negative-specializes-positive.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/negative-specializes-positive.rs:7:1
    |
@@ -6,6 +15,6 @@ LL | impl<T> MyTrait for T {}
 LL | impl !MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^^ negative implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
index f2c5f507a4ebb..a06b357654068 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.rs
@@ -1,4 +1,4 @@
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 #![feature(negative_impls)]
 
 trait MyTrait {}
diff --git a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
index a24d7aa442f4a..49c16d474040e 100644
--- a/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
+++ b/src/test/ui/traits/negative-impls/positive-specializes-negative.stderr
@@ -1,3 +1,12 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/positive-specializes-negative.rs:1:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
 error[E0751]: found both positive and negative implementation of trait `MyTrait` for type `u32`:
   --> $DIR/positive-specializes-negative.rs:7:1
    |
@@ -6,6 +15,6 @@ LL | impl<T> !MyTrait for T {}
 LL | impl MyTrait for u32 {}
    | ^^^^^^^^^^^^^^^^^^^^ positive implementation here
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0751`.
diff --git a/src/test/ui/transmute-specialization.rs b/src/test/ui/transmute-specialization.rs
index 002fba9ce8101..499334d983b1f 100644
--- a/src/test/ui/transmute-specialization.rs
+++ b/src/test/ui/transmute-specialization.rs
@@ -1,6 +1,6 @@
 // run-pass
 
-#![feature(specialization)]
+#![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
 trait Specializable { type Output; }
 
diff --git a/src/test/ui/transmute-specialization.stderr b/src/test/ui/transmute-specialization.stderr
new file mode 100644
index 0000000000000..02315051d30ec
--- /dev/null
+++ b/src/test/ui/transmute-specialization.stderr
@@ -0,0 +1,11 @@
+warning: the feature `specialization` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/transmute-specialization.rs:3:12
+   |
+LL | #![feature(specialization)]
+   |            ^^^^^^^^^^^^^^
+   |
+   = note: `#[warn(incomplete_features)]` on by default
+   = note: see issue #31844 <https://github.com/rust-lang/rust/issues/31844> for more information
+
+warning: 1 warning emitted
+