about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2019-04-04 02:31:46 +0000
committerbors <bors@rust-lang.org>2019-04-04 02:31:46 +0000
commita5dfdc589a1b44f01cb640cd0244372dcbbd6f37 (patch)
tree2e64cd0111d47ed14ffdfbde912e5a746ac8b454 /src
parent314a79cd80ed905f80d24b79fd7acb4c8c72789b (diff)
parent231bd482c6d2f2aae463f2d5b57ed3c8f5a0803e (diff)
downloadrust-a5dfdc589a1b44f01cb640cd0244372dcbbd6f37.tar.gz
rust-a5dfdc589a1b44f01cb640cd0244372dcbbd6f37.zip
Auto merge of #59684 - Centril:rollup-n7pnare, r=Centril
Rollup of 6 pull requests

Successful merges:

 - #59316 (Internal lints take 2)
 - #59663 (Be more direct about borrow contract)
 - #59664 (Updated the documentation of spin_loop and spin_loop_hint)
 - #59666 (Updated the environment description in rustc.)
 - #59669 (Reduce repetition in librustc(_lint) wrt. impl LintPass by using macros)
 - #59677 (rustfix coverage: Skip UI tests with non-json error-format)

Failed merges:

r? @ghost
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/bin/rustc.rs5
-rw-r--r--src/doc/man/rustc.14
-rw-r--r--src/libarena/lib.rs1
-rw-r--r--src/libcore/borrow.rs4
-rw-r--r--src/libcore/convert.rs10
-rw-r--r--src/libcore/hint.rs27
-rw-r--r--src/libcore/sync/atomic.rs27
-rw-r--r--src/libfmt_macros/lib.rs1
-rw-r--r--src/librustc/hir/def_id.rs107
-rw-r--r--src/librustc/ich/hcx.rs8
-rw-r--r--src/librustc/infer/error_reporting/mod.rs22
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc/lint/builtin.rs141
-rw-r--r--src/librustc/lint/internal.rs127
-rw-r--r--src/librustc/lint/mod.rs22
-rw-r--r--src/librustc/mir/tcx.rs2
-rw-r--r--src/librustc/ty/context.rs7
-rw-r--r--src/librustc/ty/mod.rs2
-rw-r--r--src/librustc/util/common.rs9
-rw-r--r--src/librustc_allocator/lib.rs1
-rw-r--r--src/librustc_borrowck/lib.rs1
-rw-r--r--src/librustc_codegen_ssa/lib.rs1
-rw-r--r--src/librustc_codegen_utils/lib.rs1
-rw-r--r--src/librustc_driver/lib.rs1
-rw-r--r--src/librustc_errors/lib.rs1
-rw-r--r--src/librustc_incremental/lib.rs1
-rw-r--r--src/librustc_interface/interface.rs1
-rw-r--r--src/librustc_interface/lib.rs1
-rw-r--r--src/librustc_interface/util.rs4
-rw-r--r--src/librustc_lint/builtin.rs401
-rw-r--r--src/librustc_lint/lib.rs17
-rw-r--r--src/librustc_lint/nonstandard_style.rs41
-rw-r--r--src/librustc_lint/types.rs66
-rw-r--r--src/librustc_lint/unused.rs78
-rw-r--r--src/librustc_metadata/lib.rs1
-rw-r--r--src/librustc_mir/borrow_check/error_reporting.rs30
-rw-r--r--src/librustc_mir/borrow_check/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/move_errors.rs4
-rw-r--r--src/librustc_mir/borrow_check/mutability_errors.rs10
-rw-r--r--src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs2
-rw-r--r--src/librustc_mir/borrow_check/nll/type_check/mod.rs8
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs2
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs4
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs12
-rw-r--r--src/librustc_mir/lib.rs1
-rw-r--r--src/librustc_mir/lints.rs4
-rw-r--r--src/librustc_mir/transform/instcombine.rs4
-rw-r--r--src/librustc_mir/transform/lower_128bit.rs6
-rw-r--r--src/librustc_passes/lib.rs1
-rw-r--r--src/librustc_privacy/lib.rs1
-rw-r--r--src/librustc_resolve/lib.rs1
-rw-r--r--src/librustc_save_analysis/lib.rs1
-rw-r--r--src/librustc_target/lib.rs1
-rw-r--r--src/librustc_traits/lib.rs1
-rw-r--r--src/librustc_typeck/astconv.rs19
-rw-r--r--src/librustc_typeck/check/wfcheck.rs4
-rw-r--r--src/librustc_typeck/lib.rs1
-rw-r--r--src/librustdoc/lib.rs1
-rw-r--r--src/libsyntax/lib.rs1
-rw-r--r--src/libsyntax_ext/lib.rs1
-rw-r--r--src/libsyntax_pos/lib.rs1
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs19
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-for-crate.rs18
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs12
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs12
-rw-r--r--src/test/ui-fulldeps/auxiliary/lint-tool-test.rs12
-rw-r--r--src/test/ui-fulldeps/internal-lints/default_hash_types.rs22
-rw-r--r--src/test/ui-fulldeps/internal-lints/default_hash_types.stderr39
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs49
-rw-r--r--src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr196
-rw-r--r--src/tools/compiletest/src/runtest.rs7
72 files changed, 939 insertions, 716 deletions
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 7429492f914..86ce5fd01a8 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -316,6 +316,11 @@ fn main() {
         }
     }
 
+    // This is required for internal lints.
+    if stage != "0" {
+        cmd.arg("-Zunstable-options");
+    }
+
     // Force all crates compiled by this compiler to (a) be unstable and (b)
     // allow the `rustc_private` feature to link to other unstable crates
     // also in the sysroot. We also do this for host crates, since those
diff --git a/src/doc/man/rustc.1 b/src/doc/man/rustc.1
index 8f611063dbe..2faf0c2e3e1 100644
--- a/src/doc/man/rustc.1
+++ b/src/doc/man/rustc.1
@@ -265,8 +265,8 @@ Optimize with possible levels 0\[en]3
 
 .SH ENVIRONMENT
 
-Some of these affect the output of the compiler, while others affect programs
-which link to the standard library.
+Some of these affect only test harness programs (generated via rustc --test);
+others affect all programs which link to the Rust standard library.
 
 .TP
 \fBRUST_TEST_THREADS\fR
diff --git a/src/libarena/lib.rs b/src/libarena/lib.rs
index 0a5b79c36aa..6fa15884f5a 100644
--- a/src/libarena/lib.rs
+++ b/src/libarena/lib.rs
@@ -12,6 +12,7 @@
        test(no_crate_inject, attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(alloc)]
 #![feature(core_intrinsics)]
diff --git a/src/libcore/borrow.rs b/src/libcore/borrow.rs
index 89668dc0650..4d58aaca941 100644
--- a/src/libcore/borrow.rs
+++ b/src/libcore/borrow.rs
@@ -32,6 +32,10 @@
 /// on the identical behavior of these additional trait implementations.
 /// These traits will likely appear as additional trait bounds.
 ///
+/// In particular `Eq`, `Ord` and `Hash` must be equivalent for
+/// borrowed and owned values: `x.borrow() == y.borrow()` should give the
+/// same result as `x == y`.
+///
 /// If generic code merely needs to work for all types that can
 /// provide a reference to related type `T`, it is often better to use
 /// [`AsRef<T>`] as more types can safely implement it.
diff --git a/src/libcore/convert.rs b/src/libcore/convert.rs
index a6c65e890a5..7b9e19e36a2 100644
--- a/src/libcore/convert.rs
+++ b/src/libcore/convert.rs
@@ -105,11 +105,13 @@ pub const fn identity<T>(x: T) -> T { x }
 /// `&T` or write a custom function.
 ///
 ///
-/// `AsRef` is very similar to, but serves a slightly different purpose than [`Borrow`]:
+/// `AsRef` has the same signature as [`Borrow`], but `Borrow` is different in few aspects:
 ///
-/// - Use `AsRef` when the goal is to simply convert into a reference
-/// - Use `Borrow` when the goal is related to writing code that is agnostic to
-///   the type of borrow and whether it is a reference or value
+/// - Unlike `AsRef`, `Borrow` has a blanket impl for any `T`, and can be used to accept either
+///   a reference or a value.
+/// - `Borrow` also requires that `Hash`, `Eq` and `Ord` for borrowed value are
+///   equivalent to those of the owned value. For this reason, if you want to
+///   borrow only a single field of a struct you can implement `AsRef`, but not `Borrow`.
 ///
 /// [`Borrow`]: ../../std/borrow/trait.Borrow.html
 ///
diff --git a/src/libcore/hint.rs b/src/libcore/hint.rs
index d1ccc148654..d43e6c49f4c 100644
--- a/src/libcore/hint.rs
+++ b/src/libcore/hint.rs
@@ -50,15 +50,28 @@ pub unsafe fn unreachable_unchecked() -> ! {
     intrinsics::unreachable()
 }
 
-/// Save power or switch hyperthreads in a busy-wait spin-loop.
+/// Signals the processor that it is entering a busy-wait spin-loop.
 ///
-/// This function is deliberately more primitive than
-/// [`std::thread::yield_now`](../../std/thread/fn.yield_now.html) and
-/// does not directly yield to the system's scheduler.
-/// In some cases it might be useful to use a combination of both functions.
-/// Careful benchmarking is advised.
+/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
+/// power or switching hyper-threads.
 ///
-/// On some platforms this function may not do anything at all.
+/// This function is different than [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop` only signals the processor that it is entering a
+/// busy-wait spin-loop without yielding control to the system's scheduler.
+///
+/// Using a busy-wait spin-loop with `spin_loop` is ideally used in situations where a
+/// contended lock is held by another thread executed on a different CPU and where the waiting
+/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
+/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
+/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
+/// before switching to the thread that holds the lock. If the contending lock is held by a thread
+/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
+/// use [`std::thread::yield_now`].
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
+/// do anything at all.
+///
+/// [`std::thread::yield_now`]: ../../std/thread/fn.yield_now.html
 #[inline]
 #[unstable(feature = "renamed_spin_loop", issue = "55002")]
 pub fn spin_loop() {
diff --git a/src/libcore/sync/atomic.rs b/src/libcore/sync/atomic.rs
index 04a49d25301..26b59969e18 100644
--- a/src/libcore/sync/atomic.rs
+++ b/src/libcore/sync/atomic.rs
@@ -124,15 +124,28 @@ use fmt;
 
 use hint::spin_loop;
 
-/// Save power or switch hyperthreads in a busy-wait spin-loop.
+/// Signals the processor that it is entering a busy-wait spin-loop.
 ///
-/// This function is deliberately more primitive than
-/// [`std::thread::yield_now`](../../../std/thread/fn.yield_now.html) and
-/// does not directly yield to the system's scheduler.
-/// In some cases it might be useful to use a combination of both functions.
-/// Careful benchmarking is advised.
+/// Upon receiving spin-loop signal the processor can optimize its behavior by, for example, saving
+/// power or switching hyper-threads.
 ///
-/// On some platforms this function may not do anything at all.
+/// This function is different than [`std::thread::yield_now`] which directly yields to the
+/// system's scheduler, whereas `spin_loop_hint` only signals the processor that it is entering a
+/// busy-wait spin-loop without yielding control to the system's scheduler.
+///
+/// Using a busy-wait spin-loop with `spin_loop_hint` is ideally used in situations where a
+/// contended lock is held by another thread executed on a different CPU and where the waiting
+/// times are relatively small. Because entering busy-wait spin-loop does not trigger the system's
+/// scheduler, no overhead for switching threads occurs. However, if the thread holding the
+/// contended lock is running on the same CPU, the spin-loop is likely to occupy an entire CPU slice
+/// before switching to the thread that holds the lock. If the contending lock is held by a thread
+/// on the same CPU or if the waiting times for acquiring the lock are longer, it is often better to
+/// use [`std::thread::yield_now`].
+///
+/// **Note**: On platforms that do not support receiving spin-loop hints this function does not
+/// do anything at all.
+///
+/// [`std::thread::yield_now`]: ../../../std/thread/fn.yield_now.html
 #[inline]
 #[stable(feature = "spin_loop_hint", since = "1.24.0")]
 pub fn spin_loop_hint() {
diff --git a/src/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index aacd6cec565..2536121c7a3 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -9,6 +9,7 @@
        test(attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 #![feature(rustc_private)]
diff --git a/src/librustc/hir/def_id.rs b/src/librustc/hir/def_id.rs
index 397843fd75a..abfa96841d9 100644
--- a/src/librustc/hir/def_id.rs
+++ b/src/librustc/hir/def_id.rs
@@ -1,10 +1,10 @@
-use crate::ty;
-use crate::ty::TyCtxt;
-use crate::hir::map::definitions::FIRST_FREE_HIGH_DEF_INDEX;
+use crate::ty::{self, print::Printer, subst::Kind, Ty, TyCtxt};
+use crate::hir::map::definitions::{DisambiguatedDefPathData, FIRST_FREE_HIGH_DEF_INDEX};
 use rustc_data_structures::indexed_vec::Idx;
 use serialize;
 use std::fmt;
 use std::u32;
+use syntax::symbol::{LocalInternedString, Symbol};
 
 newtype_index! {
     pub struct CrateId {
@@ -252,6 +252,107 @@ impl DefId {
             format!("module `{}`", tcx.def_path_str(*self))
         }
     }
+
+    /// Check if a `DefId`'s path matches the given absolute type path usage.
+    // Uplifted from rust-lang/rust-clippy
+    pub fn match_path<'a, 'tcx>(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, path: &[&str]) -> bool {
+        pub struct AbsolutePathPrinter<'a, 'tcx> {
+            pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
+        }
+
+        impl<'tcx> Printer<'tcx, 'tcx> for AbsolutePathPrinter<'_, 'tcx> {
+            type Error = !;
+
+            type Path = Vec<LocalInternedString>;
+            type Region = ();
+            type Type = ();
+            type DynExistential = ();
+
+            fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+                self.tcx
+            }
+
+            fn print_region(self, _region: ty::Region<'_>) -> Result<Self::Region, Self::Error> {
+                Ok(())
+            }
+
+            fn print_type(self, _ty: Ty<'tcx>) -> Result<Self::Type, Self::Error> {
+                Ok(())
+            }
+
+            fn print_dyn_existential(
+                self,
+                _predicates: &'tcx ty::List<ty::ExistentialPredicate<'tcx>>,
+                ) -> Result<Self::DynExistential, Self::Error> {
+                Ok(())
+            }
+
+            fn path_crate(self, cnum: CrateNum) -> Result<Self::Path, Self::Error> {
+                Ok(vec![self.tcx.original_crate_name(cnum).as_str()])
+            }
+
+            fn path_qualified(
+                self,
+                self_ty: Ty<'tcx>,
+                trait_ref: Option<ty::TraitRef<'tcx>>,
+                ) -> Result<Self::Path, Self::Error> {
+                if trait_ref.is_none() {
+                    if let ty::Adt(def, substs) = self_ty.sty {
+                        return self.print_def_path(def.did, substs);
+                    }
+                }
+
+                // This shouldn't ever be needed, but just in case:
+                Ok(vec![match trait_ref {
+                    Some(trait_ref) => Symbol::intern(&format!("{:?}", trait_ref)).as_str(),
+                    None => Symbol::intern(&format!("<{}>", self_ty)).as_str(),
+                }])
+            }
+
+            fn path_append_impl(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _disambiguated_data: &DisambiguatedDefPathData,
+                self_ty: Ty<'tcx>,
+                trait_ref: Option<ty::TraitRef<'tcx>>,
+                ) -> Result<Self::Path, Self::Error> {
+                let mut path = print_prefix(self)?;
+
+                // This shouldn't ever be needed, but just in case:
+                path.push(match trait_ref {
+                    Some(trait_ref) => {
+                        Symbol::intern(&format!("<impl {} for {}>", trait_ref, self_ty)).as_str()
+                    },
+                    None => Symbol::intern(&format!("<impl {}>", self_ty)).as_str(),
+                });
+
+                Ok(path)
+            }
+
+            fn path_append(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                disambiguated_data: &DisambiguatedDefPathData,
+                ) -> Result<Self::Path, Self::Error> {
+                let mut path = print_prefix(self)?;
+                path.push(disambiguated_data.data.as_interned_str().as_str());
+                Ok(path)
+            }
+
+            fn path_generic_args(
+                self,
+                print_prefix: impl FnOnce(Self) -> Result<Self::Path, Self::Error>,
+                _args: &[Kind<'tcx>],
+                ) -> Result<Self::Path, Self::Error> {
+                print_prefix(self)
+            }
+        }
+
+        let names = AbsolutePathPrinter { tcx }.print_def_path(self, &[]).unwrap();
+
+        names.len() == path.len()
+            && names.into_iter().zip(path.iter()).all(|(a, &b)| *a == *b)
+    }
 }
 
 impl serialize::UseSpecializedEncodable for DefId {}
diff --git a/src/librustc/ich/hcx.rs b/src/librustc/ich/hcx.rs
index e60fdd62deb..a8e5db26ead 100644
--- a/src/librustc/ich/hcx.rs
+++ b/src/librustc/ich/hcx.rs
@@ -9,7 +9,6 @@ use crate::session::Session;
 
 use std::cmp::Ord;
 use std::hash as std_hash;
-use std::collections::HashMap;
 use std::cell::RefCell;
 
 use syntax::ast;
@@ -394,13 +393,12 @@ impl<'a> HashStable<StableHashingContext<'a>> for DelimSpan {
     }
 }
 
-pub fn hash_stable_trait_impls<'a, 'gcx, W, R>(
+pub fn hash_stable_trait_impls<'a, 'gcx, W>(
     hcx: &mut StableHashingContext<'a>,
     hasher: &mut StableHasher<W>,
     blanket_impls: &[DefId],
-    non_blanket_impls: &HashMap<fast_reject::SimplifiedType, Vec<DefId>, R>)
-    where W: StableHasherResult,
-          R: std_hash::BuildHasher,
+    non_blanket_impls: &FxHashMap<fast_reject::SimplifiedType, Vec<DefId>>)
+    where W: StableHasherResult
 {
     {
         let mut blanket_impls: SmallVec<[_; 8]> = blanket_impls
diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs
index 2810b5a8e6a..19663161fe3 100644
--- a/src/librustc/infer/error_reporting/mod.rs
+++ b/src/librustc/infer/error_reporting/mod.rs
@@ -56,7 +56,7 @@ use crate::hir::Node;
 use crate::middle::region;
 use crate::traits::{ObligationCause, ObligationCauseCode};
 use crate::ty::error::TypeError;
-use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TyKind, TypeFoldable};
+use crate::ty::{self, subst::{Subst, SubstsRef}, Region, Ty, TyCtxt, TypeFoldable};
 use errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use std::{cmp, fmt};
 use syntax_pos::{Pos, Span};
@@ -1094,14 +1094,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 (_, false, _) => {
                     if let Some(exp_found) = exp_found {
                         let (def_id, ret_ty) = match exp_found.found.sty {
-                            TyKind::FnDef(def, _) => {
+                            ty::FnDef(def, _) => {
                                 (Some(def), Some(self.tcx.fn_sig(def).output()))
                             }
                             _ => (None, None),
                         };
 
                         let exp_is_struct = match exp_found.expected.sty {
-                            TyKind::Adt(def, _) => def.is_struct(),
+                            ty::Adt(def, _) => def.is_struct(),
                             _ => false,
                         };
 
@@ -1140,8 +1140,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         diag: &mut DiagnosticBuilder<'tcx>,
     ) {
         match (&exp_found.expected.sty, &exp_found.found.sty) {
-            (TyKind::Adt(exp_def, exp_substs), TyKind::Ref(_, found_ty, _)) => {
-                if let TyKind::Adt(found_def, found_substs) = found_ty.sty {
+            (ty::Adt(exp_def, exp_substs), ty::Ref(_, found_ty, _)) => {
+                if let ty::Adt(found_def, found_substs) = found_ty.sty {
                     let path_str = format!("{:?}", exp_def);
                     if exp_def == &found_def {
                         let opt_msg = "you can convert from `&Option<T>` to `Option<&T>` using \
@@ -1164,17 +1164,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             let mut show_suggestion = true;
                             for (exp_ty, found_ty) in exp_substs.types().zip(found_substs.types()) {
                                 match exp_ty.sty {
-                                    TyKind::Ref(_, exp_ty, _) => {
+                                    ty::Ref(_, exp_ty, _) => {
                                         match (&exp_ty.sty, &found_ty.sty) {
-                                            (_, TyKind::Param(_)) |
-                                            (_, TyKind::Infer(_)) |
-                                            (TyKind::Param(_), _) |
-                                            (TyKind::Infer(_), _) => {}
+                                            (_, ty::Param(_)) |
+                                            (_, ty::Infer(_)) |
+                                            (ty::Param(_), _) |
+                                            (ty::Infer(_), _) => {}
                                             _ if ty::TyS::same_type(exp_ty, found_ty) => {}
                                             _ => show_suggestion = false,
                                         };
                                     }
-                                    TyKind::Param(_) | TyKind::Infer(_) => {}
+                                    ty::Param(_) | ty::Infer(_) => {}
                                     _ => show_suggestion = false,
                                 }
                             }
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index b87343b43c9..0b75cb6c8a3 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -29,6 +29,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #![feature(arbitrary_self_types)]
diff --git a/src/librustc/lint/builtin.rs b/src/librustc/lint/builtin.rs
index 2d8a2c6321f..dc5894cd6b9 100644
--- a/src/librustc/lint/builtin.rs
+++ b/src/librustc/lint/builtin.rs
@@ -392,81 +392,72 @@ declare_lint! {
     "nested occurrence of `impl Trait` type"
 }
 
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// that are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct HardwiredLints;
-
-impl LintPass for HardwiredLints {
-    fn name(&self) -> &'static str {
-        "HardwiredLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
-            EXCEEDING_BITSHIFTS,
-            UNUSED_IMPORTS,
-            UNUSED_EXTERN_CRATES,
-            UNUSED_QUALIFICATIONS,
-            UNKNOWN_LINTS,
-            UNUSED_VARIABLES,
-            UNUSED_ASSIGNMENTS,
-            DEAD_CODE,
-            UNREACHABLE_CODE,
-            UNREACHABLE_PATTERNS,
-            UNUSED_MACROS,
-            WARNINGS,
-            UNUSED_FEATURES,
-            STABLE_FEATURES,
-            UNKNOWN_CRATE_TYPES,
-            TRIVIAL_CASTS,
-            TRIVIAL_NUMERIC_CASTS,
-            PRIVATE_IN_PUBLIC,
-            EXPORTED_PRIVATE_DEPENDENCIES,
-            PUB_USE_OF_PRIVATE_EXTERN_CRATE,
-            INVALID_TYPE_PARAM_DEFAULT,
-            CONST_ERR,
-            RENAMED_AND_REMOVED_LINTS,
-            SAFE_EXTERN_STATICS,
-            SAFE_PACKED_BORROWS,
-            PATTERNS_IN_FNS_WITHOUT_BODY,
-            LEGACY_DIRECTORY_OWNERSHIP,
-            LEGACY_CONSTRUCTOR_VISIBILITY,
-            MISSING_FRAGMENT_SPECIFIER,
-            PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
-            LATE_BOUND_LIFETIME_ARGUMENTS,
-            INCOHERENT_FUNDAMENTAL_IMPLS,
-            ORDER_DEPENDENT_TRAIT_OBJECTS,
-            DEPRECATED,
-            UNUSED_UNSAFE,
-            UNUSED_MUT,
-            UNCONDITIONAL_RECURSION,
-            SINGLE_USE_LIFETIMES,
-            UNUSED_LIFETIMES,
-            UNUSED_LABELS,
-            TYVAR_BEHIND_RAW_POINTER,
-            ELIDED_LIFETIMES_IN_PATHS,
-            BARE_TRAIT_OBJECTS,
-            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
-            UNSTABLE_NAME_COLLISIONS,
-            IRREFUTABLE_LET_PATTERNS,
-            DUPLICATE_MACRO_EXPORTS,
-            INTRA_DOC_LINK_RESOLUTION_FAILURE,
-            MISSING_DOC_CODE_EXAMPLES,
-            PRIVATE_DOC_TESTS,
-            WHERE_CLAUSES_OBJECT_SAFETY,
-            PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
-            MACRO_USE_EXTERN_CRATE,
-            MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
-            parser::QUESTION_MARK_MACRO_SEP,
-            parser::ILL_FORMED_ATTRIBUTE_INPUT,
-            DEPRECATED_IN_FUTURE,
-            AMBIGUOUS_ASSOCIATED_ITEMS,
-            NESTED_IMPL_TRAIT,
-            DUPLICATE_MATCHER_BINDING_NAME,
-        )
-    }
+declare_lint_pass! {
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// that are used by other parts of the compiler.
+    HardwiredLints => [
+        ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
+        EXCEEDING_BITSHIFTS,
+        UNUSED_IMPORTS,
+        UNUSED_EXTERN_CRATES,
+        UNUSED_QUALIFICATIONS,
+        UNKNOWN_LINTS,
+        UNUSED_VARIABLES,
+        UNUSED_ASSIGNMENTS,
+        DEAD_CODE,
+        UNREACHABLE_CODE,
+        UNREACHABLE_PATTERNS,
+        UNUSED_MACROS,
+        WARNINGS,
+        UNUSED_FEATURES,
+        STABLE_FEATURES,
+        UNKNOWN_CRATE_TYPES,
+        TRIVIAL_CASTS,
+        TRIVIAL_NUMERIC_CASTS,
+        PRIVATE_IN_PUBLIC,
+        EXPORTED_PRIVATE_DEPENDENCIES,
+        PUB_USE_OF_PRIVATE_EXTERN_CRATE,
+        INVALID_TYPE_PARAM_DEFAULT,
+        CONST_ERR,
+        RENAMED_AND_REMOVED_LINTS,
+        SAFE_EXTERN_STATICS,
+        SAFE_PACKED_BORROWS,
+        PATTERNS_IN_FNS_WITHOUT_BODY,
+        LEGACY_DIRECTORY_OWNERSHIP,
+        LEGACY_CONSTRUCTOR_VISIBILITY,
+        MISSING_FRAGMENT_SPECIFIER,
+        PARENTHESIZED_PARAMS_IN_TYPES_AND_MODULES,
+        LATE_BOUND_LIFETIME_ARGUMENTS,
+        INCOHERENT_FUNDAMENTAL_IMPLS,
+        ORDER_DEPENDENT_TRAIT_OBJECTS,
+        DEPRECATED,
+        UNUSED_UNSAFE,
+        UNUSED_MUT,
+        UNCONDITIONAL_RECURSION,
+        SINGLE_USE_LIFETIMES,
+        UNUSED_LIFETIMES,
+        UNUSED_LABELS,
+        TYVAR_BEHIND_RAW_POINTER,
+        ELIDED_LIFETIMES_IN_PATHS,
+        BARE_TRAIT_OBJECTS,
+        ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
+        UNSTABLE_NAME_COLLISIONS,
+        IRREFUTABLE_LET_PATTERNS,
+        DUPLICATE_MACRO_EXPORTS,
+        INTRA_DOC_LINK_RESOLUTION_FAILURE,
+        MISSING_DOC_CODE_EXAMPLES,
+        PRIVATE_DOC_TESTS,
+        WHERE_CLAUSES_OBJECT_SAFETY,
+        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
+        MACRO_USE_EXTERN_CRATE,
+        MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
+        parser::QUESTION_MARK_MACRO_SEP,
+        parser::ILL_FORMED_ATTRIBUTE_INPUT,
+        DEPRECATED_IN_FUTURE,
+        AMBIGUOUS_ASSOCIATED_ITEMS,
+        NESTED_IMPL_TRAIT,
+        DUPLICATE_MATCHER_BINDING_NAME,
+    ]
 }
 
 // this could be a closure, but then implementing derive traits
diff --git a/src/librustc/lint/internal.rs b/src/librustc/lint/internal.rs
new file mode 100644
index 00000000000..d5f8876d162
--- /dev/null
+++ b/src/librustc/lint/internal.rs
@@ -0,0 +1,127 @@
+//! Some lints that are only useful in the compiler or crates that use compiler internals, such as
+//! Clippy.
+
+use crate::hir::{HirId, Path, PathSegment, QPath, Ty, TyKind};
+use crate::lint::{
+    EarlyContext, EarlyLintPass, LateContext, LateLintPass, LintArray, LintContext, LintPass,
+};
+use errors::Applicability;
+use rustc_data_structures::fx::FxHashMap;
+use syntax::ast::Ident;
+
+declare_lint! {
+    pub DEFAULT_HASH_TYPES,
+    Allow,
+    "forbid HashMap and HashSet and suggest the FxHash* variants"
+}
+
+pub struct DefaultHashTypes {
+    map: FxHashMap<String, String>,
+}
+
+impl DefaultHashTypes {
+    pub fn new() -> Self {
+        let mut map = FxHashMap::default();
+        map.insert("HashMap".to_string(), "FxHashMap".to_string());
+        map.insert("HashSet".to_string(), "FxHashSet".to_string());
+        Self { map }
+    }
+}
+
+impl LintPass for DefaultHashTypes {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(DEFAULT_HASH_TYPES)
+    }
+
+    fn name(&self) -> &'static str {
+        "DefaultHashTypes"
+    }
+}
+
+impl EarlyLintPass for DefaultHashTypes {
+    fn check_ident(&mut self, cx: &EarlyContext<'_>, ident: Ident) {
+        let ident_string = ident.to_string();
+        if let Some(replace) = self.map.get(&ident_string) {
+            let msg = format!(
+                "Prefer {} over {}, it has better performance",
+                replace, ident_string
+            );
+            let mut db = cx.struct_span_lint(DEFAULT_HASH_TYPES, ident.span, &msg);
+            db.span_suggestion(
+                ident.span,
+                "use",
+                replace.to_string(),
+                Applicability::MaybeIncorrect, // FxHashMap, ... needs another import
+            );
+            db.note(&format!(
+                "a `use rustc_data_structures::fx::{}` may be necessary",
+                replace
+            ))
+            .emit();
+        }
+    }
+}
+
+declare_lint! {
+    pub USAGE_OF_TY_TYKIND,
+    Allow,
+    "Usage of `ty::TyKind` outside of the `ty::sty` module"
+}
+
+pub struct TyKindUsage;
+
+impl LintPass for TyKindUsage {
+    fn get_lints(&self) -> LintArray {
+        lint_array!(USAGE_OF_TY_TYKIND)
+    }
+
+    fn name(&self) -> &'static str {
+        "TyKindUsage"
+    }
+}
+
+impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TyKindUsage {
+    fn check_path(&mut self, cx: &LateContext<'_, '_>, path: &'tcx Path, _: HirId) {
+        let segments = path.segments.iter().rev().skip(1).rev();
+
+        if let Some(last) = segments.last() {
+            let span = path.span.with_hi(last.ident.span.hi());
+            if lint_ty_kind_usage(cx, last) {
+                cx.struct_span_lint(USAGE_OF_TY_TYKIND, span, "usage of `ty::TyKind::<kind>`")
+                    .span_suggestion(
+                        span,
+                        "try using ty::<kind> directly",
+                        "ty".to_string(),
+                        Applicability::MaybeIncorrect, // ty maybe needs an import
+                    )
+                    .emit();
+            }
+        }
+    }
+
+    fn check_ty(&mut self, cx: &LateContext<'_, '_>, ty: &'tcx Ty) {
+        if let TyKind::Path(qpath) = &ty.node {
+            if let QPath::Resolved(_, path) = qpath {
+                if let Some(last) = path.segments.iter().last() {
+                    if lint_ty_kind_usage(cx, last) {
+                        cx.struct_span_lint(USAGE_OF_TY_TYKIND, path.span, "usage of `ty::TyKind`")
+                            .help("try using `ty::Ty` instead")
+                            .emit();
+                    }
+                }
+            }
+        }
+    }
+}
+
+fn lint_ty_kind_usage(cx: &LateContext<'_, '_>, segment: &PathSegment) -> bool {
+    if segment.ident.as_str() == "TyKind" {
+        if let Some(def) = segment.def {
+            if let Some(did) = def.opt_def_id() {
+                return did.match_path(cx.tcx, &["rustc", "ty", "sty", "TyKind"]);
+            }
+        }
+    }
+
+    false
+}
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index a5506bb8f59..57d1ce9cad4 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -181,6 +181,27 @@ pub trait LintPass {
     fn get_lints(&self) -> LintArray;
 }
 
+/// Implements `LintPass for $name` with the given list of `Lint` statics.
+#[macro_export]
+macro_rules! impl_lint_pass {
+    ($name:ident => [$($lint:expr),* $(,)?]) => {
+        impl LintPass for $name {
+            fn name(&self) -> &'static str { stringify!($name) }
+            fn get_lints(&self) -> LintArray { $crate::lint_array!($($lint),*) }
+        }
+    };
+}
+
+/// Declares a type named `$name` which implements `LintPass`.
+/// To the right of `=>` a comma separated list of `Lint` statics is given.
+#[macro_export]
+macro_rules! declare_lint_pass {
+    ($(#[$m:meta])* $name:ident => [$($lint:expr),* $(,)?]) => {
+        $(#[$m])* #[derive(Copy, Clone)] pub struct $name;
+        $crate::impl_lint_pass!($name => [$($lint),*]);
+    };
+}
+
 #[macro_export]
 macro_rules! late_lint_methods {
     ($macro:path, $args:tt, [$hir:tt]) => (
@@ -574,6 +595,7 @@ impl_stable_hash_for!(enum self::LintSource {
 pub type LevelSource = (Level, LintSource);
 
 pub mod builtin;
+pub mod internal;
 mod context;
 mod levels;
 
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 0eb37f0ac9e..23be1bbf6c6 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -36,7 +36,7 @@ impl<'a, 'gcx, 'tcx> PlaceTy<'tcx> {
     pub fn field_ty(self, tcx: TyCtxt<'a, 'gcx, 'tcx>, f: &Field) -> Ty<'tcx>
     {
         let answer = match self.ty.sty {
-            ty::TyKind::Adt(adt_def, substs) => {
+            ty::Adt(adt_def, substs) => {
                 let variant_def = match self.variant_index {
                     None => adt_def.non_enum_variant(),
                     Some(variant_index) => {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 03936a82c71..aa5610739fd 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -219,6 +219,11 @@ pub struct CommonTypes<'tcx> {
     pub never: 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`.
+    /// This type must not appear anywhere in other converted types.
+    pub trait_object_dummy_self: Ty<'tcx>,
+
     pub re_empty: Region<'tcx>,
     pub re_static: Region<'tcx>,
     pub re_erased: Region<'tcx>,
@@ -955,6 +960,8 @@ impl<'tcx> CommonTypes<'tcx> {
             f32: mk(Float(ast::FloatTy::F32)),
             f64: mk(Float(ast::FloatTy::F64)),
 
+            trait_object_dummy_self: mk(Infer(ty::FreshTy(0))),
+
             re_empty: mk_region(RegionKind::ReEmpty),
             re_static: mk_region(RegionKind::ReStatic),
             re_erased: mk_region(RegionKind::ReErased),
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 102057c1380..7d47867cea1 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1,3 +1,5 @@
+#![cfg_attr(not(stage0), allow(usage_of_ty_tykind))]
+
 pub use self::Variance::*;
 pub use self::AssociatedItemContainer::*;
 pub use self::BorrowKind::*;
diff --git a/src/librustc/util/common.rs b/src/librustc/util/common.rs
index 5622fe43436..26194176350 100644
--- a/src/librustc/util/common.rs
+++ b/src/librustc/util/common.rs
@@ -1,11 +1,10 @@
 #![allow(non_camel_case_types)]
 
-use rustc_data_structures::sync::Lock;
+use rustc_data_structures::{fx::FxHashMap, sync::Lock};
 
 use std::cell::{RefCell, Cell};
-use std::collections::HashMap;
 use std::fmt::Debug;
-use std::hash::{Hash, BuildHasher};
+use std::hash::Hash;
 use std::panic;
 use std::env;
 use std::time::{Duration, Instant};
@@ -341,8 +340,8 @@ pub trait MemoizationMap {
         where OP: FnOnce() -> Self::Value;
 }
 
-impl<K, V, S> MemoizationMap for RefCell<HashMap<K,V,S>>
-    where K: Hash+Eq+Clone, V: Clone, S: BuildHasher
+impl<K, V> MemoizationMap for RefCell<FxHashMap<K,V>>
+    where K: Hash+Eq+Clone, V: Clone
 {
     type Key = K;
     type Value = V;
diff --git a/src/librustc_allocator/lib.rs b/src/librustc_allocator/lib.rs
index 9d6e728e135..a9e422fb238 100644
--- a/src/librustc_allocator/lib.rs
+++ b/src/librustc_allocator/lib.rs
@@ -2,6 +2,7 @@
 #![feature(rustc_private)]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub mod expand;
 
diff --git a/src/librustc_borrowck/lib.rs b/src/librustc_borrowck/lib.rs
index cf4669db87e..3761a52bccc 100644
--- a/src/librustc_borrowck/lib.rs
+++ b/src/librustc_borrowck/lib.rs
@@ -2,6 +2,7 @@
 
 #![allow(non_camel_case_types)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 
diff --git a/src/librustc_codegen_ssa/lib.rs b/src/librustc_codegen_ssa/lib.rs
index 1e898ced7a6..e2917578c0e 100644
--- a/src/librustc_codegen_ssa/lib.rs
+++ b/src/librustc_codegen_ssa/lib.rs
@@ -14,6 +14,7 @@
 #![allow(unused_attributes)]
 #![allow(dead_code)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_codegen_utils/lib.rs b/src/librustc_codegen_utils/lib.rs
index 1a3914e6ef4..330cfe154e3 100644
--- a/src/librustc_codegen_utils/lib.rs
+++ b/src/librustc_codegen_utils/lib.rs
@@ -16,6 +16,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_driver/lib.rs b/src/librustc_driver/lib.rs
index 4b7cffaad55..2781bfa3ec8 100644
--- a/src/librustc_driver/lib.rs
+++ b/src/librustc_driver/lib.rs
@@ -17,6 +17,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub extern crate getopts;
 #[cfg(unix)]
diff --git a/src/librustc_errors/lib.rs b/src/librustc_errors/lib.rs
index ebbc5a3d3a3..71bef54cd17 100644
--- a/src/librustc_errors/lib.rs
+++ b/src/librustc_errors/lib.rs
@@ -6,6 +6,7 @@
 #![feature(nll)]
 #![feature(optin_builtin_traits)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[allow(unused_extern_crates)]
 extern crate serialize as rustc_serialize; // used by deriving
diff --git a/src/librustc_incremental/lib.rs b/src/librustc_incremental/lib.rs
index fe75bbc36c3..d7db324f346 100644
--- a/src/librustc_incremental/lib.rs
+++ b/src/librustc_incremental/lib.rs
@@ -8,6 +8,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use] extern crate rustc;
 #[allow(unused_extern_crates)]
diff --git a/src/librustc_interface/interface.rs b/src/librustc_interface/interface.rs
index 245a2bf92d5..74085123f89 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -12,7 +12,6 @@ use rustc_data_structures::OnDrop;
 use rustc_data_structures::sync::Lrc;
 use rustc_data_structures::fx::{FxHashSet, FxHashMap};
 use rustc_metadata::cstore::CStore;
-use std::collections::HashSet;
 use std::io::Write;
 use std::path::PathBuf;
 use std::result;
diff --git a/src/librustc_interface/lib.rs b/src/librustc_interface/lib.rs
index 3314681b698..353ff6a57a5 100644
--- a/src/librustc_interface/lib.rs
+++ b/src/librustc_interface/lib.rs
@@ -7,6 +7,7 @@
 #![cfg_attr(unix, feature(libc))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![allow(unused_imports)]
 
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 6e4f2bf24e3..17523aedffb 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -21,7 +21,6 @@ use rustc_plugin;
 use rustc_privacy;
 use rustc_resolve;
 use rustc_typeck;
-use std::collections::HashSet;
 use std::env;
 use std::env::consts::{DLL_PREFIX, DLL_SUFFIX};
 use std::io::{self, Write};
@@ -109,6 +108,9 @@ pub fn create_session(
     let codegen_backend = get_codegen_backend(&sess);
 
     rustc_lint::register_builtins(&mut sess.lint_store.borrow_mut(), Some(&sess));
+    if sess.unstable_options() {
+        rustc_lint::register_internals(&mut sess.lint_store.borrow_mut(), Some(&sess));
+    }
 
     let mut cfg = config::build_configuration(&sess, config::to_crate_config(cfg));
     add_configuration(&mut cfg, &sess, &*codegen_backend);
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index 1fae931e9f1..7fe047ec2c6 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -63,18 +63,7 @@ declare_lint! {
     "suggest using `loop { }` instead of `while true { }`"
 }
 
-#[derive(Copy, Clone)]
-pub struct WhileTrue;
-
-impl LintPass for WhileTrue {
-    fn name(&self) -> &'static str {
-        "WhileTrue"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(WHILE_TRUE)
-    }
-}
+declare_lint_pass!(WhileTrue => [WHILE_TRUE]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for WhileTrue {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
@@ -105,8 +94,7 @@ declare_lint! {
     "use of owned (Box type) heap memory"
 }
 
-#[derive(Copy, Clone)]
-pub struct BoxPointers;
+declare_lint_pass!(BoxPointers => [BOX_POINTERS]);
 
 impl BoxPointers {
     fn check_heap_type<'a, 'tcx>(&self, cx: &LateContext<'_, '_>, span: Span, ty: Ty<'_>) {
@@ -119,16 +107,6 @@ impl BoxPointers {
     }
 }
 
-impl LintPass for BoxPointers {
-    fn name(&self) -> &'static str {
-        "BoxPointers"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(BOX_POINTERS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for BoxPointers {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
@@ -169,18 +147,7 @@ declare_lint! {
     "using `Struct { x: x }` instead of `Struct { x }` in a pattern"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonShorthandFieldPatterns;
-
-impl LintPass for NonShorthandFieldPatterns {
-    fn name(&self) -> &'static str {
-        "NonShorthandFieldPatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SHORTHAND_FIELD_PATTERNS)
-    }
-}
+declare_lint_pass!(NonShorthandFieldPatterns => [NON_SHORTHAND_FIELD_PATTERNS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonShorthandFieldPatterns {
     fn check_pat(&mut self, cx: &LateContext<'_, '_>, pat: &hir::Pat) {
@@ -226,18 +193,7 @@ declare_lint! {
     "usage of `unsafe` code"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnsafeCode;
-
-impl LintPass for UnsafeCode {
-    fn name(&self) -> &'static str {
-        "UnsafeCode"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSAFE_CODE)
-    }
-}
+declare_lint_pass!(UnsafeCode => [UNSAFE_CODE]);
 
 impl UnsafeCode {
     fn report_unsafe(&self, cx: &EarlyContext<'_>, span: Span, desc: &'static str) {
@@ -327,6 +283,8 @@ pub struct MissingDoc {
     private_traits: FxHashSet<hir::HirId>,
 }
 
+impl_lint_pass!(MissingDoc => [MISSING_DOCS]);
+
 fn has_doc(attr: &ast::Attribute) -> bool {
     if !attr.check_name("doc") {
         return false;
@@ -394,16 +352,6 @@ impl MissingDoc {
     }
 }
 
-impl LintPass for MissingDoc {
-    fn name(&self) -> &'static str {
-        "MissingDoc"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DOCS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDoc {
     fn enter_lint_attrs(&mut self, _: &LateContext<'_, '_>, attrs: &[ast::Attribute]) {
         let doc_hidden = self.doc_hidden() ||
@@ -541,18 +489,7 @@ declare_lint! {
     "detects potentially-forgotten implementations of `Copy`"
 }
 
-#[derive(Copy, Clone)]
-pub struct MissingCopyImplementations;
-
-impl LintPass for MissingCopyImplementations {
-    fn name(&self) -> &'static str {
-        "MissingCopyImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_COPY_IMPLEMENTATIONS)
-    }
-}
+declare_lint_pass!(MissingCopyImplementations => [MISSING_COPY_IMPLEMENTATIONS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingCopyImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -609,22 +546,14 @@ pub struct MissingDebugImplementations {
     impling_types: Option<HirIdSet>,
 }
 
+impl_lint_pass!(MissingDebugImplementations => [MISSING_DEBUG_IMPLEMENTATIONS]);
+
 impl MissingDebugImplementations {
     pub fn new() -> MissingDebugImplementations {
         MissingDebugImplementations { impling_types: None }
     }
 }
 
-impl LintPass for MissingDebugImplementations {
-    fn name(&self) -> &'static str {
-        "MissingDebugImplementations"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_DEBUG_IMPLEMENTATIONS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingDebugImplementations {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         if !cx.access_levels.is_reachable(item.hir_id) {
@@ -672,19 +601,10 @@ declare_lint! {
     "detects anonymous parameters"
 }
 
-/// Checks for use of anonymous parameters (RFC 1685).
-#[derive(Copy, Clone)]
-pub struct AnonymousParameters;
-
-impl LintPass for AnonymousParameters {
-    fn name(&self) -> &'static str {
-        "AnonymousParameters"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ANONYMOUS_PARAMETERS)
-    }
-}
+declare_lint_pass!(
+    /// Checks for use of anonymous parameters (RFC 1685).
+    AnonymousParameters => [ANONYMOUS_PARAMETERS]
+);
 
 impl EarlyLintPass for AnonymousParameters {
     fn check_trait_item(&mut self, cx: &EarlyContext<'_>, it: &ast::TraitItem) {
@@ -736,6 +656,8 @@ pub struct DeprecatedAttr {
     depr_attrs: Vec<&'static (&'static str, AttributeType, AttributeTemplate, AttributeGate)>,
 }
 
+impl_lint_pass!(DeprecatedAttr => []);
+
 impl DeprecatedAttr {
     pub fn new() -> DeprecatedAttr {
         DeprecatedAttr {
@@ -744,16 +666,6 @@ impl DeprecatedAttr {
     }
 }
 
-impl LintPass for DeprecatedAttr {
-    fn name(&self) -> &'static str {
-        "DeprecatedAttr"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
-
 impl EarlyLintPass for DeprecatedAttr {
     fn check_attribute(&mut self, cx: &EarlyContext<'_>, attr: &ast::Attribute) {
         let name = attr.name_or_empty();
@@ -786,18 +698,7 @@ declare_lint! {
     "detects doc comments that aren't used by rustdoc"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedDocComment;
-
-impl LintPass for UnusedDocComment {
-    fn name(&self) -> &'static str {
-        "UnusedDocComment"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![UNUSED_DOC_COMMENTS]
-    }
-}
+declare_lint_pass!(UnusedDocComment => [UNUSED_DOC_COMMENTS]);
 
 impl UnusedDocComment {
     fn warn_if_doc(
@@ -884,18 +785,7 @@ declare_lint! {
     "compiler plugin used as ordinary library in non-plugin crate"
 }
 
-#[derive(Copy, Clone)]
-pub struct PluginAsLibrary;
-
-impl LintPass for PluginAsLibrary {
-    fn name(&self) -> &'static str {
-        "PluginAsLibrary"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![PLUGIN_AS_LIBRARY]
-    }
-}
+declare_lint_pass!(PluginAsLibrary => [PLUGIN_AS_LIBRARY]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PluginAsLibrary {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -940,19 +830,7 @@ declare_lint! {
     "generic items must be mangled"
 }
 
-#[derive(Copy, Clone)]
-pub struct InvalidNoMangleItems;
-
-impl LintPass for InvalidNoMangleItems {
-    fn name(&self) -> &'static str {
-        "InvalidNoMangleItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NO_MANGLE_CONST_ITEMS,
-                    NO_MANGLE_GENERIC_ITEMS)
-    }
-}
+declare_lint_pass!(InvalidNoMangleItems => [NO_MANGLE_CONST_ITEMS, NO_MANGLE_GENERIC_ITEMS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
@@ -1011,24 +889,13 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for InvalidNoMangleItems {
     }
 }
 
-#[derive(Clone, Copy)]
-pub struct MutableTransmutes;
-
 declare_lint! {
     MUTABLE_TRANSMUTES,
     Deny,
     "mutating transmuted &mut T from &T may cause undefined behavior"
 }
 
-impl LintPass for MutableTransmutes {
-    fn name(&self) -> &'static str {
-        "MutableTransmutes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MUTABLE_TRANSMUTES)
-    }
-}
+declare_lint_pass!(MutableTransmutes => [MUTABLE_TRANSMUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, expr: &hir::Expr) {
@@ -1036,7 +903,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
 
         let msg = "mutating transmuted &mut T from &T may cause undefined behavior, \
                    consider instead using an UnsafeCell";
-        match get_transmute_from_to(cx, expr) {
+        match get_transmute_from_to(cx, expr).map(|(ty1, ty2)| (&ty1.sty, &ty2.sty)) {
             Some((&ty::Ref(_, _, from_mt), &ty::Ref(_, _, to_mt))) => {
                 if to_mt == hir::Mutability::MutMutable &&
                    from_mt == hir::Mutability::MutImmutable {
@@ -1049,7 +916,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
         fn get_transmute_from_to<'a, 'tcx>
             (cx: &LateContext<'a, 'tcx>,
              expr: &hir::Expr)
-             -> Option<(&'tcx ty::TyKind<'tcx>, &'tcx ty::TyKind<'tcx>)> {
+             -> Option<(Ty<'tcx>, Ty<'tcx>)> {
             let def = if let hir::ExprKind::Path(ref qpath) = expr.node {
                 cx.tables.qpath_def(qpath, expr.hir_id)
             } else {
@@ -1062,7 +929,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
                 let sig = cx.tables.node_type(expr.hir_id).fn_sig(cx.tcx);
                 let from = sig.inputs().skip_binder()[0];
                 let to = *sig.output().skip_binder();
-                return Some((&from.sty, &to.sty));
+                return Some((from, to));
             }
             None
         }
@@ -1074,25 +941,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MutableTransmutes {
     }
 }
 
-/// Forbids using the `#[feature(...)]` attribute
-#[derive(Copy, Clone)]
-pub struct UnstableFeatures;
-
 declare_lint! {
     UNSTABLE_FEATURES,
     Allow,
     "enabling unstable features (deprecated. do not use)"
 }
 
-impl LintPass for UnstableFeatures {
-    fn name(&self) -> &'static str {
-        "UnstableFeatures"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNSTABLE_FEATURES)
-    }
-}
+declare_lint_pass!(
+    /// Forbids using the `#[feature(...)]` attribute
+    UnstableFeatures => [UNSTABLE_FEATURES]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     fn check_attribute(&mut self, ctx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -1106,24 +964,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnstableFeatures {
     }
 }
 
-/// Lint for unions that contain fields with possibly non-trivial destructors.
-pub struct UnionsWithDropFields;
-
 declare_lint! {
     UNIONS_WITH_DROP_FIELDS,
     Warn,
     "use of unions that contain fields with possibly non-trivial drop code"
 }
 
-impl LintPass for UnionsWithDropFields {
-    fn name(&self) -> &'static str {
-        "UnionsWithDropFields"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNIONS_WITH_DROP_FIELDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for unions that contain fields with possibly non-trivial destructors.
+    UnionsWithDropFields => [UNIONS_WITH_DROP_FIELDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     fn check_item(&mut self, ctx: &LateContext<'_, '_>, item: &hir::Item) {
@@ -1143,25 +993,16 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnionsWithDropFields {
     }
 }
 
-/// Lint for items marked `pub` that aren't reachable from other crates.
-#[derive(Copy, Clone)]
-pub struct UnreachablePub;
-
 declare_lint! {
     pub UNREACHABLE_PUB,
     Allow,
     "`pub` items not reachable from crate root"
 }
 
-impl LintPass for UnreachablePub {
-    fn name(&self) -> &'static str {
-        "UnreachablePub"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNREACHABLE_PUB)
-    }
-}
+declare_lint_pass!(
+    /// Lint for items marked `pub` that aren't reachable from other crates.
+    UnreachablePub => [UNREACHABLE_PUB]
+);
 
 impl UnreachablePub {
     fn perform_lint(&self, cx: &LateContext<'_, '_>, what: &str, id: hir::HirId,
@@ -1197,7 +1038,6 @@ impl UnreachablePub {
     }
 }
 
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, item: &hir::Item) {
         self.perform_lint(cx, "item", item.hir_id, &item.vis, item.span, true);
@@ -1217,27 +1057,18 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnreachablePub {
     }
 }
 
-/// Lint for trait and lifetime bounds in type aliases being mostly ignored.
-/// They are relevant when using associated types, but otherwise neither checked
-/// at definition site nor enforced at use site.
-
-pub struct TypeAliasBounds;
-
 declare_lint! {
     TYPE_ALIAS_BOUNDS,
     Warn,
     "bounds in type aliases are not enforced"
 }
 
-impl LintPass for TypeAliasBounds {
-    fn name(&self) -> &'static str {
-        "TypeAliasBounds"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TYPE_ALIAS_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds in type aliases being mostly ignored.
+    /// They are relevant when using associated types, but otherwise neither checked
+    /// at definition site nor enforced at use site.
+    TypeAliasBounds => [TYPE_ALIAS_BOUNDS]
+);
 
 impl TypeAliasBounds {
     fn is_type_variable_assoc(qpath: &hir::QPath) -> bool {
@@ -1331,21 +1162,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeAliasBounds {
     }
 }
 
-/// Lint constants that are erroneous.
-/// Without this lint, we might not get any diagnostic if the constant is
-/// unused within this crate, even though downstream crates can't use it
-/// without producing an error.
-pub struct UnusedBrokenConst;
-
-impl LintPass for UnusedBrokenConst {
-    fn name(&self) -> &'static str {
-        "UnusedBrokenConst"
-    }
+declare_lint_pass!(
+    /// Lint constants that are erroneous.
+    /// Without this lint, we might not get any diagnostic if the constant is
+    /// unused within this crate, even though downstream crates can't use it
+    /// without producing an error.
+    UnusedBrokenConst => []
+);
 
-    fn get_lints(&self) -> LintArray {
-        lint_array!()
-    }
-}
 fn check_const(cx: &LateContext<'_, '_>, body_id: hir::BodyId) {
     let def_id = cx.tcx.hir().body_owner_def_id(body_id);
     let is_static = cx.tcx.is_static(def_id).is_some();
@@ -1378,25 +1202,17 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedBrokenConst {
     }
 }
 
-/// Lint for trait and lifetime bounds that don't depend on type parameters
-/// which either do nothing, or stop the item from being used.
-pub struct TrivialConstraints;
-
 declare_lint! {
     TRIVIAL_BOUNDS,
     Warn,
     "these bounds don't depend on an type parameters"
 }
 
-impl LintPass for TrivialConstraints {
-    fn name(&self) -> &'static str {
-        "TrivialConstraints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TRIVIAL_BOUNDS)
-    }
-}
+declare_lint_pass!(
+    /// Lint for trait and lifetime bounds that don't depend on type parameters
+    /// which either do nothing, or stop the item from being used.
+    TrivialConstraints => [TRIVIAL_BOUNDS]
+);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     fn check_item(
@@ -1440,40 +1256,30 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TrivialConstraints {
     }
 }
 
-
-/// Does nothing as a lint pass, but registers some `Lint`s
-/// which are used by other parts of the compiler.
-#[derive(Copy, Clone)]
-pub struct SoftLints;
-
-impl LintPass for SoftLints {
-    fn name(&self) -> &'static str {
-        "SoftLints"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(
-            WHILE_TRUE,
-            BOX_POINTERS,
-            NON_SHORTHAND_FIELD_PATTERNS,
-            UNSAFE_CODE,
-            MISSING_DOCS,
-            MISSING_COPY_IMPLEMENTATIONS,
-            MISSING_DEBUG_IMPLEMENTATIONS,
-            ANONYMOUS_PARAMETERS,
-            UNUSED_DOC_COMMENTS,
-            PLUGIN_AS_LIBRARY,
-            NO_MANGLE_CONST_ITEMS,
-            NO_MANGLE_GENERIC_ITEMS,
-            MUTABLE_TRANSMUTES,
-            UNSTABLE_FEATURES,
-            UNIONS_WITH_DROP_FIELDS,
-            UNREACHABLE_PUB,
-            TYPE_ALIAS_BOUNDS,
-            TRIVIAL_BOUNDS
-        )
-    }
-}
+declare_lint_pass!(
+    /// Does nothing as a lint pass, but registers some `Lint`s
+    /// which are used by other parts of the compiler.
+    SoftLints => [
+        WHILE_TRUE,
+        BOX_POINTERS,
+        NON_SHORTHAND_FIELD_PATTERNS,
+        UNSAFE_CODE,
+        MISSING_DOCS,
+        MISSING_COPY_IMPLEMENTATIONS,
+        MISSING_DEBUG_IMPLEMENTATIONS,
+        ANONYMOUS_PARAMETERS,
+        UNUSED_DOC_COMMENTS,
+        PLUGIN_AS_LIBRARY,
+        NO_MANGLE_CONST_ITEMS,
+        NO_MANGLE_GENERIC_ITEMS,
+        MUTABLE_TRANSMUTES,
+        UNSTABLE_FEATURES,
+        UNIONS_WITH_DROP_FIELDS,
+        UNREACHABLE_PUB,
+        TYPE_ALIAS_BOUNDS,
+        TRIVIAL_BOUNDS
+    ]
+);
 
 declare_lint! {
     pub ELLIPSIS_INCLUSIVE_RANGE_PATTERNS,
@@ -1481,18 +1287,7 @@ declare_lint! {
     "`...` range patterns are deprecated"
 }
 
-
-pub struct EllipsisInclusiveRangePatterns;
-
-impl LintPass for EllipsisInclusiveRangePatterns {
-    fn name(&self) -> &'static str {
-        "EllipsisInclusiveRangePatterns"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(ELLIPSIS_INCLUSIVE_RANGE_PATTERNS)
-    }
-}
+declare_lint_pass!(EllipsisInclusiveRangePatterns => [ELLIPSIS_INCLUSIVE_RANGE_PATTERNS]);
 
 impl EarlyLintPass for EllipsisInclusiveRangePatterns {
     fn check_pat(&mut self, cx: &EarlyContext<'_>, pat: &ast::Pat, visit_subpats: &mut bool) {
@@ -1553,6 +1348,8 @@ pub struct UnnameableTestItems {
     items_nameable: bool,
 }
 
+impl_lint_pass!(UnnameableTestItems => [UNNAMEABLE_TEST_ITEMS]);
+
 impl UnnameableTestItems {
     pub fn new() -> Self {
         Self {
@@ -1562,16 +1359,6 @@ impl UnnameableTestItems {
     }
 }
 
-impl LintPass for UnnameableTestItems {
-    fn name(&self) -> &'static str {
-        "UnnameableTestItems"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNNAMEABLE_TEST_ITEMS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnnameableTestItems {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         if self.items_nameable {
@@ -1605,19 +1392,10 @@ declare_lint! {
     "detects edition keywords being used as an identifier"
 }
 
-/// Check for uses of edition keywords used as an identifier.
-#[derive(Copy, Clone)]
-pub struct KeywordIdents;
-
-impl LintPass for KeywordIdents {
-    fn name(&self) -> &'static str {
-        "KeywordIdents"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(KEYWORD_IDENTS)
-    }
-}
+declare_lint_pass!(
+    /// Check for uses of edition keywords used as an identifier.
+    KeywordIdents => [KEYWORD_IDENTS]
+);
 
 struct UnderMacro(bool);
 
@@ -1740,18 +1518,7 @@ impl EarlyLintPass for KeywordIdents {
     }
 }
 
-
-pub struct ExplicitOutlivesRequirements;
-
-impl LintPass for ExplicitOutlivesRequirements {
-    fn name(&self) -> &'static str {
-        "ExplicitOutlivesRequirements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array![EXPLICIT_OUTLIVES_REQUIREMENTS]
-    }
-}
+declare_lint_pass!(ExplicitOutlivesRequirements => [EXPLICIT_OUTLIVES_REQUIREMENTS]);
 
 impl ExplicitOutlivesRequirements {
     fn collect_outlives_bound_spans(
diff --git a/src/librustc_lint/lib.rs b/src/librustc_lint/lib.rs
index c9301a32d83..7e77962a16e 100644
--- a/src/librustc_lint/lib.rs
+++ b/src/librustc_lint/lib.rs
@@ -20,6 +20,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
@@ -61,6 +62,7 @@ use nonstandard_style::*;
 use builtin::*;
 use types::*;
 use unused::*;
+use rustc::lint::internal::*;
 
 /// Useful for other parts of the compiler.
 pub use builtin::SoftLints;
@@ -488,3 +490,18 @@ pub fn register_builtins(store: &mut lint::LintStore, sess: Option<&Session>) {
     store.register_removed("bad_repr",
         "replaced with a generic attribute input check");
 }
+
+pub fn register_internals(store: &mut lint::LintStore, sess: Option<&Session>) {
+    store.register_early_pass(sess, false, false, box DefaultHashTypes::new());
+    store.register_late_pass(sess, false, false, false, box TyKindUsage);
+    store.register_group(
+        sess,
+        false,
+        "internal",
+        None,
+        vec![
+            LintId::of(DEFAULT_HASH_TYPES),
+            LintId::of(USAGE_OF_TY_TYKIND),
+        ],
+    );
+}
diff --git a/src/librustc_lint/nonstandard_style.rs b/src/librustc_lint/nonstandard_style.rs
index 7a164dbcdf1..1d8979f7d1c 100644
--- a/src/librustc_lint/nonstandard_style.rs
+++ b/src/librustc_lint/nonstandard_style.rs
@@ -38,6 +38,8 @@ declare_lint! {
     "types, variants, traits and type parameters should have camel case names"
 }
 
+declare_lint_pass!(NonCamelCaseTypes => [NON_CAMEL_CASE_TYPES]);
+
 fn char_has_case(c: char) -> bool {
     c.is_lowercase() || c.is_uppercase()
 }
@@ -105,9 +107,6 @@ fn to_camel_case(s: &str) -> String {
         .0
 }
 
-#[derive(Copy, Clone)]
-pub struct NonCamelCaseTypes;
-
 impl NonCamelCaseTypes {
     fn check_case(&self, cx: &EarlyContext<'_>, sort: &str, ident: &Ident) {
         let name = &ident.name.as_str();
@@ -126,16 +125,6 @@ impl NonCamelCaseTypes {
     }
 }
 
-impl LintPass for NonCamelCaseTypes {
-    fn name(&self) -> &'static str {
-        "NonCamelCaseTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_CAMEL_CASE_TYPES)
-    }
-}
-
 impl EarlyLintPass for NonCamelCaseTypes {
     fn check_item(&mut self, cx: &EarlyContext<'_>, it: &ast::Item) {
         let has_repr_c = it.attrs
@@ -173,8 +162,7 @@ declare_lint! {
     "variables, methods, functions, lifetime parameters and modules should have snake case names"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonSnakeCase;
+declare_lint_pass!(NonSnakeCase => [NON_SNAKE_CASE]);
 
 impl NonSnakeCase {
     fn to_snake_case(mut str: &str) -> String {
@@ -256,16 +244,6 @@ impl NonSnakeCase {
     }
 }
 
-impl LintPass for NonSnakeCase {
-    fn name(&self) -> &'static str {
-        "NonSnakeCase"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_SNAKE_CASE)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonSnakeCase {
     fn check_mod(&mut self, cx: &LateContext<'_, '_>, _: &'tcx hir::Mod, _: Span, id: hir::HirId) {
         if id != hir::CRATE_HIR_ID {
@@ -387,8 +365,7 @@ declare_lint! {
     "static constants should have uppercase identifiers"
 }
 
-#[derive(Copy, Clone)]
-pub struct NonUpperCaseGlobals;
+declare_lint_pass!(NonUpperCaseGlobals => [NON_UPPER_CASE_GLOBALS]);
 
 impl NonUpperCaseGlobals {
     fn check_upper_case(cx: &LateContext<'_, '_>, sort: &str, ident: &Ident) {
@@ -410,16 +387,6 @@ impl NonUpperCaseGlobals {
     }
 }
 
-impl LintPass for NonUpperCaseGlobals {
-    fn name(&self) -> &'static str {
-        "NonUpperCaseGlobals"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(NON_UPPER_CASE_GLOBALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for NonUpperCaseGlobals {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
         match it.node {
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index 494a9bb73ed..7423ce2e760 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -49,23 +49,14 @@ pub struct TypeLimits {
     negated_expr_id: hir::HirId,
 }
 
+impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS]);
+
 impl TypeLimits {
     pub fn new() -> TypeLimits {
         TypeLimits { negated_expr_id: hir::DUMMY_HIR_ID }
     }
 }
 
-impl LintPass for TypeLimits {
-    fn name(&self) -> &'static str {
-        "TypeLimits"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_COMPARISONS,
-                    OVERFLOWING_LITERALS)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'a, 'tcx>, e: &'tcx hir::Expr) {
         match e.node {
@@ -104,7 +95,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                         report_bin_hex_error(
                                             cx,
                                             e,
-                                            ty::Int(t),
+                                            attr::IntType::SignedInt(t),
                                             repr_str,
                                             v,
                                             negative,
@@ -159,7 +150,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                                 report_bin_hex_error(
                                     cx,
                                     e,
-                                    ty::Uint(t),
+                                    attr::IntType::UnsignedInt(t),
                                     repr_str,
                                     lit_val,
                                     false,
@@ -321,7 +312,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
         //
         // No suggestion for: `isize`, `usize`.
         fn get_type_suggestion<'a>(
-            t: &ty::TyKind<'_>,
+            t: Ty<'_>,
             val: u128,
             negative: bool,
         ) -> Option<String> {
@@ -347,14 +338,14 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                     }
                 }
             }
-            match t {
-                &ty::Int(i) => find_fit!(i, val, negative,
+            match t.sty {
+                ty::Int(i) => find_fit!(i, val, negative,
                               I8 => [U8] => [I16, I32, I64, I128],
                               I16 => [U16] => [I32, I64, I128],
                               I32 => [U32] => [I64, I128],
                               I64 => [U64] => [I128],
                               I128 => [U128] => []),
-                &ty::Uint(u) => find_fit!(u, val, negative,
+                ty::Uint(u) => find_fit!(u, val, negative,
                               U8 => [U8, U16, U32, U64, U128] => [],
                               U16 => [U16, U32, U64, U128] => [],
                               U32 => [U32, U64, U128] => [],
@@ -367,25 +358,21 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
         fn report_bin_hex_error(
             cx: &LateContext<'_, '_>,
             expr: &hir::Expr,
-            ty: ty::TyKind<'_>,
+            ty: attr::IntType,
             repr_str: String,
             val: u128,
             negative: bool,
         ) {
+            let size = layout::Integer::from_attr(&cx.tcx, ty).size();
             let (t, actually) = match ty {
-                ty::Int(t) => {
-                    let ity = attr::IntType::SignedInt(t);
-                    let size = layout::Integer::from_attr(&cx.tcx, ity).size();
+                attr::IntType::SignedInt(t) => {
                     let actually = sign_extend(val, size) as i128;
                     (format!("{:?}", t), actually.to_string())
                 }
-                ty::Uint(t) => {
-                    let ity = attr::IntType::UnsignedInt(t);
-                    let size = layout::Integer::from_attr(&cx.tcx, ity).size();
+                attr::IntType::UnsignedInt(t) => {
                     let actually = truncate(val, size);
                     (format!("{:?}", t), actually.to_string())
                 }
-                _ => bug!(),
             };
             let mut err = cx.struct_span_lint(
                 OVERFLOWING_LITERALS,
@@ -398,7 +385,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for TypeLimits {
                 repr_str, val, t, actually, t
             ));
             if let Some(sugg_ty) =
-                get_type_suggestion(&cx.tables.node_type(expr.hir_id).sty, val, negative)
+                get_type_suggestion(&cx.tables.node_type(expr.hir_id), val, negative)
             {
                 if let Some(pos) = repr_str.chars().position(|c| c == 'i' || c == 'u') {
                     let (sans_suffix, _) = repr_str.split_at(pos);
@@ -424,6 +411,8 @@ declare_lint! {
     "proper use of libc types in foreign modules"
 }
 
+declare_lint_pass!(ImproperCTypes => [IMPROPER_CTYPES]);
+
 struct ImproperCTypesVisitor<'a, 'tcx: 'a> {
     cx: &'a LateContext<'a, 'tcx>,
 }
@@ -793,19 +782,6 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
     }
 }
 
-#[derive(Copy, Clone)]
-pub struct ImproperCTypes;
-
-impl LintPass for ImproperCTypes {
-    fn name(&self) -> &'static str {
-        "ImproperCTypes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(IMPROPER_CTYPES)
-    }
-}
-
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     fn check_foreign_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::ForeignItem) {
         let mut vis = ImproperCTypesVisitor { cx };
@@ -824,17 +800,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for ImproperCTypes {
     }
 }
 
-pub struct VariantSizeDifferences;
-
-impl LintPass for VariantSizeDifferences {
-    fn name(&self) -> &'static str {
-        "VariantSizeDifferences"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(VARIANT_SIZE_DIFFERENCES)
-    }
-}
+declare_lint_pass!(VariantSizeDifferences => [VARIANT_SIZE_DIFFERENCES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for VariantSizeDifferences {
     fn check_item(&mut self, cx: &LateContext<'_, '_>, it: &hir::Item) {
diff --git a/src/librustc_lint/unused.rs b/src/librustc_lint/unused.rs
index 37c147d93d8..d41d97f58bc 100644
--- a/src/librustc_lint/unused.rs
+++ b/src/librustc_lint/unused.rs
@@ -32,18 +32,7 @@ declare_lint! {
     "unused result of an expression in a statement"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedResults;
-
-impl LintPass for UnusedResults {
-    fn name(&self) -> &'static str {
-        "UnusedResults"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_MUST_USE, UNUSED_RESULTS)
-    }
-}
+declare_lint_pass!(UnusedResults => [UNUSED_MUST_USE, UNUSED_RESULTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedResults {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -203,18 +192,7 @@ declare_lint! {
     "path statements with no effect"
 }
 
-#[derive(Copy, Clone)]
-pub struct PathStatements;
-
-impl LintPass for PathStatements {
-    fn name(&self) -> &'static str {
-        "PathStatements"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(PATH_STATEMENTS)
-    }
-}
+declare_lint_pass!(PathStatements => [PATH_STATEMENTS]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for PathStatements {
     fn check_stmt(&mut self, cx: &LateContext<'_, '_>, s: &hir::Stmt) {
@@ -232,18 +210,7 @@ declare_lint! {
     "detects attributes that were not used by the compiler"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAttributes;
-
-impl LintPass for UnusedAttributes {
-    fn name(&self) -> &'static str {
-        "UnusedAttributes"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ATTRIBUTES)
-    }
-}
+declare_lint_pass!(UnusedAttributes => [UNUSED_ATTRIBUTES]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAttributes {
     fn check_attribute(&mut self, cx: &LateContext<'_, '_>, attr: &ast::Attribute) {
@@ -305,8 +272,7 @@ declare_lint! {
     "`if`, `match`, `while` and `return` do not need parentheses"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedParens;
+declare_lint_pass!(UnusedParens => [UNUSED_PARENS]);
 
 impl UnusedParens {
     fn check_unused_parens_expr(&self,
@@ -383,16 +349,6 @@ impl UnusedParens {
     }
 }
 
-impl LintPass for UnusedParens {
-    fn name(&self) -> &'static str {
-        "UnusedParens"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_PARENS)
-    }
-}
-
 impl EarlyLintPass for UnusedParens {
     fn check_expr(&mut self, cx: &EarlyContext<'_>, e: &ast::Expr) {
         use syntax::ast::ExprKind::*;
@@ -465,8 +421,7 @@ declare_lint! {
     "unnecessary braces around an imported item"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedImportBraces;
+declare_lint_pass!(UnusedImportBraces => [UNUSED_IMPORT_BRACES]);
 
 impl UnusedImportBraces {
     fn check_use_tree(&self, cx: &EarlyContext<'_>, use_tree: &ast::UseTree, item: &ast::Item) {
@@ -505,16 +460,6 @@ impl UnusedImportBraces {
     }
 }
 
-impl LintPass for UnusedImportBraces {
-    fn name(&self) -> &'static str {
-        "UnusedImportBraces"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_IMPORT_BRACES)
-    }
-}
-
 impl EarlyLintPass for UnusedImportBraces {
     fn check_item(&mut self, cx: &EarlyContext<'_>, item: &ast::Item) {
         if let ast::ItemKind::Use(ref use_tree) = item.node {
@@ -529,18 +474,7 @@ declare_lint! {
     "detects unnecessary allocations that can be eliminated"
 }
 
-#[derive(Copy, Clone)]
-pub struct UnusedAllocation;
-
-impl LintPass for UnusedAllocation {
-    fn name(&self) -> &'static str {
-        "UnusedAllocation"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(UNUSED_ALLOCATION)
-    }
-}
+declare_lint_pass!(UnusedAllocation => [UNUSED_ALLOCATION]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnusedAllocation {
     fn check_expr(&mut self, cx: &LateContext<'_, '_>, e: &hir::Expr) {
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 14416b5ce07..4078171733f 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -14,6 +14,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 extern crate libc;
 #[allow(unused_extern_crates)]
diff --git a/src/librustc_mir/borrow_check/error_reporting.rs b/src/librustc_mir/borrow_check/error_reporting.rs
index c04a36fe9c6..01c06739e29 100644
--- a/src/librustc_mir/borrow_check/error_reporting.rs
+++ b/src/librustc_mir/borrow_check/error_reporting.rs
@@ -223,7 +223,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     Some(ref name) => format!("`{}`", name),
                     None => "value".to_owned(),
                 };
-                if let ty::TyKind::Param(param_ty) = ty.sty {
+                if let ty::Param(param_ty) = ty.sty {
                     let tcx = self.infcx.tcx;
                     let generics = tcx.generics_of(self.mir_def_id);
                     let def_id = generics.type_param(&param_ty, tcx).def_id;
@@ -1529,7 +1529,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         if let TerminatorKind::Call {
             func: Operand::Constant(box Constant {
                 literal: ty::Const {
-                    ty: &ty::TyS { sty: ty::TyKind::FnDef(id, _), ..  },
+                    ty: &ty::TyS { sty: ty::FnDef(id, _), ..  },
                     ..
                 },
                 ..
@@ -1547,7 +1547,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 };
 
                 debug!("add_moved_or_invoked_closure_note: closure={:?}", closure);
-                if let ty::TyKind::Closure(did, _) = self.mir.local_decls[closure].ty.sty {
+                if let ty::Closure(did, _) = self.mir.local_decls[closure].ty.sty {
                     let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();
 
                     if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
@@ -1570,7 +1570,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
         // Check if we are just moving a closure after it has been invoked.
         if let Some(target) = target {
-            if let ty::TyKind::Closure(did, _) = self.mir.local_decls[target].ty.sty {
+            if let ty::Closure(did, _) = self.mir.local_decls[target].ty.sty {
                 let hir_id = self.infcx.tcx.hir().as_local_hir_id(did).unwrap();
 
                 if let Some((span, name)) = self.infcx.tcx.typeck_tables_of(did)
@@ -1919,7 +1919,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
             } else {
                 let ty = self.infcx.tcx.type_of(self.mir_def_id);
                 match ty.sty {
-                    ty::TyKind::FnDef(_, _) | ty::TyKind::FnPtr(_) => self.annotate_fn_sig(
+                    ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
                         self.mir_def_id,
                         self.infcx.tcx.fn_sig(self.mir_def_id),
                     ),
@@ -2164,12 +2164,12 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         //    anything.
         let return_ty = sig.output();
         match return_ty.skip_binder().sty {
-            ty::TyKind::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
+            ty::Ref(return_region, _, _) if return_region.has_name() && !is_closure => {
                 // This is case 1 from above, return type is a named reference so we need to
                 // search for relevant arguments.
                 let mut arguments = Vec::new();
                 for (index, argument) in sig.inputs().skip_binder().iter().enumerate() {
-                    if let ty::TyKind::Ref(argument_region, _, _) = argument.sty {
+                    if let ty::Ref(argument_region, _, _) = argument.sty {
                         if argument_region == return_region {
                             // Need to use the `rustc::ty` types to compare against the
                             // `return_region`. Then use the `rustc::hir` type to get only
@@ -2206,7 +2206,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                     return_span,
                 })
             }
-            ty::TyKind::Ref(_, _, _) if is_closure => {
+            ty::Ref(_, _, _) if is_closure => {
                 // This is case 2 from above but only for closures, return type is anonymous
                 // reference so we select
                 // the first argument.
@@ -2215,9 +2215,9 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 // Closure arguments are wrapped in a tuple, so we need to get the first
                 // from that.
-                if let ty::TyKind::Tuple(elems) = argument_ty.sty {
+                if let ty::Tuple(elems) = argument_ty.sty {
                     let argument_ty = elems.first()?;
-                    if let ty::TyKind::Ref(_, _, _) = argument_ty.sty {
+                    if let ty::Ref(_, _, _) = argument_ty.sty {
                         return Some(AnnotatedBorrowFnSignature::Closure {
                             argument_ty,
                             argument_span,
@@ -2227,7 +2227,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 None
             }
-            ty::TyKind::Ref(_, _, _) => {
+            ty::Ref(_, _, _) => {
                 // This is also case 2 from above but for functions, return type is still an
                 // anonymous reference so we select the first argument.
                 let argument_span = fn_decl.inputs.first()?.span;
@@ -2238,7 +2238,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
 
                 // We expect the first argument to be a reference.
                 match argument_ty.sty {
-                    ty::TyKind::Ref(_, _, _) => {}
+                    ty::Ref(_, _, _) => {}
                     _ => return None,
                 }
 
@@ -2366,8 +2366,8 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         // this by hooking into the pretty printer and telling it to label the
         // lifetimes without names with the value `'0`.
         match ty.sty {
-            ty::TyKind::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
-            | ty::TyKind::Ref(
+            ty::Ref(ty::RegionKind::ReLateBound(_, br), _, _)
+            | ty::Ref(
                 ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }),
                 _,
                 _,
@@ -2386,7 +2386,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
         let mut printer = ty::print::FmtPrinter::new(self.infcx.tcx, &mut s, Namespace::TypeNS);
 
         let region = match ty.sty {
-            ty::TyKind::Ref(region, _, _) => {
+            ty::Ref(region, _, _) => {
                 match region {
                     ty::RegionKind::ReLateBound(_, br)
                     | ty::RegionKind::RePlaceholder(ty::PlaceholderRegion { name: br, .. }) => {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index a8c151a22ee..bf297ae0deb 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -1741,7 +1741,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                 // no move out from an earlier location) then this is an attempt at initialization
                 // of the union - we should error in that case.
                 let tcx = this.infcx.tcx;
-                if let ty::TyKind::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
+                if let ty::Adt(def, _) = base.ty(this.mir, tcx).ty.sty {
                     if def.is_union() {
                         if this.move_data.path_map[mpi].iter().any(|moi| {
                             this.move_data.moves[*moi].source.is_predecessor_of(
diff --git a/src/librustc_mir/borrow_check/move_errors.rs b/src/librustc_mir/borrow_check/move_errors.rs
index b6e7996586e..7efe1d83c2e 100644
--- a/src/librustc_mir/borrow_check/move_errors.rs
+++ b/src/librustc_mir/borrow_check/move_errors.rs
@@ -532,7 +532,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                     if let StatementKind::Assign(_, box Rvalue::Ref(_, _, source)) = &stmt.kind {
                         let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
-                            ty::TyKind::Ref(_, ty, _) => ty,
+                            ty::Ref(_, ty, _) => ty,
                             _ => ty,
                         };
                         debug!("borrowed_content_source: ty={:?}", ty);
@@ -557,7 +557,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
 
                         let ty = source.ty(self.mir, self.infcx.tcx).ty;
                         let ty = match ty.sty {
-                            ty::TyKind::Ref(_, ty, _) => ty,
+                            ty::Ref(_, ty, _) => ty,
                             _ => ty,
                         };
                         debug!("borrowed_content_source: ty={:?}", ty);
diff --git a/src/librustc_mir/borrow_check/mutability_errors.rs b/src/librustc_mir/borrow_check/mutability_errors.rs
index 8a55a59b15b..b780511315d 100644
--- a/src/librustc_mir/borrow_check/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/mutability_errors.rs
@@ -5,7 +5,7 @@ use rustc::mir::{
     Mutability, Operand, Place, PlaceBase, Projection, ProjectionElem, Static, StaticKind,
 };
 use rustc::mir::{Terminator, TerminatorKind};
-use rustc::ty::{self, Const, DefIdTree, TyS, TyKind, TyCtxt};
+use rustc::ty::{self, Const, DefIdTree, TyS, TyCtxt};
 use rustc_data_structures::indexed_vec::Idx;
 use syntax_pos::Span;
 use syntax_pos::symbol::keywords;
@@ -261,7 +261,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                             // Otherwise, check if the name is the self kewyord - in which case
                             // we have an explicit self. Do the same thing in this case and check
                             // for a `self: &mut Self` to suggest removing the `&mut`.
-                            if let ty::TyKind::Ref(
+                            if let ty::Ref(
                                 _, _, hir::Mutability::MutMutable
                             ) = local_decl.ty.sty {
                                 true
@@ -476,7 +476,7 @@ impl<'a, 'gcx, 'tcx> MirBorrowckCtxt<'a, 'gcx, 'tcx> {
                                     func: Operand::Constant(box Constant {
                                         literal: Const {
                                             ty: &TyS {
-                                                sty: TyKind::FnDef(id, substs),
+                                                sty: ty::FnDef(id, substs),
                                                 ..
                                             },
                                             ..
@@ -633,8 +633,8 @@ fn annotate_struct_field(
     field: &mir::Field,
 ) -> Option<(Span, String)> {
     // Expect our local to be a reference to a struct of some kind.
-    if let ty::TyKind::Ref(_, ty, _) = ty.sty {
-        if let ty::TyKind::Adt(def, _) = ty.sty {
+    if let ty::Ref(_, ty, _) = ty.sty {
+        if let ty::Adt(def, _) = ty.sty {
             let field = def.all_fields().nth(field.index())?;
             // Use the HIR types to construct the diagnostic message.
             let hir_id = tcx.hir().as_local_hir_id(field.did)?;
diff --git a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
index 67b77605f3c..e30938bc326 100644
--- a/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/explain_borrow/mod.rs
@@ -589,7 +589,7 @@ impl<'cx, 'gcx, 'tcx> MirBorrowckCtxt<'cx, 'gcx, 'tcx> {
                                 // Check the type for a trait object.
                                 return match ty.sty {
                                     // `&dyn Trait`
-                                    ty::TyKind::Ref(_, ty, _) if ty.is_trait() => true,
+                                    ty::Ref(_, ty, _) if ty.is_trait() => true,
                                     // `Box<dyn Trait>`
                                     _ if ty.is_box() && ty.boxed_ty().is_trait() => true,
                                     // `dyn Trait`
diff --git a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
index 3773f1a40c7..917e383cae8 100644
--- a/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/region_infer/error_reporting/mod.rs
@@ -583,7 +583,7 @@ impl<'tcx> RegionInferenceContext<'tcx> {
             (self.to_error_region(fr), self.to_error_region(outlived_fr))
         {
             if let Some(ty::TyS {
-                sty: ty::TyKind::Opaque(did, substs),
+                sty: ty::Opaque(did, substs),
                 ..
             }) = infcx
                 .tcx
diff --git a/src/librustc_mir/borrow_check/nll/type_check/mod.rs b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
index b06ebbdbf34..ec5637d1707 100644
--- a/src/librustc_mir/borrow_check/nll/type_check/mod.rs
+++ b/src/librustc_mir/borrow_check/nll/type_check/mod.rs
@@ -39,7 +39,7 @@ use rustc::traits::{ObligationCause, PredicateObligations};
 use rustc::ty::fold::TypeFoldable;
 use rustc::ty::subst::{Subst, SubstsRef, UnpackedKind, UserSubsts};
 use rustc::ty::{
-    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, TyKind, UserType,
+    self, RegionVid, ToPolyTraitRef, Ty, TyCtxt, UserType,
     CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations,
     UserTypeAnnotationIndex,
 };
@@ -746,7 +746,7 @@ impl<'a, 'b, 'gcx, 'tcx> TypeVerifier<'a, 'b, 'gcx, 'tcx> {
         let (variant, substs) = match base_ty {
             PlaceTy { ty, variant_index: Some(variant_index) } => {
                 match ty.sty {
-                    ty::TyKind::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
+                    ty::Adt(adt_def, substs) => (&adt_def.variants[variant_index], substs),
                     _ => bug!("can't have downcast of non-adt type"),
                 }
             }
@@ -1136,7 +1136,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
         category: ConstraintCategory,
     ) -> Fallible<()> {
         if let Err(terr) = self.sub_types(sub, sup, locations, category) {
-            if let TyKind::Opaque(..) = sup.sty {
+            if let ty::Opaque(..) = sup.sty {
                 // When you have `let x: impl Foo = ...` in a closure,
                 // the resulting inferend values are stored with the
                 // def-id of the base function.
@@ -1389,7 +1389,7 @@ impl<'a, 'gcx, 'tcx> TypeChecker<'a, 'gcx, 'tcx> {
             } => {
                 let place_type = place.ty(mir, tcx).ty;
                 let adt = match place_type.sty {
-                    TyKind::Adt(adt, _) if adt.is_enum() => adt,
+                    ty::Adt(adt, _) if adt.is_enum() => adt,
                     _ => {
                         span_bug!(
                             stmt.source_info.span,
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 011dc54f3b3..2471c01e3f3 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -425,7 +425,7 @@ impl<'b, 'a, 'gcx, 'tcx> Gatherer<'b, 'a, 'gcx, 'tcx> {
                 base,
                 elem: ProjectionElem::Field(_, _),
             }) if match base.ty(self.builder.mir, self.builder.tcx).ty.sty {
-                    ty::TyKind::Adt(def, _) if def.is_union() => true,
+                    ty::Adt(def, _) if def.is_union() => true,
                     _ => false,
             } => base,
             // Otherwise, lookup the place.
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 303ffcb3bfb..a9c521f59a9 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1754,7 +1754,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                     // they should be pointing to memory is when they are subslices of nonzero
                     // slices
                     let (opt_ptr, n, ty) = match value.ty.sty {
-                        ty::TyKind::Array(t, n) => {
+                        ty::Array(t, n) => {
                             match value.val {
                                 ConstValue::ByRef(ptr, alloc) => (
                                     Some((ptr, alloc)),
@@ -1767,7 +1767,7 @@ fn specialize<'p, 'a: 'p, 'tcx: 'a>(
                                 ),
                             }
                         },
-                        ty::TyKind::Slice(t) => {
+                        ty::Slice(t) => {
                             match value.val {
                                 ConstValue::Slice(ptr, n) => (
                                     ptr.to_ptr().ok().map(|ptr| (
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 50df676aea9..7ded973701e 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -10,7 +10,7 @@ use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::mem_categorization::cmt_;
 use rustc::middle::region;
 use rustc::session::Session;
-use rustc::ty::{self, Ty, TyCtxt, TyKind};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::ty::subst::{InternalSubsts, SubstsRef};
 use rustc::lint;
 use rustc_errors::{Applicability, DiagnosticBuilder};
@@ -481,7 +481,7 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
             }
             let patterns = witnesses.iter().map(|p| (**p).clone()).collect::<Vec<Pattern<'_>>>();
             if patterns.len() < 4 {
-                for sp in maybe_point_at_variant(cx, &scrut_ty.sty, patterns.as_slice()) {
+                for sp in maybe_point_at_variant(cx, scrut_ty, patterns.as_slice()) {
                     err.span_label(sp, "not covered");
                 }
             }
@@ -498,11 +498,11 @@ fn check_exhaustive<'p, 'a: 'p, 'tcx: 'a>(
 
 fn maybe_point_at_variant(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
-    sty: &TyKind<'tcx>,
+    ty: Ty<'tcx>,
     patterns: &[Pattern<'_>],
 ) -> Vec<Span> {
     let mut covered = vec![];
-    if let ty::Adt(def, _) = sty {
+    if let ty::Adt(def, _) = ty.sty {
         // Don't point at variants that have already been covered due to other patterns to avoid
         // visual clutter
         for pattern in patterns {
@@ -518,7 +518,7 @@ fn maybe_point_at_variant(
                         .map(|field_pattern| field_pattern.pattern.clone())
                         .collect::<Vec<_>>();
                     covered.extend(
-                        maybe_point_at_variant(cx, sty, subpatterns.as_slice()),
+                        maybe_point_at_variant(cx, ty, subpatterns.as_slice()),
                     );
                 }
             }
@@ -526,7 +526,7 @@ fn maybe_point_at_variant(
                 let subpatterns = subpatterns.iter()
                     .map(|field_pattern| field_pattern.pattern.clone())
                     .collect::<Vec<_>>();
-                covered.extend(maybe_point_at_variant(cx, sty, subpatterns.as_slice()));
+                covered.extend(maybe_point_at_variant(cx, ty, subpatterns.as_slice()));
             }
         }
     }
diff --git a/src/librustc_mir/lib.rs b/src/librustc_mir/lib.rs
index c45e694ebf8..deeed9a0b98 100644
--- a/src/librustc_mir/lib.rs
+++ b/src/librustc_mir/lib.rs
@@ -28,6 +28,7 @@ Rust MIR: a lowered representation of Rust. Also: an experiment!
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
diff --git a/src/librustc_mir/lints.rs b/src/librustc_mir/lints.rs
index 6d6a3f91472..572f7133cad 100644
--- a/src/librustc_mir/lints.rs
+++ b/src/librustc_mir/lints.rs
@@ -4,7 +4,7 @@ use rustc::hir::intravisit::FnKind;
 use rustc::hir::map::blocks::FnLikeNode;
 use rustc::lint::builtin::UNCONDITIONAL_RECURSION;
 use rustc::mir::{self, Mir, TerminatorKind};
-use rustc::ty::{AssociatedItem, AssociatedItemContainer, Instance, TyCtxt, TyKind};
+use rustc::ty::{self, AssociatedItem, AssociatedItemContainer, Instance, TyCtxt};
 use rustc::ty::subst::InternalSubsts;
 
 pub fn check(tcx: TyCtxt<'a, 'tcx, 'tcx>,
@@ -86,7 +86,7 @@ fn check_fn_for_unconditional_recursion(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                 TerminatorKind::Call { ref func, .. } => {
                     let func_ty = func.ty(mir, tcx);
 
-                    if let TyKind::FnDef(fn_def_id, substs) = func_ty.sty {
+                    if let ty::FnDef(fn_def_id, substs) = func_ty.sty {
                         let (call_fn_id, call_substs) =
                             if let Some(instance) = Instance::resolve(tcx,
                                                                         param_env,
diff --git a/src/librustc_mir/transform/instcombine.rs b/src/librustc_mir/transform/instcombine.rs
index 7e925f65ee2..8187a81f0ed 100644
--- a/src/librustc_mir/transform/instcombine.rs
+++ b/src/librustc_mir/transform/instcombine.rs
@@ -2,7 +2,7 @@
 
 use rustc::mir::{Constant, Location, Place, PlaceBase, Mir, Operand, ProjectionElem, Rvalue, Local};
 use rustc::mir::visit::{MutVisitor, Visitor};
-use rustc::ty::{TyCtxt, TyKind};
+use rustc::ty::{self, TyCtxt};
 use rustc::util::nodemap::{FxHashMap, FxHashSet};
 use rustc_data_structures::indexed_vec::Idx;
 use std::mem;
@@ -90,7 +90,7 @@ impl<'b, 'a, 'tcx> Visitor<'tcx> for OptimizationFinder<'b, 'a, 'tcx> {
 
         if let Rvalue::Len(ref place) = *rvalue {
             let place_ty = place.ty(&self.mir.local_decls, self.tcx).ty;
-            if let TyKind::Array(_, len) = place_ty.sty {
+            if let ty::Array(_, len) = place_ty.sty {
                 let span = self.mir.source_info(location).span;
                 let ty = self.tcx.types.usize;
                 let constant = Constant { span, ty, literal: len, user_ty: None };
diff --git a/src/librustc_mir/transform/lower_128bit.rs b/src/librustc_mir/transform/lower_128bit.rs
index dda9457cc8c..fd9d6bb5760 100644
--- a/src/librustc_mir/transform/lower_128bit.rs
+++ b/src/librustc_mir/transform/lower_128bit.rs
@@ -3,7 +3,7 @@
 use rustc::hir::def_id::DefId;
 use rustc::middle::lang_items::LangItem;
 use rustc::mir::*;
-use rustc::ty::{List, Ty, TyCtxt, TyKind};
+use rustc::ty::{self, List, Ty, TyCtxt};
 use rustc_data_structures::indexed_vec::{Idx};
 use crate::transform::{MirPass, MirSource};
 
@@ -183,8 +183,8 @@ impl RhsKind {
 
 fn sign_of_128bit(ty: Ty<'_>) -> Option<bool> {
     match ty.sty {
-        TyKind::Int(syntax::ast::IntTy::I128) => Some(true),
-        TyKind::Uint(syntax::ast::UintTy::U128) => Some(false),
+        ty::Int(syntax::ast::IntTy::I128) => Some(true),
+        ty::Uint(syntax::ast::UintTy::U128) => Some(false),
         _ => None,
     }
 }
diff --git a/src/librustc_passes/lib.rs b/src/librustc_passes/lib.rs
index ff2e345d084..20442a4a566 100644
--- a/src/librustc_passes/lib.rs
+++ b/src/librustc_passes/lib.rs
@@ -12,6 +12,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use]
 extern crate rustc;
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index 030883c0159..9a8970b2935 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -1,6 +1,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(nll)]
 #![feature(rustc_diagnostic_macros)]
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 1934f800af7..5216156c0ca 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -8,6 +8,7 @@
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 pub use rustc::hir::def::{Namespace, PerNS};
 
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 898ea62046d..a363fe11418 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -2,6 +2,7 @@
 #![feature(custom_attribute)]
 #![feature(nll)]
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(unused_attributes)]
 
 #![recursion_limit="256"]
diff --git a/src/librustc_target/lib.rs b/src/librustc_target/lib.rs
index efffb198572..f1812c20dcc 100644
--- a/src/librustc_target/lib.rs
+++ b/src/librustc_target/lib.rs
@@ -16,6 +16,7 @@
 #![feature(step_trait)]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #[macro_use] extern crate log;
 
diff --git a/src/librustc_traits/lib.rs b/src/librustc_traits/lib.rs
index d52a976981d..bc034e1fb16 100644
--- a/src/librustc_traits/lib.rs
+++ b/src/librustc_traits/lib.rs
@@ -2,6 +2,7 @@
 //! the guts are broken up into modules; see the comments in those modules.
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(crate_visibility_modifier)]
 #![feature(in_band_lifetimes)]
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index fba4414c127..8805dade40e 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -99,11 +99,6 @@ enum GenericArgPosition {
     MethodCall,
 }
 
-/// Dummy type used for the `Self` of a `TraitRef` created for converting
-/// a trait object, and which gets removed in `ExistentialTraitRef`.
-/// This type must not appear anywhere in other converted types.
-const TRAIT_OBJECT_DUMMY_SELF: ty::TyKind<'static> = ty::Infer(ty::FreshTy(0));
-
 impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
     pub fn ast_region_to_region(&self,
         lifetime: &hir::Lifetime,
@@ -595,7 +590,9 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             infer_types,
         );
 
-        let is_object = self_ty.map_or(false, |ty| ty.sty == TRAIT_OBJECT_DUMMY_SELF);
+        let is_object = self_ty.map_or(false, |ty| {
+            ty == self.tcx().types.trait_object_dummy_self
+        });
         let default_needs_object_self = |param: &ty::GenericParamDef| {
             if let GenericParamDefKind::Type { has_default, .. } = param.kind {
                 if is_object && has_default {
@@ -956,10 +953,10 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
     }
 
     /// Transform a `PolyTraitRef` into a `PolyExistentialTraitRef` by
-    /// removing the dummy `Self` type (`TRAIT_OBJECT_DUMMY_SELF`).
+    /// removing the dummy `Self` type (`trait_object_dummy_self`).
     fn trait_ref_to_existential(&self, trait_ref: ty::TraitRef<'tcx>)
                                 -> ty::ExistentialTraitRef<'tcx> {
-        if trait_ref.self_ty().sty != TRAIT_OBJECT_DUMMY_SELF {
+        if trait_ref.self_ty() != self.tcx().types.trait_object_dummy_self {
             bug!("trait_ref_to_existential called on {:?} with non-dummy Self", trait_ref);
         }
         ty::ExistentialTraitRef::erase_self_ty(self.tcx(), trait_ref)
@@ -980,7 +977,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
         }
 
         let mut projection_bounds = Vec::new();
-        let dummy_self = tcx.mk_ty(TRAIT_OBJECT_DUMMY_SELF);
+        let dummy_self = self.tcx().types.trait_object_dummy_self;
         let (principal, potential_assoc_types) = self.instantiate_poly_trait_ref(
             &trait_bounds[0],
             dummy_self,
@@ -1030,7 +1027,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
                 }
                 ty::Predicate::Projection(pred) => {
                     // A `Self` within the original bound will be substituted with a
-                    // `TRAIT_OBJECT_DUMMY_SELF`, so check for that.
+                    // `trait_object_dummy_self`, so check for that.
                     let references_self =
                         pred.skip_binder().ty.walk().any(|t| t == dummy_self);
 
@@ -1130,7 +1127,7 @@ impl<'o, 'gcx: 'tcx, 'tcx> dyn AstConv<'gcx, 'tcx> + 'o {
             err.emit();
         }
 
-        // Erase the `dummy_self` (`TRAIT_OBJECT_DUMMY_SELF`) used above.
+        // Erase the `dummy_self` (`trait_object_dummy_self`) used above.
         let existential_principal = principal.map_bound(|trait_ref| {
             self.trait_ref_to_existential(trait_ref)
         });
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 3579810b8d7..d108e7c3107 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -3,7 +3,7 @@ use crate::constrained_generic_params::{identify_constrained_generic_params, Par
 
 use crate::hir::def_id::DefId;
 use rustc::traits::{self, ObligationCauseCode};
-use rustc::ty::{self, Lift, Ty, TyCtxt, TyKind, GenericParamDefKind, TypeFoldable, ToPredicate};
+use rustc::ty::{self, Lift, Ty, TyCtxt, GenericParamDefKind, TypeFoldable, ToPredicate};
 use rustc::ty::subst::{Subst, InternalSubsts};
 use rustc::util::nodemap::{FxHashSet, FxHashMap};
 use rustc::mir::interpret::ConstValue;
@@ -354,7 +354,7 @@ fn check_item_type<'a, 'tcx>(
 
         let mut forbid_unsized = true;
         if allow_foreign_ty {
-            if let TyKind::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
+            if let ty::Foreign(_) = fcx.tcx.struct_tail(item_ty).sty {
                 forbid_unsized = false;
             }
         }
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 1fa16352b86..4a7b1e67366 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -71,6 +71,7 @@ This API is completely unstable and subject to change.
 #![recursion_limit="256"]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 #![allow(explicit_outlives_requirements)]
 
 #[macro_use] extern crate log;
diff --git a/src/librustdoc/lib.rs b/src/librustdoc/lib.rs
index 2ebb465d53d..6cb937d9216 100644
--- a/src/librustdoc/lib.rs
+++ b/src/librustdoc/lib.rs
@@ -1,4 +1,5 @@
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/",
        html_playground_url = "https://play.rust-lang.org/")]
diff --git a/src/libsyntax/lib.rs b/src/libsyntax/lib.rs
index a6145d5dcb3..9905b981395 100644
--- a/src/libsyntax/lib.rs
+++ b/src/libsyntax/lib.rs
@@ -8,6 +8,7 @@
        test(attr(deny(warnings))))]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(crate_visibility_modifier)]
 #![feature(label_break_value)]
diff --git a/src/libsyntax_ext/lib.rs b/src/libsyntax_ext/lib.rs
index aa472eee3ca..ee0b86963f3 100644
--- a/src/libsyntax_ext/lib.rs
+++ b/src/libsyntax_ext/lib.rs
@@ -3,6 +3,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(in_band_lifetimes)]
 #![feature(proc_macro_diagnostic)]
diff --git a/src/libsyntax_pos/lib.rs b/src/libsyntax_pos/lib.rs
index 48d087ee43c..db1543ff13f 100644
--- a/src/libsyntax_pos/lib.rs
+++ b/src/libsyntax_pos/lib.rs
@@ -7,6 +7,7 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/")]
 
 #![deny(rust_2018_idioms)]
+#![cfg_attr(not(stage0), deny(internal))]
 
 #![feature(const_fn)]
 #![feature(crate_visibility_modifier)]
diff --git a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
index 09aa106ebbd..76d0906f97c 100644
--- a/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/issue-40001-plugin.rs
@@ -26,21 +26,14 @@ pub fn plugin_registrar(reg: &mut Registry) {
     reg.register_attribute("whitelisted_attr".to_string(), Whitelisted);
 }
 
-declare_lint!(MISSING_WHITELISTED_ATTR, Deny,
-              "Checks for missing `whitelisted_attr` attribute");
-
-struct MissingWhitelistedAttrPass;
-
-impl LintPass for MissingWhitelistedAttrPass {
-    fn name(&self) -> &'static str {
-        "MissingWhitelistedAttrPass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(MISSING_WHITELISTED_ATTR)
-    }
+declare_lint! {
+    MISSING_WHITELISTED_ATTR,
+    Deny,
+    "Checks for missing `whitelisted_attr` attribute"
 }
 
+declare_lint_pass!(MissingWhitelistedAttrPass => [MISSING_WHITELISTED_ATTR]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for MissingWhitelistedAttrPass {
     fn check_fn(&mut self,
                 cx: &LateContext<'a, 'tcx>,
diff --git a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
index 82aa28b26b6..e8f1d2eedf5 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-for-crate.rs
@@ -12,20 +12,14 @@ use rustc_plugin::Registry;
 use rustc::hir;
 use syntax::attr;
 
-declare_lint!(CRATE_NOT_OKAY, Warn, "crate not marked with #![crate_okay]");
-
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(CRATE_NOT_OKAY)
-    }
+declare_lint! {
+    CRATE_NOT_OKAY,
+    Warn,
+    "crate not marked with #![crate_okay]"
 }
 
+declare_lint_pass!(Pass => [CRATE_NOT_OKAY]);
+
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_crate(&mut self, cx: &LateContext, krate: &hir::Crate) {
         if !attr::contains_name(&krate.attrs, "crate_okay") {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
index 16630e2b312..941fe25b14c 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-group-plugin-test.rs
@@ -16,17 +16,7 @@ declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
 declare_lint!(PLEASE_LINT, Warn, "Warn about items named 'pleaselintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, PLEASE_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, PLEASE_LINT]);
 
 impl<'a, 'tcx> LateLintPass<'a, 'tcx> for Pass {
     fn check_item(&mut self, cx: &LateContext, it: &hir::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
index 4e45189b424..1d204e7bfcf 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-plugin-test.rs
@@ -16,17 +16,7 @@ use rustc_plugin::Registry;
 use syntax::ast;
 declare_lint!(TEST_LINT, Warn, "Warn about items named 'lintme'");
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
diff --git a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
index d25a5ea3746..182d2899da1 100644
--- a/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint-tool-test.rs
@@ -19,17 +19,7 @@ declare_tool_lint!(
     Warn, "Warn about other stuff"
 );
 
-struct Pass;
-
-impl LintPass for Pass {
-    fn name(&self) -> &'static str {
-        "Pass"
-    }
-
-    fn get_lints(&self) -> LintArray {
-        lint_array!(TEST_LINT, TEST_GROUP)
-    }
-}
+declare_lint_pass!(Pass => [TEST_LINT, TEST_GROUP]);
 
 impl EarlyLintPass for Pass {
     fn check_item(&mut self, cx: &EarlyContext, it: &ast::Item) {
diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.rs b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs
new file mode 100644
index 00000000000..3264099c876
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.rs
@@ -0,0 +1,22 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+
+extern crate rustc_data_structures;
+
+use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use std::collections::{HashMap, HashSet};
+
+#[deny(default_hash_types)]
+fn main() {
+    let _map: HashMap<String, String> = HashMap::default();
+    //~^ ERROR Prefer FxHashMap over HashMap, it has better performance
+    //~^^ ERROR Prefer FxHashMap over HashMap, it has better performance
+    let _set: HashSet<String> = HashSet::default();
+    //~^ ERROR Prefer FxHashSet over HashSet, it has better performance
+    //~^^ ERROR Prefer FxHashSet over HashSet, it has better performance
+
+    // test that the lint doesn't also match the Fx variants themselves
+    let _fx_map: FxHashMap<String, String> = FxHashMap::default();
+    let _fx_set: FxHashSet<String> = FxHashSet::default();
+}
diff --git a/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
new file mode 100644
index 00000000000..64f322cb0c1
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/default_hash_types.stderr
@@ -0,0 +1,39 @@
+error: Prefer FxHashMap over HashMap, it has better performance
+  --> $DIR/default_hash_types.rs:12:15
+   |
+LL |     let _map: HashMap<String, String> = HashMap::default();
+   |               ^^^^^^^ help: use: `FxHashMap`
+   |
+note: lint level defined here
+  --> $DIR/default_hash_types.rs:10:8
+   |
+LL | #[deny(default_hash_types)]
+   |        ^^^^^^^^^^^^^^^^^^
+   = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
+
+error: Prefer FxHashMap over HashMap, it has better performance
+  --> $DIR/default_hash_types.rs:12:41
+   |
+LL |     let _map: HashMap<String, String> = HashMap::default();
+   |                                         ^^^^^^^ help: use: `FxHashMap`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashMap` may be necessary
+
+error: Prefer FxHashSet over HashSet, it has better performance
+  --> $DIR/default_hash_types.rs:15:15
+   |
+LL |     let _set: HashSet<String> = HashSet::default();
+   |               ^^^^^^^ help: use: `FxHashSet`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
+
+error: Prefer FxHashSet over HashSet, it has better performance
+  --> $DIR/default_hash_types.rs:15:33
+   |
+LL |     let _set: HashSet<String> = HashSet::default();
+   |                                 ^^^^^^^ help: use: `FxHashSet`
+   |
+   = note: a `use rustc_data_structures::fx::FxHashSet` may be necessary
+
+error: aborting due to 4 previous errors
+
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
new file mode 100644
index 00000000000..dba0db69b7f
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.rs
@@ -0,0 +1,49 @@
+// compile-flags: -Z unstable-options
+
+#![feature(rustc_private)]
+
+extern crate rustc;
+
+use rustc::ty::{self, Ty, TyKind};
+
+#[deny(usage_of_ty_tykind)]
+fn main() {
+    let sty = TyKind::Bool; //~ ERROR usage of `ty::TyKind::<kind>`
+
+    match sty {
+        TyKind::Bool => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Char => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Int(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Uint(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Float(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Adt(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Foreign(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Str => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Array(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Slice(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::RawPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Ref(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::FnDef(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::FnPtr(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Dynamic(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Closure(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Generator(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::GeneratorWitness(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Never => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Tuple(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Projection(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::UnnormalizedProjection(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Opaque(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        TyKind::Param(..) => (), //~ ERROR usage of `ty::TyKind::<kind>`
+        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>`
+    }
+
+    if let ty::Int(int_ty) = sty {}
+
+    if let TyKind::Int(int_ty) = sty {} //~ ERROR usage of `ty::TyKind::<kind>`
+
+    fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {} //~ ERROR usage of `ty::TyKind`
+}
diff --git a/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
new file mode 100644
index 00000000000..4e94af12453
--- /dev/null
+++ b/src/test/ui-fulldeps/internal-lints/ty_tykind_usage.stderr
@@ -0,0 +1,196 @@
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:11:15
+   |
+LL |     let sty = TyKind::Bool;
+   |               ^^^^^^ help: try using ty::<kind> directly: `ty`
+   |
+note: lint level defined here
+  --> $DIR/ty_tykind_usage.rs:9:8
+   |
+LL | #[deny(usage_of_ty_tykind)]
+   |        ^^^^^^^^^^^^^^^^^^
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:14:9
+   |
+LL |         TyKind::Bool => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:15:9
+   |
+LL |         TyKind::Char => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:16:9
+   |
+LL |         TyKind::Int(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:17:9
+   |
+LL |         TyKind::Uint(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:18:9
+   |
+LL |         TyKind::Float(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:19:9
+   |
+LL |         TyKind::Adt(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:20:9
+   |
+LL |         TyKind::Foreign(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:21:9
+   |
+LL |         TyKind::Str => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:22:9
+   |
+LL |         TyKind::Array(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:23:9
+   |
+LL |         TyKind::Slice(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:24:9
+   |
+LL |         TyKind::RawPtr(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:25:9
+   |
+LL |         TyKind::Ref(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:26:9
+   |
+LL |         TyKind::FnDef(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:27:9
+   |
+LL |         TyKind::FnPtr(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:28:9
+   |
+LL |         TyKind::Dynamic(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:29:9
+   |
+LL |         TyKind::Closure(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:30:9
+   |
+LL |         TyKind::Generator(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:31:9
+   |
+LL |         TyKind::GeneratorWitness(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:32:9
+   |
+LL |         TyKind::Never => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:33:9
+   |
+LL |         TyKind::Tuple(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:34:9
+   |
+LL |         TyKind::Projection(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:35:9
+   |
+LL |         TyKind::UnnormalizedProjection(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:36:9
+   |
+LL |         TyKind::Opaque(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:37:9
+   |
+LL |         TyKind::Param(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:38:9
+   |
+LL |         TyKind::Bound(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:39:9
+   |
+LL |         TyKind::Placeholder(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:40:9
+   |
+LL |         TyKind::Infer(..) => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:41:9
+   |
+LL |         TyKind::Error => (),
+   |         ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind::<kind>`
+  --> $DIR/ty_tykind_usage.rs:46:12
+   |
+LL |     if let TyKind::Int(int_ty) = sty {}
+   |            ^^^^^^ help: try using ty::<kind> directly: `ty`
+
+error: usage of `ty::TyKind`
+  --> $DIR/ty_tykind_usage.rs:48:24
+   |
+LL |     fn ty_kind(ty_bad: TyKind<'_>, ty_good: Ty<'_>) {}
+   |                        ^^^^^^^^^^
+   |
+   = help: try using `ty::Ty` instead
+
+error: aborting due to 31 previous errors
+
diff --git a/src/tools/compiletest/src/runtest.rs b/src/tools/compiletest/src/runtest.rs
index 35f8dca79b5..2021dd513aa 100644
--- a/src/tools/compiletest/src/runtest.rs
+++ b/src/tools/compiletest/src/runtest.rs
@@ -2820,12 +2820,15 @@ impl<'test> TestCx<'test> {
             // don't test rustfix with nll right now
         } else if self.config.rustfix_coverage {
             // Find out which tests have `MachineApplicable` suggestions but are missing
-            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers
+            // `run-rustfix` or `run-rustfix-only-machine-applicable` headers.
+            //
+            // This will return an empty `Vec` in case the executed test file has a
+            // `compile-flags: --error-format=xxxx` header with a value other than `json`.
             let suggestions = get_suggestions_from_json(
                 &proc_res.stderr,
                 &HashSet::new(),
                 Filter::MachineApplicableOnly
-            ).unwrap();
+            ).unwrap_or_default();
             if suggestions.len() > 0
                 && !self.props.run_rustfix
                 && !self.props.rustfix_only_machine_applicable {