diff --git a/src/etc/lldb_rust_formatters.py b/src/etc/lldb_rust_formatters.py
index 2c651c90f82eb..fdc1c4fa0cc38 100644
--- a/src/etc/lldb_rust_formatters.py
+++ b/src/etc/lldb_rust_formatters.py
@@ -290,6 +290,8 @@ def render_element(i):
 
 
 def read_utf8_string(ptr_val, byte_count):
+    if byte_count == 0:
+        return '""'
     error = lldb.SBError()
     process = ptr_val.get_wrapped_value().GetProcess()
     data = process.ReadMemory(ptr_val.as_integer(), byte_count, error)
diff --git a/src/libcore/benches/iter.rs b/src/libcore/benches/iter.rs
index fe852e42b5cd3..1dd2bd3ee78aa 100644
--- a/src/libcore/benches/iter.rs
+++ b/src/libcore/benches/iter.rs
@@ -185,13 +185,13 @@ bench_sums! {
 bench_sums! {
     bench_filter_sum,
     bench_filter_ref_sum,
-    (0i64..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
     bench_filter_chain_sum,
     bench_filter_chain_ref_sum,
-    (0i64..1000000).chain(0..1000000).filter(|x| x % 2 == 0)
+    (0i64..1000000).chain(0..1000000).filter(|x| x % 3 == 0)
 }
 
 bench_sums! {
@@ -306,3 +306,31 @@ fn bench_skip_then_zip(b: &mut Bencher) {
         assert_eq!(s, 2009900);
     });
 }
+
+#[bench]
+fn bench_filter_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).filter(|x| x % 3 == 0).count()
+    })
+}
+
+#[bench]
+fn bench_filter_chain_ref_count(b: &mut Bencher) {
+    b.iter(|| {
+        (0i64..1000000).chain(0..1000000).map(black_box).by_ref().filter(|x| x % 3 == 0).count()
+    })
+}
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index bca1b76dbb975..d4ad22c16bbfa 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -681,12 +681,7 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
 
     #[inline]
     fn next(&mut self) -> Option<I::Item> {
-        for x in &mut self.iter {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -707,12 +702,9 @@ impl<I: Iterator, P> Iterator for Filter<I, P> where P: FnMut(&I::Item) -> bool
     // Using the branchless version will also simplify the LLVM byte code, thus
     // leaving more budget for LLVM optimizations.
     #[inline]
-    fn count(mut self) -> usize {
-        let mut count = 0;
-        for x in &mut self.iter {
-            count += (self.predicate)(&x) as usize;
-        }
-        count
+    fn count(self) -> usize {
+        let mut predicate = self.predicate;
+        self.iter.map(|x| predicate(&x) as usize).sum()
     }
 
     #[inline]
@@ -746,12 +738,7 @@ impl<I: DoubleEndedIterator, P> DoubleEndedIterator for Filter<I, P>
 {
     #[inline]
     fn next_back(&mut self) -> Option<I::Item> {
-        for x in self.iter.by_ref().rev() {
-            if (self.predicate)(&x) {
-                return Some(x);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
@@ -820,12 +807,7 @@ impl<B, I: Iterator, F> Iterator for FilterMap<I, F>
 
     #[inline]
     fn next(&mut self) -> Option<B> {
-        for x in self.iter.by_ref() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_for_each(Err).err()
     }
 
     #[inline]
@@ -863,12 +845,7 @@ impl<B, I: DoubleEndedIterator, F> DoubleEndedIterator for FilterMap<I, F>
 {
     #[inline]
     fn next_back(&mut self) -> Option<B> {
-        for x in self.iter.by_ref().rev() {
-            if let Some(y) = (self.f)(x) {
-                return Some(y);
-            }
-        }
-        None
+        self.try_rfold((), |_, x| Err(x)).err()
     }
 
     #[inline]
diff --git a/src/libcore/mem.rs b/src/libcore/mem.rs
index f41d293e80ad3..94f342e7e8efc 100644
--- a/src/libcore/mem.rs
+++ b/src/libcore/mem.rs
@@ -900,10 +900,16 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
     }
 }
 
+// FIXME: Reference `MaybeUninit` from these docs, once that is stable.
 /// A wrapper to inhibit compiler from automatically calling `T`’s destructor.
 ///
 /// This wrapper is 0-cost.
 ///
+/// `ManuallyDrop<T>` is subject to the same layout optimizations as `T`.
+/// As a consequence, it has *no effect* on the assumptions that the compiler makes
+/// about all values being initialized at their type.  In particular, initializing
+/// a `ManuallyDrop<&mut T>` with [`mem::zeroed`] is undefined behavior.
+///
 /// # Examples
 ///
 /// This wrapper helps with explicitly documenting the drop order dependencies between fields of
@@ -935,6 +941,8 @@ pub fn discriminant<T>(v: &T) -> Discriminant<T> {
 ///     }
 /// }
 /// ```
+///
+/// [`mem::zeroed`]: fn.zeroed.html
 #[stable(feature = "manually_drop", since = "1.20.0")]
 #[lang = "manually_drop"]
 #[derive(Copy, Clone, Debug, Default, PartialEq, Eq, PartialOrd, Ord, Hash)]
diff --git a/src/libcore/pin.rs b/src/libcore/pin.rs
index f9f20dcea9e2e..835357b4e017c 100644
--- a/src/libcore/pin.rs
+++ b/src/libcore/pin.rs
@@ -215,7 +215,7 @@
 //!     had a method `fn get_pin_mut(self: Pin<&mut Self>) -> Pin<&mut T>`.
 //!     Then we could do the following:
 //!     ```compile_fail
-//!     fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>) {
+//!     fn exploit_ref_cell<T>(rc: Pin<&mut RefCell<T>>) {
 //!         { let p = rc.as_mut().get_pin_mut(); } // Here we get pinned access to the `T`.
 //!         let rc_shr: &RefCell<T> = rc.into_ref().get_ref();
 //!         let b = rc_shr.borrow_mut();
diff --git a/src/libcore/ptr.rs b/src/libcore/ptr.rs
index 866c8d0896b3c..3e1773ff9d25c 100644
--- a/src/libcore/ptr.rs
+++ b/src/libcore/ptr.rs
@@ -2790,7 +2790,7 @@ impl<T: ?Sized> Unique<T> {
     }
 
     /// Acquires the underlying `*mut` pointer.
-    pub fn as_ptr(self) -> *mut T {
+    pub const fn as_ptr(self) -> *mut T {
         self.pointer as *mut T
     }
 
@@ -2903,7 +2903,8 @@ impl<T: Sized> NonNull<T> {
     /// some other means.
     #[stable(feature = "nonnull", since = "1.25.0")]
     #[inline]
-    pub fn dangling() -> Self {
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+    pub const fn dangling() -> Self {
         unsafe {
             let ptr = mem::align_of::<T>() as *mut T;
             NonNull::new_unchecked(ptr)
@@ -2966,7 +2967,8 @@ impl<T: ?Sized> NonNull<T> {
     /// Cast to a pointer of another type
     #[stable(feature = "nonnull_cast", since = "1.27.0")]
     #[inline]
-    pub fn cast<U>(self) -> NonNull<U> {
+    #[cfg_attr(not(stage0), rustc_const_unstable(feature = "const_ptr_nonnull"))]
+    pub const fn cast<U>(self) -> NonNull<U> {
         unsafe {
             NonNull::new_unchecked(self.as_ptr() as *mut U)
         }
diff --git a/src/libcore/str/mod.rs b/src/libcore/str/mod.rs
index 8b51d8465141a..53334adadb856 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -3965,7 +3965,7 @@ impl str {
         me.make_ascii_lowercase()
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_debug`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_debug`].
     ///
     /// Note: only extended grapheme codepoints that begin the string will be
     /// escaped.
@@ -4013,7 +4013,7 @@ impl str {
         }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_default`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_default`].
     ///
     /// [`char::escape_default`]: ../std/primitive.char.html#method.escape_default
     ///
@@ -4051,7 +4051,7 @@ impl str {
         EscapeDefault { inner: self.chars().flat_map(CharEscapeDefault) }
     }
 
-    /// Return an iterator that escapes each char in `s` with [`char::escape_unicode`].
+    /// Return an iterator that escapes each char in `self` with [`char::escape_unicode`].
     ///
     /// [`char::escape_unicode`]: ../std/primitive.char.html#method.escape_unicode
     ///
diff --git a/src/librustc/lint/mod.rs b/src/librustc/lint/mod.rs
index dd003e44bea09..496ff568b31b4 100644
--- a/src/librustc/lint/mod.rs
+++ b/src/librustc/lint/mod.rs
@@ -132,14 +132,22 @@ macro_rules! declare_lint {
 
 #[macro_export]
 macro_rules! declare_tool_lint {
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr) => (
-        declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, false}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level: ident, $desc: expr
+    ) => (
+        declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, false}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr,
-     report_in_external_macro: $rep: expr) => (
-         declare_tool_lint!{$vis $tool::$NAME, $Level, $desc, $rep}
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        report_in_external_macro: $rep:expr
+    ) => (
+         declare_tool_lint!{$(#[$attr])* $vis $tool::$NAME, $Level, $desc, $rep}
     );
-    ($vis: vis $tool: ident ::$NAME: ident, $Level: ident, $desc: expr, $external: expr) => (
+    (
+        $(#[$attr:meta])* $vis:vis $tool:ident ::$NAME:ident, $Level:ident, $desc:expr,
+        $external:expr
+    ) => (
+        $(#[$attr])*
         $vis static $NAME: &$crate::lint::Lint = &$crate::lint::Lint {
             name: &concat!(stringify!($tool), "::", stringify!($NAME)),
             default_level: $crate::lint::$Level,
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 7fc01e302a7d2..9217ac9276fac 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -83,6 +83,9 @@ pub trait Delegate<'tcx> {
               assignment_span: Span,
               assignee_cmt: &mc::cmt_<'tcx>,
               mode: MutateMode);
+
+    // A nested closure or generator - only one layer deep.
+    fn nested_body(&mut self, _body_id: hir::BodyId) {}
 }
 
 #[derive(Copy, Clone, PartialEq, Debug)]
@@ -532,8 +535,9 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
                 self.consume_expr(&base);
             }
 
-            hir::ExprKind::Closure(.., fn_decl_span, _) => {
-                self.walk_captures(expr, fn_decl_span)
+            hir::ExprKind::Closure(_, _, body_id, fn_decl_span, _) => {
+                self.delegate.nested_body(body_id);
+                self.walk_captures(expr, fn_decl_span);
             }
 
             hir::ExprKind::Box(ref base) => {
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index c74d7f00cf516..11a03f940243f 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -178,6 +178,22 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> {
     }
 
     fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) { }
+
+    fn nested_body(&mut self, body_id: hir::BodyId) {
+        // rust-lang/rust#58776: MIR and AST borrow check disagree on where
+        // certain closure errors are reported. As such migrate borrowck has to
+        // operate at the level of items, rather than bodies. Check if the
+        // contained closure had any errors and set `signalled_any_error` if it
+        // has.
+        let bccx = self.bccx;
+        if bccx.tcx.migrate_borrowck() {
+            if let SignalledError::NoErrorsSeen = bccx.signalled_any_error.get() {
+                let closure_def_id = bccx.tcx.hir().body_owner_def_id(body_id);
+
+                bccx.signalled_any_error.set(bccx.tcx.borrowck(closure_def_id).signalled_any_error);
+            }
+        }
+    }
 }
 
 pub fn check_loans<'a, 'b, 'c, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
diff --git a/src/librustc_codegen_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index db5430a4219a0..8f991a9ef490b 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -13,10 +13,8 @@ use crate::common;
 use crate::LlvmCodegenBackend;
 use rustc_codegen_ssa::back::write::{CodegenContext, ModuleConfig, run_assembler};
 use rustc_codegen_ssa::traits::*;
-use rustc::hir::def_id::LOCAL_CRATE;
 use rustc::session::config::{self, OutputType, Passes, Lto};
 use rustc::session::Session;
-use rustc::ty::TyCtxt;
 use rustc_codegen_ssa::{ModuleCodegen, CompiledModule};
 use rustc::util::common::time_ext;
 use rustc_fs_util::{path_to_c_string, link_or_copy};
@@ -82,14 +80,6 @@ pub fn write_output_file(
     }
 }
 
-pub fn create_target_machine(
-    tcx: TyCtxt<'_, '_, '_>,
-    find_features: bool,
-) -> &'static mut llvm::TargetMachine {
-    target_machine_factory(tcx.sess, tcx.backend_optimization_level(LOCAL_CRATE), find_features)()
-        .unwrap_or_else(|err| llvm_err(tcx.sess.diagnostic(), &err).raise() )
-}
-
 pub fn create_informational_target_machine(
     sess: &Session,
     find_features: bool,
diff --git a/src/librustc_codegen_llvm/context.rs b/src/librustc_codegen_llvm/context.rs
index 23e3a8425d370..619304ad9afd0 100644
--- a/src/librustc_codegen_llvm/context.rs
+++ b/src/librustc_codegen_llvm/context.rs
@@ -154,7 +154,7 @@ pub unsafe fn create_module(
 
     // Ensure the data-layout values hardcoded remain the defaults.
     if sess.target.target.options.is_builtin {
-        let tm = crate::back::write::create_target_machine(tcx, false);
+        let tm = crate::back::write::create_informational_target_machine(&tcx.sess, false);
         llvm::LLVMRustSetDataLayoutFromTargetMachine(llmod, tm);
         llvm::LLVMRustDisposeTargetMachine(tm);
 
diff --git a/src/librustc_codegen_llvm/lib.rs b/src/librustc_codegen_llvm/lib.rs
index 5b8c7461bcb60..38b16078a7d38 100644
--- a/src/librustc_codegen_llvm/lib.rs
+++ b/src/librustc_codegen_llvm/lib.rs
@@ -24,7 +24,7 @@
 #![deny(rust_2018_idioms)]
 #![allow(explicit_outlives_requirements)]
 
-use back::write::create_target_machine;
+use back::write::create_informational_target_machine;
 use syntax_pos::symbol::Symbol;
 
 extern crate flate2;
@@ -114,8 +114,9 @@ pub struct LlvmCodegenBackend(());
 
 impl ExtraBackendMethods for LlvmCodegenBackend {
     fn new_metadata(&self, tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> ModuleLlvm {
-        ModuleLlvm::new(tcx, mod_name)
+        ModuleLlvm::new_metadata(tcx, mod_name)
     }
+
     fn write_metadata<'b, 'gcx>(
         &self,
         tcx: TyCtxt<'b, 'gcx, 'gcx>,
@@ -366,15 +367,14 @@ unsafe impl Send for ModuleLlvm { }
 unsafe impl Sync for ModuleLlvm { }
 
 impl ModuleLlvm {
-    fn new(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
+    fn new_metadata(tcx: TyCtxt<'_, '_, '_>, mod_name: &str) -> Self {
         unsafe {
             let llcx = llvm::LLVMRustContextCreate(tcx.sess.fewer_names());
             let llmod_raw = context::create_module(tcx, llcx, mod_name) as *const _;
-
             ModuleLlvm {
                 llmod_raw,
                 llcx,
-                tm: create_target_machine(tcx, false),
+                tm: create_informational_target_machine(&tcx.sess, false),
             }
         }
     }
diff --git a/src/librustc_codegen_ssa/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 908ee95efcba3..2bade64ddbd34 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -1022,7 +1022,13 @@ fn start_executing_work<B: ExtraBackendMethods>(
         None
     };
 
-    let ol = tcx.backend_optimization_level(LOCAL_CRATE);
+    let ol = if tcx.sess.opts.debugging_opts.no_codegen
+             || !tcx.sess.opts.output_types.should_codegen() {
+        // If we know that we won’t be doing codegen, create target machines without optimisation.
+        config::OptLevel::No
+    } else {
+        tcx.backend_optimization_level(LOCAL_CRATE)
+    };
     let cgcx = CodegenContext::<B> {
         backend: backend.clone(),
         crate_types: sess.crate_types.borrow().clone(),
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 1091646bdd5c6..edd71058dbd02 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -329,30 +329,12 @@ fn do_mir_borrowck<'a, 'gcx, 'tcx>(
             // When borrowck=migrate, check if AST-borrowck would
             // error on the given code.
 
-            // rust-lang/rust#55492: loop over parents to ensure that
-            // errors that AST-borrowck only detects in some parent of
-            // a closure still allows NLL to signal an error.
-            let mut curr_def_id = def_id;
-            let signalled_any_error = loop {
-                match tcx.borrowck(curr_def_id).signalled_any_error {
-                    SignalledError::NoErrorsSeen => {
-                        // keep traversing (and borrow-checking) parents
-                    }
-                    SignalledError::SawSomeError => {
-                        // stop search here
-                        break SignalledError::SawSomeError;
-                    }
-                }
-
-                if tcx.is_closure(curr_def_id) {
-                    curr_def_id = tcx.parent_def_id(curr_def_id)
-                        .expect("a closure must have a parent_def_id");
-                } else {
-                    break SignalledError::NoErrorsSeen;
-                }
-            };
+            // rust-lang/rust#55492, rust-lang/rust#58776 check the base def id
+            // for errors. AST borrowck is responsible for aggregating
+            // `signalled_any_error` from all of the nested closures here.
+            let base_def_id = tcx.closure_base_def_id(def_id);
 
-            match signalled_any_error {
+            match tcx.borrowck(base_def_id).signalled_any_error {
                 SignalledError::NoErrorsSeen => {
                     // if AST-borrowck signalled no errors, then
                     // downgrade all the buffered MIR-borrowck errors
diff --git a/src/test/debuginfo/empty-string.rs b/src/test/debuginfo/empty-string.rs
new file mode 100644
index 0000000000000..46df427cf829b
--- /dev/null
+++ b/src/test/debuginfo/empty-string.rs
@@ -0,0 +1,34 @@
+// ignore-windows failing on win32 bot
+// compile-flags:-g
+// min-gdb-version: 7.7
+// min-lldb-version: 310
+
+// === GDB TESTS ===================================================================================
+
+// gdb-command: run
+
+// gdb-command: print empty_string
+// gdb-check:$1 = ""
+
+// gdb-command: print empty_str
+// gdb-check:$2 = ""
+
+// === LLDB TESTS ==================================================================================
+
+// lldb-command: run
+
+// lldb-command: fr v empty_string
+// lldb-check:[...]empty_string = ""
+
+// lldb-command: fr v empty_str
+// lldb-check:[...]empty_str = ""
+
+fn main() {
+    let empty_string = String::new();
+
+    let empty_str = "";
+
+    zzz(); // #break
+}
+
+fn zzz() {}
diff --git a/src/test/run-pass/consts/const-ptr-nonnull.rs b/src/test/run-pass/consts/const-ptr-nonnull.rs
new file mode 100644
index 0000000000000..91624e92fbe75
--- /dev/null
+++ b/src/test/run-pass/consts/const-ptr-nonnull.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(const_ptr_nonnull)]
+
+use std::ptr::NonNull;
+
+const DANGLING: NonNull<u32> = NonNull::dangling();
+const CASTED: NonNull<u32> = NonNull::cast(NonNull::<i32>::dangling());
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+pub fn main() {
+    assert_eq!(DANGLING, ident(NonNull::dangling()));
+    assert_eq!(CASTED, ident(NonNull::dangling()));
+}
diff --git a/src/test/run-pass/consts/const-ptr-unique.rs b/src/test/run-pass/consts/const-ptr-unique.rs
new file mode 100644
index 0000000000000..eb371ab184166
--- /dev/null
+++ b/src/test/run-pass/consts/const-ptr-unique.rs
@@ -0,0 +1,15 @@
+// run-pass
+
+#![feature(ptr_internals)]
+
+use std::ptr::Unique;
+
+const PTR: *mut u32 = Unique::empty().as_ptr();
+
+fn ident<T>(ident: T) -> T {
+    ident
+}
+
+pub fn main() {
+    assert_eq!(PTR, ident(Unique::<u32>::empty().as_ptr()));
+}
diff --git a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
index 1a9bd9e66dbac..d25a5ea374627 100644
--- a/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
+++ b/src/test/ui-fulldeps/auxiliary/lint_tool_test.rs
@@ -13,7 +13,11 @@ use rustc::lint::{EarlyContext, LintContext, LintPass, EarlyLintPass,
 use rustc_plugin::Registry;
 use syntax::ast;
 declare_tool_lint!(pub clippy::TEST_LINT, Warn, "Warn about stuff");
-declare_tool_lint!(pub clippy::TEST_GROUP, Warn, "Warn about other stuff");
+declare_tool_lint!(
+    /// Some docs
+    pub clippy::TEST_GROUP,
+    Warn, "Warn about other stuff"
+);
 
 struct Pass;
 
diff --git a/src/test/ui/asm/invalid-inline-asm-2.rs b/src/test/ui/asm/invalid-inline-asm-2.rs
new file mode 100644
index 0000000000000..7b3f1cdd67949
--- /dev/null
+++ b/src/test/ui/asm/invalid-inline-asm-2.rs
@@ -0,0 +1,10 @@
+#![feature(asm)]
+
+fn main() {
+    let a: usize;
+
+    unsafe {
+        asm!("" : "=d"(a) : : : );
+        //~^ ERROR couldn't allocate output register for constraint 'd'
+    }
+}
diff --git a/src/test/ui/asm/invalid-inline-asm-2.stderr b/src/test/ui/asm/invalid-inline-asm-2.stderr
new file mode 100644
index 0000000000000..3534a2ea58c7a
--- /dev/null
+++ b/src/test/ui/asm/invalid-inline-asm-2.stderr
@@ -0,0 +1,8 @@
+error: couldn't allocate output register for constraint 'd'
+  --> $DIR/invalid-inline-asm-2.rs:7:9
+   |
+LL |         asm!("" : "=d"(a) : : : );
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/invalid-inline-asm.rs b/src/test/ui/asm/invalid-inline-asm.rs
new file mode 100644
index 0000000000000..1dcded0be0b74
--- /dev/null
+++ b/src/test/ui/asm/invalid-inline-asm.rs
@@ -0,0 +1,9 @@
+#![feature(asm)]
+
+fn main() {
+    let byte = 0;
+    let port = 0x80;
+
+    unsafe { asm!("out %al, %dx" :: "a" (byte), "d" (port) :: "volatile"); }
+    //~^ ERROR couldn't allocate input reg for constraint 'a'
+}
diff --git a/src/test/ui/asm/invalid-inline-asm.stderr b/src/test/ui/asm/invalid-inline-asm.stderr
new file mode 100644
index 0000000000000..11a32d3141e08
--- /dev/null
+++ b/src/test/ui/asm/invalid-inline-asm.stderr
@@ -0,0 +1,8 @@
+error: couldn't allocate input reg for constraint 'a'
+  --> $DIR/invalid-inline-asm.rs:7:14
+   |
+LL |     unsafe { asm!("out %al, %dx" :: "a" (byte), "d" (port) :: "volatile"); }
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/block-expression-remove-semicolon.rs b/src/test/ui/block-expression-remove-semicolon.rs
new file mode 100644
index 0000000000000..afa10b38b9144
--- /dev/null
+++ b/src/test/ui/block-expression-remove-semicolon.rs
@@ -0,0 +1,10 @@
+fn foo() -> i32 {
+   0
+}
+
+fn main() {
+    let x: i32 = {
+        //~^ ERROR mismatched types
+        foo(); //~ HELP consider removing this semicolon
+    };
+}
diff --git a/src/test/ui/block-expression-remove-semicolon.stderr b/src/test/ui/block-expression-remove-semicolon.stderr
new file mode 100644
index 0000000000000..aa4889fc5a577
--- /dev/null
+++ b/src/test/ui/block-expression-remove-semicolon.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/block-expression-remove-semicolon.rs:6:18
+   |
+LL |       let x: i32 = {
+   |  __________________^
+LL | |         //~^ ERROR mismatched types
+LL | |         foo(); //~ HELP consider removing this semicolon
+   | |              - help: consider removing this semicolon
+LL | |     };
+   | |_____^ expected i32, found ()
+   |
+   = note: expected type `i32`
+              found type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/borrowck/issue-10876.rs b/src/test/ui/borrowck/issue-10876.rs
new file mode 100644
index 0000000000000..d8fff5f17760a
--- /dev/null
+++ b/src/test/ui/borrowck/issue-10876.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![feature(nll)]
+
+enum Nat {
+    S(Box<Nat>),
+    Z
+}
+fn test(x: &mut Nat) {
+    let mut p = &mut *x;
+    loop {
+        match p {
+            &mut Nat::Z => break,
+            &mut Nat::S(ref mut n) => p = &mut *n
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr
new file mode 100644
index 0000000000000..9e0b0aac1e3c6
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.ast.stderr
@@ -0,0 +1,15 @@
+error[E0597]: `**greeting` does not live long enough
+  --> $DIR/issue-58776-borrowck-scans-children.rs:10:24
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                    --  ^^^^^^^^     - borrowed value only lives until here
+   |                    |   |
+   |                    |   borrowed value does not live long enough
+   |                    capture occurs here
+...
+LL | }
+   | - borrowed value needs to live until here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
new file mode 100644
index 0000000000000..bd8f2286f170c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.migrate.stderr
@@ -0,0 +1,32 @@
+error[E0506]: cannot assign to `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:13:5
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     greeting = "DEALLOCATED".to_string();
+   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error[E0505]: cannot move out of `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:16:10
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     drop(greeting);
+   |          ^^^^^^^^ move out of `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0506.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr
new file mode 100644
index 0000000000000..bd8f2286f170c
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.nll.stderr
@@ -0,0 +1,32 @@
+error[E0506]: cannot assign to `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:13:5
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     greeting = "DEALLOCATED".to_string();
+   |     ^^^^^^^^ assignment to borrowed `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error[E0505]: cannot move out of `greeting` because it is borrowed
+  --> $DIR/issue-58776-borrowck-scans-children.rs:16:10
+   |
+LL |     let res = (|| (|| &greeting)())();
+   |                --      -------- borrow occurs due to use in closure
+   |                |
+   |                borrow of `greeting` occurs here
+...
+LL |     drop(greeting);
+   |          ^^^^^^^^ move out of `greeting` occurs here
+...
+LL |     println!("thread result: {:?}", res);
+   |                                     --- borrow later used here
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0505, E0506.
+For more information about an error, try `rustc --explain E0505`.
diff --git a/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs
new file mode 100644
index 0000000000000..378969f9a1867
--- /dev/null
+++ b/src/test/ui/borrowck/issue-58776-borrowck-scans-children.rs
@@ -0,0 +1,21 @@
+// ignore-compare-mode-nll
+
+// revisions: ast migrate nll
+
+//[migrate]compile-flags: -Z borrowck=migrate
+#![cfg_attr(nll, feature(nll))]
+
+fn main() {
+    let mut greeting = "Hello world!".to_string();
+    let res = (|| (|| &greeting)())();
+    //[ast]~^ ERROR does not live long enough
+
+    greeting = "DEALLOCATED".to_string();
+    //[migrate]~^ ERROR cannot assign
+    //[nll]~^^ ERROR cannot assign
+    drop(greeting);
+    //[migrate]~^ ERROR cannot move
+    //[nll]~^^ ERROR cannot move
+
+    println!("thread result: {:?}", res);
+}
diff --git a/src/test/ui/consts/const-ptr-nonnull.rs b/src/test/ui/consts/const-ptr-nonnull.rs
new file mode 100644
index 0000000000000..54e743aa32e23
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.rs
@@ -0,0 +1,11 @@
+use std::ptr::NonNull;
+
+fn main() {
+    let x: &'static NonNull<u32> = &(NonNull::dangling());
+    //~^ ERROR borrowed value does not live long enough
+
+    let mut i: i32 = 10;
+    let non_null = NonNull::new(&mut i).unwrap();
+    let x: &'static NonNull<u32> = &(non_null.cast());
+    //~^ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-nonnull.stderr b/src/test/ui/consts/const-ptr-nonnull.stderr
new file mode 100644
index 0000000000000..a9476dda6d320
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-nonnull.stderr
@@ -0,0 +1,25 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:4:37
+   |
+LL |     let x: &'static NonNull<u32> = &(NonNull::dangling());
+   |                                     ^^^^^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+...
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-nonnull.rs:9:37
+   |
+LL |     let x: &'static NonNull<u32> = &(non_null.cast());
+   |                                     ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ ERROR borrowed value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/consts/const-ptr-unique.rs b/src/test/ui/consts/const-ptr-unique.rs
new file mode 100644
index 0000000000000..be44a24181606
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.rs
@@ -0,0 +1,10 @@
+#![feature(ptr_internals)]
+
+use std::ptr::Unique;
+
+fn main() {
+    let mut i: u32 = 10;
+    let unique = Unique::new(&mut i).unwrap();
+    let x: &'static *mut u32 = &(unique.as_ptr());
+    //~^ ERROR borrowed value does not live long enough
+}
diff --git a/src/test/ui/consts/const-ptr-unique.stderr b/src/test/ui/consts/const-ptr-unique.stderr
new file mode 100644
index 0000000000000..141465bf184d0
--- /dev/null
+++ b/src/test/ui/consts/const-ptr-unique.stderr
@@ -0,0 +1,14 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/const-ptr-unique.rs:8:33
+   |
+LL |     let x: &'static *mut u32 = &(unique.as_ptr());
+   |                                 ^^^^^^^^^^^^^^^^^ temporary value does not live long enough
+LL |     //~^ ERROR borrowed value does not live long enough
+LL | }
+   | - temporary value only lives until here
+   |
+   = note: borrowed value must be valid for the static lifetime...
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-26448-1.rs b/src/test/ui/issues/issue-26448-1.rs
new file mode 100644
index 0000000000000..7d2d75bf2e878
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-1.rs
@@ -0,0 +1,13 @@
+// run-pass
+
+pub trait Foo<T> {
+    fn foo(self) -> T;
+}
+
+impl<'a, T> Foo<T> for &'a str where &'a str: Into<T> {
+    fn foo(self) -> T {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26448-2.rs b/src/test/ui/issues/issue-26448-2.rs
new file mode 100644
index 0000000000000..17e7c1f977a6d
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-2.rs
@@ -0,0 +1,21 @@
+// run-pass
+
+pub struct Bar<T> {
+    items: Vec<&'static str>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26448-3.rs b/src/test/ui/issues/issue-26448-3.rs
new file mode 100644
index 0000000000000..e57352e57f4fc
--- /dev/null
+++ b/src/test/ui/issues/issue-26448-3.rs
@@ -0,0 +1,25 @@
+// run-pass
+
+pub struct Item {
+    _inner: &'static str,
+}
+
+pub struct Bar<T> {
+    items: Vec<Item>,
+    inner: T,
+}
+
+pub trait IntoBar<T> {
+    fn into_bar(self) -> Bar<T>;
+}
+
+impl<'a, T> IntoBar<T> for &'a str where &'a str: Into<T> {
+    fn into_bar(self) -> Bar<T> {
+        Bar {
+            items: Vec::new(),
+            inner: self.into(),
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-26619.rs b/src/test/ui/issues/issue-26619.rs
new file mode 100644
index 0000000000000..cd89c674e4996
--- /dev/null
+++ b/src/test/ui/issues/issue-26619.rs
@@ -0,0 +1,24 @@
+#![feature(slice_patterns)]
+
+pub struct History<'a> { pub _s: &'a str }
+
+impl<'a> History<'a> {
+    pub fn get_page(&self) {
+        for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+            //~^ ERROR borrowed value does not live long enough
+            println!("{:?}", s);
+        }
+    }
+
+    fn make_entry(&self, s: &'a String) -> Option<&str> {
+        let parts: Vec<_> = s.split('|').collect();
+        println!("{:?} -> {:?}", s, parts);
+
+        if let [commit, ..] = &parts[..] { Some(commit) } else { None }
+    }
+}
+
+fn main() {
+    let h = History{ _s: "" };
+    h.get_page();
+}
diff --git a/src/test/ui/issues/issue-26619.stderr b/src/test/ui/issues/issue-26619.stderr
new file mode 100644
index 0000000000000..3ac6c4e308d21
--- /dev/null
+++ b/src/test/ui/issues/issue-26619.stderr
@@ -0,0 +1,12 @@
+error[E0597]: borrowed value does not live long enough
+  --> $DIR/issue-26619.rs:7:66
+   |
+LL |         for s in vec!["1|2".to_string()].into_iter().filter_map(|ref line| self.make_entry(line)) {
+   |                                                                  ^^^^^^^^                      -- temporary value needs to live until here
+   |                                                                  |                             |
+   |                                                                  |                             temporary value dropped here while still borrowed
+   |                                                                  temporary value does not live long enough
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0597`.
diff --git a/src/test/ui/issues/issue-44127.rs b/src/test/ui/issues/issue-44127.rs
new file mode 100644
index 0000000000000..21b2e68264a14
--- /dev/null
+++ b/src/test/ui/issues/issue-44127.rs
@@ -0,0 +1,17 @@
+// run-pass
+
+#![feature(decl_macro)]
+
+pub struct Foo {
+    bar: u32,
+}
+pub macro pattern($a:pat) {
+    Foo { bar: $a }
+}
+
+fn main() {
+    match (Foo { bar: 3 }) {
+        pattern!(3) => println!("Test OK"),
+        _ => unreachable!(),
+    }
+}
diff --git a/src/test/ui/issues/issue-44255.rs b/src/test/ui/issues/issue-44255.rs
new file mode 100644
index 0000000000000..2245032043257
--- /dev/null
+++ b/src/test/ui/issues/issue-44255.rs
@@ -0,0 +1,29 @@
+// run-pass
+
+use std::marker::PhantomData;
+
+fn main() {
+    let _arr = [1; <Multiply<Five, Five>>::VAL];
+}
+
+trait TypeVal<T> {
+    const VAL: T;
+}
+
+struct Five;
+
+impl TypeVal<usize> for Five {
+    const VAL: usize = 5;
+}
+
+struct Multiply<N, M> {
+    _n: PhantomData<N>,
+    _m: PhantomData<M>,
+}
+
+impl<N, M> TypeVal<usize> for Multiply<N, M>
+    where N: TypeVal<usize>,
+          M: TypeVal<usize>,
+{
+    const VAL: usize = N::VAL * M::VAL;
+}
diff --git a/src/test/ui/issues/issue-46101.rs b/src/test/ui/issues/issue-46101.rs
new file mode 100644
index 0000000000000..2d9111e9b3a98
--- /dev/null
+++ b/src/test/ui/issues/issue-46101.rs
@@ -0,0 +1,4 @@
+#![feature(use_extern_macros)]
+trait Foo {}
+#[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+struct S;
diff --git a/src/test/ui/issues/issue-46101.stderr b/src/test/ui/issues/issue-46101.stderr
new file mode 100644
index 0000000000000..f8b95d7a23bf2
--- /dev/null
+++ b/src/test/ui/issues/issue-46101.stderr
@@ -0,0 +1,14 @@
+error[E0433]: failed to resolve: partially resolved path in a derive macro
+  --> $DIR/issue-46101.rs:3:10
+   |
+LL | #[derive(Foo::Anything)] //~ ERROR failed to resolve: partially resolved path in a derive macro
+   |          ^^^^^^^^^^^^^ partially resolved path in a derive macro
+
+error[E0601]: `main` function not found in crate `issue_46101`
+   |
+   = note: consider adding a `main` function to `$DIR/issue-46101.rs`
+
+error: aborting due to 2 previous errors
+
+Some errors occurred: E0433, E0601.
+For more information about an error, try `rustc --explain E0433`.
diff --git a/src/test/ui/issues/issue-55731.rs b/src/test/ui/issues/issue-55731.rs
new file mode 100644
index 0000000000000..7b4f4e2cd3b40
--- /dev/null
+++ b/src/test/ui/issues/issue-55731.rs
@@ -0,0 +1,52 @@
+use std::marker::PhantomData;
+
+trait DistributedIterator {
+    fn reduce(self)
+    where
+        Self: Sized,
+    {
+        unreachable!()
+    }
+}
+
+trait DistributedIteratorMulti<Source> {
+    type Item;
+}
+
+struct Connect<I>(PhantomData<fn(I)>);
+impl<I: for<'a> DistributedIteratorMulti<&'a ()>> DistributedIterator for Connect<I> where {}
+
+struct Cloned<Source>(PhantomData<fn(Source)>);
+impl<'a, Source> DistributedIteratorMulti<&'a Source> for Cloned<&'a Source> {
+    type Item = ();
+}
+
+struct Map<I, F> {
+    i: I,
+    f: F,
+}
+impl<I: DistributedIteratorMulti<Source>, F, Source> DistributedIteratorMulti<Source> for Map<I, F>
+where
+    F: A<<I as DistributedIteratorMulti<Source>>::Item>,
+{
+    type Item = ();
+}
+
+trait A<B> {}
+
+struct X;
+impl A<()> for X {}
+
+fn multi<I>(_reducer: I)
+where
+    I: for<'a> DistributedIteratorMulti<&'a ()>,
+{
+    DistributedIterator::reduce(Connect::<I>(PhantomData))
+}
+
+fn main() {
+    multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough
+        i: Cloned(PhantomData),
+        f: X,
+    });
+}
diff --git a/src/test/ui/issues/issue-55731.stderr b/src/test/ui/issues/issue-55731.stderr
new file mode 100644
index 0000000000000..f490b45bf9767
--- /dev/null
+++ b/src/test/ui/issues/issue-55731.stderr
@@ -0,0 +1,11 @@
+error: implementation of `DistributedIteratorMulti` is not general enough
+  --> $DIR/issue-55731.rs:48:5
+   |
+LL |     multi(Map { //~ ERROR implementation of `DistributedIteratorMulti` is not general enough
+   |     ^^^^^
+   |
+   = note: `DistributedIteratorMulti<&'0 ()>` would have to be implemented for the type `Cloned<&()>`, for any lifetime `'0`
+   = note: but `DistributedIteratorMulti<&'1 ()>` is actually implemented for the type `Cloned<&'1 ()>`, for some specific lifetime `'1`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-57781.rs b/src/test/ui/issues/issue-57781.rs
new file mode 100644
index 0000000000000..f5015aaf5d81f
--- /dev/null
+++ b/src/test/ui/issues/issue-57781.rs
@@ -0,0 +1,20 @@
+// run-pass
+
+use std::cell::UnsafeCell;
+use std::collections::HashMap;
+
+struct OnceCell<T> {
+    _value: UnsafeCell<Option<T>>,
+}
+
+impl<T> OnceCell<T> {
+    const INIT: OnceCell<T> = OnceCell {
+        _value: UnsafeCell::new(None),
+    };
+}
+
+pub fn crash<K, T>() {
+    let _ = OnceCell::<HashMap<K, T>>::INIT;
+}
+
+fn main() {}
diff --git a/src/test/ui/primitive-binop-lhs-mut.rs b/src/test/ui/primitive-binop-lhs-mut.rs
new file mode 100644
index 0000000000000..4f1c456ace354
--- /dev/null
+++ b/src/test/ui/primitive-binop-lhs-mut.rs
@@ -0,0 +1,6 @@
+// run-pass
+
+fn main() {
+    let x = Box::new(0);
+    assert_eq!(0, *x + { drop(x); let _ = Box::new(main); 0 });
+}
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index 94dd5478e5297..0169725fa2968 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -49,13 +49,13 @@ const EXCEPTIONS: &[&str] = &[
 ];
 
 /// Which crates to check against the whitelist?
-const WHITELIST_CRATES: &[CrateVersion] = &[
+const WHITELIST_CRATES: &[CrateVersion<'_>] = &[
     CrateVersion("rustc", "0.0.0"),
     CrateVersion("rustc_codegen_llvm", "0.0.0"),
 ];
 
 /// Whitelist of crates rustc is allowed to depend on. Avoid adding to the list if possible.
-const WHITELIST: &[Crate] = &[
+const WHITELIST: &[Crate<'_>] = &[
     Crate("adler32"),
     Crate("aho-corasick"),
     Crate("arrayvec"),
@@ -183,7 +183,7 @@ struct Crate<'a>(&'a str); // (name)
 #[derive(Copy, Clone, PartialOrd, Ord, PartialEq, Eq, Debug, Hash)]
 struct CrateVersion<'a>(&'a str, &'a str); // (name, version)
 
-impl<'a> Crate<'a> {
+impl Crate<'_> {
     pub fn id_str(&self) -> String {
         format!("{} ", self.0)
     }
@@ -330,10 +330,10 @@ fn get_deps(path: &Path, cargo: &Path) -> Resolve {
 
 /// Checks the dependencies of the given crate from the given cargo metadata to see if they are on
 /// the whitelist. Returns a list of illegal dependencies.
-fn check_crate_whitelist<'a, 'b>(
-    whitelist: &'a HashSet<Crate>,
+fn check_crate_whitelist<'a>(
+    whitelist: &'a HashSet<Crate<'_>>,
     resolve: &'a Resolve,
-    visited: &'b mut BTreeSet<CrateVersion<'a>>,
+    visited: &mut BTreeSet<CrateVersion<'a>>,
     krate: CrateVersion<'a>,
     must_be_on_whitelist: bool,
 ) -> BTreeSet<Crate<'a>> {
diff --git a/src/tools/tidy/src/features.rs b/src/tools/tidy/src/features.rs
index 7126c0c2f6ecf..1eab217027c8a 100644
--- a/src/tools/tidy/src/features.rs
+++ b/src/tools/tidy/src/features.rs
@@ -22,7 +22,7 @@ pub enum Status {
 }
 
 impl fmt::Display for Status {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         let as_str = match *self {
             Status::Stable => "stable",
             Status::Unstable => "unstable",
diff --git a/src/tools/tidy/src/lib.rs b/src/tools/tidy/src/lib.rs
index 022c53f909c75..c4a1246ffdf55 100644
--- a/src/tools/tidy/src/lib.rs
+++ b/src/tools/tidy/src/lib.rs
@@ -3,7 +3,8 @@
 //! This library contains the tidy lints and exposes it
 //! to be used by tools.
 
-extern crate serde;
+#![deny(rust_2018_idioms)]
+
 extern crate serde_json;
 #[macro_use]
 extern crate serde_derive;