diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 355f282921537..bf3c22744f165 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -428,11 +428,6 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_LLVM_ASSERTIONS: 1
             os: windows-latest-xl
-          - name: x86_64-msvc-aux
-            env:
-              RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-              RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc"
-            os: windows-latest-xl
           - name: x86_64-msvc-cargo
             env:
               SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
diff --git a/Cargo.lock b/Cargo.lock
index bbbcf797f7535..009767934d447 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1434,9 +1434,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.1.13"
+version = "0.1.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "91780f809e750b0a89f5544be56617ff6b1227ee485bcb06ebe10cdf89bd3b71"
+checksum = "b9586eedd4ce6b3c498bc3b4dd92fc9f11166aa908a914071953768066c67909"
 dependencies = [
  "compiler_builtins",
  "libc",
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c4f29927cf4a8..ea5300bdfc04c 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -373,7 +373,6 @@ impl<'a> Builder<'a> {
                 test::UiFullDeps,
                 test::Rustdoc,
                 test::Pretty,
-                test::RunPassValgrindPretty,
                 test::Crate,
                 test::CrateLibrustc,
                 test::CrateRustdoc,
diff --git a/src/bootstrap/mk/Makefile.in b/src/bootstrap/mk/Makefile.in
index d8c97fc741478..12a1734e21c7e 100644
--- a/src/bootstrap/mk/Makefile.in
+++ b/src/bootstrap/mk/Makefile.in
@@ -6,12 +6,6 @@ Q := @
 BOOTSTRAP_ARGS :=
 endif
 
-ifdef EXCLUDE_CARGO
-AUX_ARGS :=
-else
-AUX_ARGS := src/tools/cargo src/tools/cargotest
-endif
-
 BOOTSTRAP := $(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap.py
 
 all:
@@ -48,8 +42,8 @@ check:
 	$(Q)$(BOOTSTRAP) test $(BOOTSTRAP_ARGS)
 check-aux:
 	$(Q)$(BOOTSTRAP) test \
-		src/test/run-pass-valgrind/pretty \
-		$(AUX_ARGS) \
+		src/tools/cargo \
+		src/tools/cargotest \
 		$(BOOTSTRAP_ARGS)
 check-bootstrap:
 	$(Q)$(CFG_PYTHON) $(CFG_SRC_DIR)src/bootstrap/bootstrap_test.py
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index aeabb227cf5e9..b8c5751565838 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -930,13 +930,6 @@ host_test!(UiFullDeps { path: "src/test/ui-fulldeps", mode: "ui", suite: "ui-ful
 host_test!(Rustdoc { path: "src/test/rustdoc", mode: "rustdoc", suite: "rustdoc" });
 
 host_test!(Pretty { path: "src/test/pretty", mode: "pretty", suite: "pretty" });
-test!(RunPassValgrindPretty {
-    path: "src/test/run-pass-valgrind/pretty",
-    mode: "pretty",
-    suite: "run-pass-valgrind",
-    default: false,
-    host: true
-});
 
 default_test!(RunMake { path: "src/test/run-make", mode: "run-make", suite: "run-make" });
 
diff --git a/src/ci/azure-pipelines/auto.yml b/src/ci/azure-pipelines/auto.yml
index f8fa7b727d179..3de27bc54c5c0 100644
--- a/src/ci/azure-pipelines/auto.yml
+++ b/src/ci/azure-pipelines/auto.yml
@@ -142,10 +142,6 @@ jobs:
         # FIXME(#59637)
         NO_DEBUG_ASSERTIONS: 1
         NO_LLVM_ASSERTIONS: 1
-      # MSVC aux tests
-      x86_64-msvc-aux:
-        RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-        INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
       x86_64-msvc-cargo:
         SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
         INITIAL_RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-lld
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 590845b33cda7..a052d0879a3db 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -492,12 +492,6 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
             <<: *job-windows-xl
 
-          - name: x86_64-msvc-aux
-            env:
-              RUST_CHECK_TARGET: check-aux EXCLUDE_CARGO=1
-              RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc
-            <<: *job-windows-xl
-
           - name: x86_64-msvc-cargo
             env:
               SCRIPT: python x.py test src/tools/cargotest src/tools/cargo
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index 7d21f9a9a66d0..fe05e914e6d44 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -145,7 +145,6 @@
 #![feature(associated_type_bounds)]
 #![feature(const_type_id)]
 #![feature(const_caller_location)]
-#![feature(option_zip)]
 #![feature(no_niche)] // rust-lang/rust#68303
 
 #[prelude_import]
diff --git a/src/libcore/option.rs b/src/libcore/option.rs
index e8483875c97e5..5f0a12678ff43 100644
--- a/src/libcore/option.rs
+++ b/src/libcore/option.rs
@@ -926,7 +926,6 @@ impl<T> Option<T> {
     /// # Examples
     ///
     /// ```
-    /// #![feature(option_zip)]
     /// let x = Some(1);
     /// let y = Some("hi");
     /// let z = None::<u8>;
@@ -934,9 +933,12 @@ impl<T> Option<T> {
     /// assert_eq!(x.zip(y), Some((1, "hi")));
     /// assert_eq!(x.zip(z), None);
     /// ```
-    #[unstable(feature = "option_zip", issue = "70086")]
+    #[stable(feature = "option_zip_option", since = "1.46.0")]
     pub fn zip<U>(self, other: Option<U>) -> Option<(T, U)> {
-        self.zip_with(other, |a, b| (a, b))
+        match (self, other) {
+            (Some(a), Some(b)) => Some((a, b)),
+            _ => None,
+        }
     }
 
     /// Zips `self` and another `Option` with function `f`.
diff --git a/src/librustc_arena/lib.rs b/src/librustc_arena/lib.rs
index 4da336f8e288d..4a2a0de0e211f 100644
--- a/src/librustc_arena/lib.rs
+++ b/src/librustc_arena/lib.rs
@@ -602,7 +602,7 @@ macro_rules! which_arena_for_type {
 
 #[macro_export]
 macro_rules! declare_arena {
-    ([], [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+    ([], [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
         #[derive(Default)]
         pub struct Arena<$tcx> {
             pub dropless: $crate::DroplessArena,
@@ -611,17 +611,17 @@ macro_rules! declare_arena {
         }
 
         #[marker]
-        pub trait ArenaAllocatable {}
+        pub trait ArenaAllocatable<'tcx> {}
 
-        impl<T: Copy> ArenaAllocatable for T {}
+        impl<'tcx, T: Copy> ArenaAllocatable<'tcx> for T {}
 
-        unsafe trait ArenaField<'tcx>: Sized {
+        unsafe trait ArenaField<'tcx>: Sized + ArenaAllocatable<'tcx> {
             /// Returns a specific arena to allocate from.
             /// If `None` is returned, the `DropArena` will be used.
             fn arena<'a>(arena: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>>;
         }
 
-        unsafe impl<'tcx, T> ArenaField<'tcx> for T {
+        unsafe impl<'tcx, T: ArenaAllocatable<'tcx>> ArenaField<'tcx> for T {
             #[inline]
             default fn arena<'a>(_: &'a Arena<'tcx>) -> Option<&'a $crate::TypedArena<Self>> {
                 panic!()
@@ -630,18 +630,27 @@ macro_rules! declare_arena {
 
         $(
             #[allow(unused_lifetimes)]
-            impl<$tcx> ArenaAllocatable for $ty {}
-            unsafe impl<$tcx> ArenaField<$tcx> for $ty {
+            impl<$tcx> ArenaAllocatable<$tcx> for $ty {}
+            unsafe impl<$tcx, '_x, '_y, '_z, '_w> ArenaField<$tcx> for $gen_ty where Self: ArenaAllocatable<$tcx> {
                 #[inline]
                 fn arena<'a>(_arena: &'a Arena<$tcx>) -> Option<&'a $crate::TypedArena<Self>> {
-                    $crate::which_arena_for_type!($a[&_arena.$name])
+                    // SAFETY: We only implement `ArenaAllocatable<$tcx>` for
+                    // `$ty`, so `$ty` and Self are the same type
+                    unsafe {
+                        ::std::mem::transmute::<
+                            Option<&'a $crate::TypedArena<$ty>>,
+                            Option<&'a $crate::TypedArena<Self>>,
+                        >(
+                            $crate::which_arena_for_type!($a[&_arena.$name])
+                        )
+                    }
                 }
             }
         )*
 
         impl<'tcx> Arena<'tcx> {
             #[inline]
-            pub fn alloc<T: ArenaAllocatable>(&self, value: T) -> &mut T {
+            pub fn alloc<T: ArenaAllocatable<'tcx>>(&self, value: T) -> &mut T {
                 if !::std::mem::needs_drop::<T>() {
                     return self.dropless.alloc(value);
                 }
@@ -659,7 +668,7 @@ macro_rules! declare_arena {
                 self.dropless.alloc_slice(value)
             }
 
-            pub fn alloc_from_iter<'a, T: ArenaAllocatable>(
+            pub fn alloc_from_iter<'a, T: ArenaAllocatable<'tcx>>(
                 &'a self,
                 iter: impl ::std::iter::IntoIterator<Item = T>,
             ) -> &'a mut [T] {
diff --git a/src/librustc_ast_lowering/lib.rs b/src/librustc_ast_lowering/lib.rs
index d7946ad009415..a722a88a7a102 100644
--- a/src/librustc_ast_lowering/lib.rs
+++ b/src/librustc_ast_lowering/lib.rs
@@ -33,7 +33,7 @@
 #![feature(array_value_iter)]
 #![feature(crate_visibility_modifier)]
 #![feature(marker_trait_attr)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(or_patterns)]
 #![recursion_limit = "256"]
 
diff --git a/src/librustc_error_codes/error_codes.rs b/src/librustc_error_codes/error_codes.rs
index 3fb5e04efc922..99ef226f94aae 100644
--- a/src/librustc_error_codes/error_codes.rs
+++ b/src/librustc_error_codes/error_codes.rs
@@ -439,6 +439,7 @@ E0752: include_str!("./error_codes/E0752.md"),
 E0753: include_str!("./error_codes/E0753.md"),
 E0754: include_str!("./error_codes/E0754.md"),
 E0758: include_str!("./error_codes/E0758.md"),
+E0759: include_str!("./error_codes/E0759.md"),
 E0760: include_str!("./error_codes/E0760.md"),
 E0761: include_str!("./error_codes/E0761.md"),
 E0762: include_str!("./error_codes/E0762.md"),
diff --git a/src/librustc_error_codes/error_codes/E0759.md b/src/librustc_error_codes/error_codes/E0759.md
new file mode 100644
index 0000000000000..a74759bdf634b
--- /dev/null
+++ b/src/librustc_error_codes/error_codes/E0759.md
@@ -0,0 +1,67 @@
+A `'static` requirement in a return type involving a trait is not fulfilled.
+
+Erroneous code examples:
+
+```compile_fail,E0759
+use std::fmt::Debug;
+
+fn foo(x: &i32) -> impl Debug {
+    x
+}
+```
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn bar(x: &i32) -> Box<dyn Debug> {
+    Box::new(x)
+}
+```
+
+These examples have the same semantics as the following:
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn foo(x: &i32) -> impl Debug + 'static {
+    x
+}
+```
+
+```compile_fail,E0759
+# use std::fmt::Debug;
+fn bar(x: &i32) -> Box<dyn Debug + 'static> {
+    Box::new(x)
+}
+```
+
+Both [`dyn Trait`] and [`impl Trait`] in return types have a an implicit
+`'static` requirement, meaning that the value implementing them that is being
+returned has to be either a `'static` borrow or an owned value.
+
+In order to change the requirement from `'static` to be a lifetime derived from
+its arguments, you can add an explicit bound, either to an anonymous lifetime
+`'_` or some appropriate named lifetime.
+
+```
+# use std::fmt::Debug;
+fn foo(x: &i32) -> impl Debug + '_ {
+    x
+}
+fn bar(x: &i32) -> Box<dyn Debug + '_> {
+    Box::new(x)
+}
+```
+
+These are equivalent to the following explicit lifetime annotations:
+
+```
+# use std::fmt::Debug;
+fn foo<'a>(x: &'a i32) -> impl Debug + 'a {
+    x
+}
+fn bar<'a>(x: &'a i32) -> Box<dyn Debug + 'a> {
+    Box::new(x)
+}
+```
+
+[`dyn Trait`]: https://doc.rust-lang.org/book/ch17-02-trait-objects.html#using-trait-objects-that-allow-for-values-of-different-types
+[`impl Trait`]: https://doc.rust-lang.org/book/ch10-02-traits.html#returning-types-that-implement-traits
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index cff83c3d5cda2..acaa26c6ad2fc 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -296,6 +296,29 @@ impl Diagnostic {
         self
     }
 
+    pub fn multipart_suggestions(
+        &mut self,
+        msg: &str,
+        suggestions: Vec<Vec<(Span, String)>>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        self.suggestions.push(CodeSuggestion {
+            substitutions: suggestions
+                .into_iter()
+                .map(|suggestion| Substitution {
+                    parts: suggestion
+                        .into_iter()
+                        .map(|(span, snippet)| SubstitutionPart { snippet, span })
+                        .collect(),
+                })
+                .collect(),
+            msg: msg.to_owned(),
+            style: SuggestionStyle::ShowCode,
+            applicability,
+        });
+        self
+    }
+
     /// Prints out a message with for a multipart suggestion without showing the suggested code.
     ///
     /// This is intended to be used for suggestions that are obvious in what the changes need to
diff --git a/src/librustc_errors/diagnostic_builder.rs b/src/librustc_errors/diagnostic_builder.rs
index 2dbd9f4e52fad..22bf8fe34aa15 100644
--- a/src/librustc_errors/diagnostic_builder.rs
+++ b/src/librustc_errors/diagnostic_builder.rs
@@ -260,6 +260,19 @@ impl<'a> DiagnosticBuilder<'a> {
         self
     }
 
+    pub fn multipart_suggestions(
+        &mut self,
+        msg: &str,
+        suggestions: Vec<Vec<(Span, String)>>,
+        applicability: Applicability,
+    ) -> &mut Self {
+        if !self.0.allow_suggestions {
+            return self;
+        }
+        self.0.diagnostic.multipart_suggestions(msg, suggestions, applicability);
+        self
+    }
+
     pub fn tool_only_multipart_suggestion(
         &mut self,
         msg: &str,
diff --git a/src/librustc_hir/arena.rs b/src/librustc_hir/arena.rs
index 6ba396666070a..f439db715310c 100644
--- a/src/librustc_hir/arena.rs
+++ b/src/librustc_hir/arena.rs
@@ -12,41 +12,41 @@ macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
             // HIR types
-            [few] hir_krate: rustc_hir::Crate<$tcx>,
-            [] arm: rustc_hir::Arm<$tcx>,
-            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>,
-            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
-            [] attribute: rustc_ast::ast::Attribute,
-            [] block: rustc_hir::Block<$tcx>,
-            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>,
-            [few] global_asm: rustc_hir::GlobalAsm,
-            [] generic_arg: rustc_hir::GenericArg<$tcx>,
-            [] generic_args: rustc_hir::GenericArgs<$tcx>,
-            [] generic_bound: rustc_hir::GenericBound<$tcx>,
-            [] generic_param: rustc_hir::GenericParam<$tcx>,
-            [] expr: rustc_hir::Expr<$tcx>,
-            [] field: rustc_hir::Field<$tcx>,
-            [] field_pat: rustc_hir::FieldPat<$tcx>,
-            [] fn_decl: rustc_hir::FnDecl<$tcx>,
-            [] foreign_item: rustc_hir::ForeignItem<$tcx>,
-            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>,
-            [few] inline_asm: rustc_hir::InlineAsm<$tcx>,
-            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
-            [] local: rustc_hir::Local<$tcx>,
-            [few] macro_def: rustc_hir::MacroDef<$tcx>,
-            [] param: rustc_hir::Param<$tcx>,
-            [] pat: rustc_hir::Pat<$tcx>,
-            [] path: rustc_hir::Path<$tcx>,
-            [] path_segment: rustc_hir::PathSegment<$tcx>,
-            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>,
-            [] qpath: rustc_hir::QPath<$tcx>,
-            [] stmt: rustc_hir::Stmt<$tcx>,
-            [] struct_field: rustc_hir::StructField<$tcx>,
-            [] trait_item_ref: rustc_hir::TraitItemRef,
-            [] ty: rustc_hir::Ty<$tcx>,
-            [] type_binding: rustc_hir::TypeBinding<$tcx>,
-            [] variant: rustc_hir::Variant<$tcx>,
-            [] where_predicate: rustc_hir::WherePredicate<$tcx>,
+            [few] hir_krate: rustc_hir::Crate<$tcx>, rustc_hir::Crate<'_x>;
+            [] arm: rustc_hir::Arm<$tcx>, rustc_hir::Arm<'_x>;
+            [] asm_operand: rustc_hir::InlineAsmOperand<$tcx>, rustc_hir::InlineAsmOperand<'_x>;
+            [] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
+            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
+            [] block: rustc_hir::Block<$tcx>, rustc_hir::Block<'_x>;
+            [] bare_fn_ty: rustc_hir::BareFnTy<$tcx>, rustc_hir::BareFnTy<'_x>;
+            [few] global_asm: rustc_hir::GlobalAsm, rustc_hir::GlobalAsm;
+            [] generic_arg: rustc_hir::GenericArg<$tcx>, rustc_hir::GenericArg<'_x>;
+            [] generic_args: rustc_hir::GenericArgs<$tcx>, rustc_hir::GenericArgs<'_x>;
+            [] generic_bound: rustc_hir::GenericBound<$tcx>, rustc_hir::GenericBound<'_x>;
+            [] generic_param: rustc_hir::GenericParam<$tcx>, rustc_hir::GenericParam<'_x>;
+            [] expr: rustc_hir::Expr<$tcx>, rustc_hir::Expr<'_x>;
+            [] field: rustc_hir::Field<$tcx>, rustc_hir::Field<'_x>;
+            [] field_pat: rustc_hir::FieldPat<$tcx>, rustc_hir::FieldPat<'_x>;
+            [] fn_decl: rustc_hir::FnDecl<$tcx>, rustc_hir::FnDecl<'_x>;
+            [] foreign_item: rustc_hir::ForeignItem<$tcx>, rustc_hir::ForeignItem<'_x>;
+            [] impl_item_ref: rustc_hir::ImplItemRef<$tcx>, rustc_hir::ImplItemRef<'_x>;
+            [few] inline_asm: rustc_hir::InlineAsm<$tcx>, rustc_hir::InlineAsm<'_x>;
+            [few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>, rustc_hir::LlvmInlineAsm<'_x>;
+            [] local: rustc_hir::Local<$tcx>, rustc_hir::Local<'_x>;
+            [few] macro_def: rustc_hir::MacroDef<$tcx>, rustc_hir::MacroDef<'_x>;
+            [] param: rustc_hir::Param<$tcx>, rustc_hir::Param<'_x>;
+            [] pat: rustc_hir::Pat<$tcx>, rustc_hir::Pat<'_x>;
+            [] path: rustc_hir::Path<$tcx>, rustc_hir::Path<'_x>;
+            [] path_segment: rustc_hir::PathSegment<$tcx>, rustc_hir::PathSegment<'_x>;
+            [] poly_trait_ref: rustc_hir::PolyTraitRef<$tcx>, rustc_hir::PolyTraitRef<'_x>;
+            [] qpath: rustc_hir::QPath<$tcx>, rustc_hir::QPath<'_x>;
+            [] stmt: rustc_hir::Stmt<$tcx>, rustc_hir::Stmt<'_x>;
+            [] struct_field: rustc_hir::StructField<$tcx>, rustc_hir::StructField<'_x>;
+            [] trait_item_ref: rustc_hir::TraitItemRef, rustc_hir::TraitItemRef;
+            [] ty: rustc_hir::Ty<$tcx>, rustc_hir::Ty<'_x>;
+            [] type_binding: rustc_hir::TypeBinding<$tcx>, rustc_hir::TypeBinding<'_x>;
+            [] variant: rustc_hir::Variant<$tcx>, rustc_hir::Variant<'_x>;
+            [] where_predicate: rustc_hir::WherePredicate<$tcx>, rustc_hir::WherePredicate<'_x>;
         ], $tcx);
     )
 }
diff --git a/src/librustc_infer/infer/canonical/query_response.rs b/src/librustc_infer/infer/canonical/query_response.rs
index ab2393918c354..8af526e3ad31b 100644
--- a/src/librustc_infer/infer/canonical/query_response.rs
+++ b/src/librustc_infer/infer/canonical/query_response.rs
@@ -56,7 +56,7 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
     ) -> Fallible<CanonicalizedQueryResponse<'tcx, T>>
     where
         T: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable,
+        Canonical<'tcx, QueryResponse<'tcx, T>>: ArenaAllocatable<'tcx>,
     {
         let query_response = self.make_query_response(inference_vars, answer, fulfill_cx)?;
         let canonical_result = self.canonicalize_response(&query_response);
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index 12f7a9c0ca502..9cfa11dd7c813 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -2035,8 +2035,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             self.tcx.sess,
             var_origin.span(),
             E0495,
-            "cannot infer an appropriate lifetime{} \
-             due to conflicting requirements",
+            "cannot infer an appropriate lifetime{} due to conflicting requirements",
             var_description
         )
     }
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
index f4c86ddae604e..853a414290704 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -1,14 +1,15 @@
 //! Error Reporting for static impl Traits.
 
-use crate::infer::error_reporting::msg_span_from_free_region;
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use rustc_errors::{Applicability, ErrorReported};
+use rustc_errors::{struct_span_err, Applicability, ErrorReported};
+use rustc_hir::{GenericBound, ItemKind, Lifetime, LifetimeName, TyKind};
 use rustc_middle::ty::RegionKind;
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the return type is a static impl Trait.
     pub(super) fn try_report_static_impl_trait(&self) -> Option<ErrorReported> {
+        debug!("try_report_static_impl_trait(error={:?})", self.error);
         if let Some(ref error) = self.error {
             if let RegionResolutionError::SubSupConflict(
                 _,
@@ -17,18 +18,36 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 sub_r,
                 sup_origin,
                 sup_r,
-            ) = error.clone()
+            ) = error
             {
+                debug!(
+                    "try_report_static_impl_trait(var={:?}, sub={:?} {:?} sup={:?} {:?})",
+                    var_origin, sub_origin, sub_r, sup_origin, sup_r
+                );
                 let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
-                let (fn_return_span, is_dyn) =
-                    self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
-                if sub_r == &RegionKind::ReStatic {
+                debug!("try_report_static_impl_trait: anon_reg_sup={:?}", anon_reg_sup);
+                let fn_return = self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
+                debug!("try_report_static_impl_trait: fn_return={:?}", fn_return);
+                if **sub_r == RegionKind::ReStatic {
                     let sp = var_origin.span();
                     let return_sp = sub_origin.span();
-                    let mut err =
-                        self.tcx().sess.struct_span_err(sp, "cannot infer an appropriate lifetime");
                     let param_info = self.find_param_with_region(sup_r, sub_r)?;
-                    err.span_label(param_info.param_ty_span, "data with this lifetime...");
+                    let (lifetime_name, lifetime) = if sup_r.has_name() {
+                        (sup_r.to_string(), format!("lifetime `{}`", sup_r))
+                    } else {
+                        ("'_".to_owned(), "an anonymous lifetime `'_`".to_string())
+                    };
+                    let mut err = struct_span_err!(
+                        self.tcx().sess,
+                        sp,
+                        E0759,
+                        "cannot infer an appropriate lifetime"
+                    );
+                    err.span_label(
+                        param_info.param_ty_span,
+                        &format!("this data with {}...", lifetime),
+                    );
+                    debug!("try_report_static_impl_trait: param_info={:?}", param_info);
 
                     // We try to make the output have fewer overlapping spans if possible.
                     if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
@@ -38,41 +57,146 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
                         // Customize the spans and labels depending on their relative order so
                         // that split sentences flow correctly.
-                        if sup_origin.span().shrink_to_hi() <= return_sp.shrink_to_lo() {
-                            err.span_label(sup_origin.span(), "...is captured here...");
-                            err.span_label(return_sp, "...and required to be `'static` by this");
+                        if sup_origin.span().overlaps(return_sp) && sp == sup_origin.span() {
+                            // Avoid the following:
+                            //
+                            // error: cannot infer an appropriate lifetime
+                            //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+                            //    |
+                            // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+                            //    |           ----                      ---------^-
+                            //
+                            // and instead show:
+                            //
+                            // error: cannot infer an appropriate lifetime
+                            //   --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+                            //    |
+                            // LL | fn foo(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+                            //    |           ----                               ^
+                            err.span_label(
+                                sup_origin.span(),
+                                "...is captured here, requiring it to live as long as `'static`",
+                            );
                         } else {
-                            err.span_label(return_sp, "...is required to be `'static` by this...");
-                            err.span_label(sup_origin.span(), "...and is captured here");
+                            err.span_label(sup_origin.span(), "...is captured here...");
+                            if return_sp < sup_origin.span() {
+                                err.span_note(
+                                    return_sp,
+                                    "...and is required to live as long as `'static` here",
+                                );
+                            } else {
+                                err.span_label(
+                                    return_sp,
+                                    "...and is required to live as long as `'static` here",
+                                );
+                            }
                         }
                     } else {
                         err.span_label(
                             return_sp,
-                            "...is captured and required to be `'static` here",
+                            "...is captured and required to live as long as `'static` here",
                         );
                     }
 
-                    let (lifetime, _) = msg_span_from_free_region(self.tcx(), sup_r);
-
-                    let lifetime_name =
-                        if sup_r.has_name() { sup_r.to_string() } else { "'_".to_owned() };
                     // only apply this suggestion onto functions with
                     // explicit non-desugar'able return.
-                    if fn_return_span.desugaring_kind().is_none() {
-                        let msg = format!(
-                            "to permit non-static references in {} `{} Trait` value, you can add \
-                             an explicit bound for {}",
-                            if is_dyn { "a" } else { "an" },
-                            if is_dyn { "dyn" } else { "impl" },
-                            lifetime,
-                        );
+                    if fn_return.span.desugaring_kind().is_none() {
                         // FIXME: account for the need of parens in `&(dyn Trait + '_)`
-                        err.span_suggestion_verbose(
-                            fn_return_span.shrink_to_hi(),
-                            &msg,
-                            format!(" + {}", lifetime_name),
-                            Applicability::MaybeIncorrect,
-                        );
+
+                        let consider = "consider changing the";
+                        let declare = "to declare that the";
+                        let arg = match param_info.param.pat.simple_ident() {
+                            Some(simple_ident) => format!("argument `{}`", simple_ident),
+                            None => "the argument".to_string(),
+                        };
+                        let explicit =
+                            format!("you can add an explicit `{}` lifetime bound", lifetime_name);
+                        let explicit_static =
+                            format!("explicit `'static` bound to the lifetime of {}", arg);
+                        let captures = format!("captures data from {}", arg);
+                        let add_static_bound =
+                            "alternatively, add an explicit `'static` bound to this reference";
+                        let plus_lt = format!(" + {}", lifetime_name);
+                        match fn_return.kind {
+                            TyKind::Def(item_id, _) => {
+                                let item = self.tcx().hir().item(item_id.id);
+                                let opaque = if let ItemKind::OpaqueTy(opaque) = &item.kind {
+                                    opaque
+                                } else {
+                                    err.emit();
+                                    return Some(ErrorReported);
+                                };
+
+                                if let Some(span) = opaque
+                                    .bounds
+                                    .iter()
+                                    .filter_map(|arg| match arg {
+                                        GenericBound::Outlives(Lifetime {
+                                            name: LifetimeName::Static,
+                                            span,
+                                            ..
+                                        }) => Some(*span),
+                                        _ => None,
+                                    })
+                                    .next()
+                                {
+                                    err.span_suggestion_verbose(
+                                        span,
+                                        &format!("{} `impl Trait`'s {}", consider, explicit_static),
+                                        lifetime_name,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                    err.span_suggestion_verbose(
+                                        param_info.param_ty_span,
+                                        add_static_bound,
+                                        param_info.param_ty.to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                } else {
+                                    err.span_suggestion_verbose(
+                                        fn_return.span.shrink_to_hi(),
+                                        &format!(
+                                            "{declare} `impl Trait` {captures}, {explicit}",
+                                            declare = declare,
+                                            captures = captures,
+                                            explicit = explicit,
+                                        ),
+                                        plus_lt,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                };
+                            }
+                            TyKind::TraitObject(_, lt) => match lt.name {
+                                LifetimeName::ImplicitObjectLifetimeDefault => {
+                                    err.span_suggestion_verbose(
+                                        fn_return.span.shrink_to_hi(),
+                                        &format!(
+                                            "{declare} trait object {captures}, {explicit}",
+                                            declare = declare,
+                                            captures = captures,
+                                            explicit = explicit,
+                                        ),
+                                        plus_lt,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                                _ => {
+                                    err.span_suggestion_verbose(
+                                        lt.span,
+                                        &format!("{} trait object's {}", consider, explicit_static),
+                                        lifetime_name,
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                    err.span_suggestion_verbose(
+                                        param_info.param_ty_span,
+                                        add_static_bound,
+                                        param_info.param_ty.to_string(),
+                                        Applicability::MaybeIncorrect,
+                                    );
+                                }
+                            },
+                            _ => {}
+                        }
                     }
                     err.emit();
                     return Some(ErrorReported);
diff --git a/src/librustc_macros/src/query.rs b/src/librustc_macros/src/query.rs
index 41a49a38a19cf..c17d5311e8fe6 100644
--- a/src/librustc_macros/src/query.rs
+++ b/src/librustc_macros/src/query.rs
@@ -433,7 +433,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
 
                 try_load_from_on_disk_cache_stream.extend(quote! {
                     ::rustc_middle::dep_graph::DepKind::#name => {
-                        if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
+                        if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
                             debug_assert!($tcx.dep_graph
                                             .node_color($dep_node)
                                             .map(|c| c.is_green())
@@ -490,7 +490,7 @@ pub fn rustc_queries(input: TokenStream) -> TokenStream {
             // Add a match arm to force the query given the dep node
             dep_node_force_stream.extend(quote! {
                 ::rustc_middle::dep_graph::DepKind::#name => {
-                    if <#arg as DepNodeParams<TyCtxt<'_>>>::CAN_RECONSTRUCT_QUERY_KEY {
+                    if <#arg as DepNodeParams<TyCtxt<'_>>>::can_reconstruct_query_key() {
                         if let Some(key) = <#arg as DepNodeParams<TyCtxt<'_>>>::recover($tcx, $dep_node) {
                             force_query::<crate::ty::query::queries::#name<'_>, _>(
                                 $tcx,
diff --git a/src/librustc_metadata/lib.rs b/src/librustc_metadata/lib.rs
index 2a2169880a54e..76e39a476c6d8 100644
--- a/src/librustc_metadata/lib.rs
+++ b/src/librustc_metadata/lib.rs
@@ -7,7 +7,7 @@
 #![feature(nll)]
 #![feature(or_patterns)]
 #![feature(proc_macro_internals)]
-#![feature(specialization)] // FIXME: min_specialization ICEs
+#![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
 
diff --git a/src/librustc_metadata/rmeta/decoder.rs b/src/librustc_metadata/rmeta/decoder.rs
index 44944a9fb265a..5b2f000a93fca 100644
--- a/src/librustc_metadata/rmeta/decoder.rs
+++ b/src/librustc_metadata/rmeta/decoder.rs
@@ -30,7 +30,7 @@ use rustc_middle::mir::{self, interpret, Body, Promoted};
 use rustc_middle::ty::codec::TyDecoder;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_middle::util::common::record_time;
-use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder};
+use rustc_serialize::{opaque, Decodable, Decoder, SpecializedDecoder, UseSpecializedDecodable};
 use rustc_session::Session;
 use rustc_span::source_map::{respan, Spanned};
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -218,7 +218,7 @@ impl<'a, 'tcx> Metadata<'a, 'tcx> for (&'a CrateMetadataRef<'a>, TyCtxt<'tcx>) {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> Lazy<T> {
+impl<'a, 'tcx, T: Decodable> Lazy<T, ()> {
     fn decode<M: Metadata<'a, 'tcx>>(self, metadata: M) -> T {
         let mut dcx = metadata.decoder(self.position.get());
         dcx.lazy_state = LazyState::NodeStart(self.position);
@@ -226,7 +226,7 @@ impl<'a, 'tcx, T: Decodable> Lazy<T> {
     }
 }
 
-impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T]> {
+impl<'a: 'x, 'tcx: 'x, 'x, T: Decodable> Lazy<[T], usize> {
     fn decode<M: Metadata<'a, 'tcx>>(
         self,
         metadata: M,
@@ -321,20 +321,20 @@ impl<'a, 'tcx> TyDecoder<'tcx> for DecodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<T, ()>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<T>, Self::Error> {
         self.read_lazy_with_meta(())
     }
 }
 
-impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T]>> for DecodeContext<'a, 'tcx> {
+impl<'a, 'tcx, T> SpecializedDecoder<Lazy<[T], usize>> for DecodeContext<'a, 'tcx> {
     fn specialized_decode(&mut self) -> Result<Lazy<[T]>, Self::Error> {
         let len = self.read_usize()?;
         if len == 0 { Ok(Lazy::empty()) } else { self.read_lazy_with_meta(len) }
     }
 }
 
-impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>>> for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, I: Idx, T> SpecializedDecoder<Lazy<Table<I, T>, usize>> for DecodeContext<'a, 'tcx>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -515,8 +515,9 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for DecodeContext<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
-    for DecodeContext<'a, 'tcx>
+impl<'a, 'tcx, T> SpecializedDecoder<mir::ClearCrossCrate<T>> for DecodeContext<'a, 'tcx>
+where
+    mir::ClearCrossCrate<T>: UseSpecializedDecodable,
 {
     #[inline]
     fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
diff --git a/src/librustc_metadata/rmeta/encoder.rs b/src/librustc_metadata/rmeta/encoder.rs
index 1dc22c10c8e7a..feefdf299a95a 100644
--- a/src/librustc_metadata/rmeta/encoder.rs
+++ b/src/librustc_metadata/rmeta/encoder.rs
@@ -27,7 +27,7 @@ use rustc_middle::mir::{self, interpret};
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::{self as ty_codec, TyEncoder};
 use rustc_middle::ty::{self, SymbolName, Ty, TyCtxt};
-use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder};
+use rustc_serialize::{opaque, Encodable, Encoder, SpecializedEncoder, UseSpecializedEncodable};
 use rustc_session::config::CrateType;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -93,13 +93,13 @@ impl<'tcx> Encoder for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<Lazy<T>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<T, ()>> for EncodeContext<'tcx> {
     fn specialized_encode(&mut self, lazy: &Lazy<T>) -> Result<(), Self::Error> {
         self.emit_lazy_distance(*lazy)
     }
 }
 
-impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<Lazy<[T], usize>> for EncodeContext<'tcx> {
     fn specialized_encode(&mut self, lazy: &Lazy<[T]>) -> Result<(), Self::Error> {
         self.emit_usize(lazy.meta)?;
         if lazy.meta == 0 {
@@ -109,7 +109,7 @@ impl<'tcx, T> SpecializedEncoder<Lazy<[T]>> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>>> for EncodeContext<'tcx>
+impl<'tcx, I: Idx, T> SpecializedEncoder<Lazy<Table<I, T>, usize>> for EncodeContext<'tcx>
 where
     Option<T>: FixedSizeEncoding,
 {
@@ -228,8 +228,13 @@ impl<'tcx> SpecializedEncoder<LocalDefId> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx> SpecializedEncoder<Ty<'tcx>> for EncodeContext<'tcx> {
-    fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
+impl<'a, 'b, 'tcx> SpecializedEncoder<&'a ty::TyS<'b>> for EncodeContext<'tcx>
+where
+    &'a ty::TyS<'b>: UseSpecializedEncodable,
+{
+    fn specialized_encode(&mut self, ty: &&'a ty::TyS<'b>) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(ty).is_some());
+        let ty = unsafe { std::mem::transmute::<&&'a ty::TyS<'b>, &&'tcx ty::TyS<'tcx>>(ty) };
         ty_codec::encode_with_shorthand(self, ty, |ecx| &mut ecx.type_shorthands)
     }
 }
@@ -251,12 +256,19 @@ impl<'tcx> SpecializedEncoder<interpret::AllocId> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]> for EncodeContext<'tcx> {
+impl<'a, 'b, 'tcx> SpecializedEncoder<&'a [(ty::Predicate<'b>, Span)]> for EncodeContext<'tcx> {
     fn specialized_encode(
         &mut self,
-        predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
+        predicates: &&'a [(ty::Predicate<'b>, Span)],
     ) -> Result<(), Self::Error> {
-        ty_codec::encode_spanned_predicates(self, predicates, |ecx| &mut ecx.predicate_shorthands)
+        debug_assert!(self.tcx.lift(*predicates).is_some());
+        let predicates = unsafe {
+            std::mem::transmute::<
+                &&'a [(ty::Predicate<'b>, Span)],
+                &&'tcx [(ty::Predicate<'tcx>, Span)],
+            >(predicates)
+        };
+        ty_codec::encode_spanned_predicates(self, &predicates, |ecx| &mut ecx.predicate_shorthands)
     }
 }
 
@@ -266,7 +278,10 @@ impl<'tcx> SpecializedEncoder<Fingerprint> for EncodeContext<'tcx> {
     }
 }
 
-impl<'tcx, T: Encodable> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx> {
+impl<'tcx, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for EncodeContext<'tcx>
+where
+    mir::ClearCrossCrate<T>: UseSpecializedEncodable,
+{
     fn specialized_encode(&mut self, _: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
         Ok(())
     }
diff --git a/src/librustc_middle/arena.rs b/src/librustc_middle/arena.rs
index 75228350c6c45..f861d63aba0f3 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -11,79 +11,109 @@
 macro_rules! arena_types {
     ($macro:path, $args:tt, $tcx:lifetime) => (
         $macro!($args, [
-            [] layouts: rustc_target::abi::Layout,
+            [] layouts: rustc_target::abi::Layout, rustc_target::abi::Layout;
             // AdtDef are interned and compared by address
-            [] adt_def: rustc_middle::ty::AdtDef,
-            [decode] tables: rustc_middle::ty::TypeckTables<$tcx>,
-            [] const_allocs: rustc_middle::mir::interpret::Allocation,
+            [] adt_def: rustc_middle::ty::AdtDef, rustc_middle::ty::AdtDef;
+            [decode] tables: rustc_middle::ty::TypeckTables<$tcx>, rustc_middle::ty::TypeckTables<'_x>;
+            [] const_allocs: rustc_middle::mir::interpret::Allocation, rustc_middle::mir::interpret::Allocation;
             // Required for the incremental on-disk cache
-            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet,
-            [] region_scope_tree: rustc_middle::middle::region::ScopeTree,
+            [few, decode] mir_keys: rustc_hir::def_id::DefIdSet, rustc_hir::def_id::DefIdSet;
+            [] region_scope_tree: rustc_middle::middle::region::ScopeTree, rustc_middle::middle::region::ScopeTree;
             [] dropck_outlives:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::DropckOutlivesResult<'tcx>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        rustc_middle::traits::query::DropckOutlivesResult<'_z>
+                    >
+                >;
             [] normalize_projection_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         rustc_middle::traits::query::NormalizationResult<'tcx>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        rustc_middle::traits::query::NormalizationResult<'_z>
+                    >
+                >;
             [] implied_outlives_bounds:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx,
                         Vec<rustc_middle::traits::query::OutlivesBound<'tcx>>
                     >
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y,
+                        Vec<rustc_middle::traits::query::OutlivesBound<'_z>>
+                    >
+                >;
             [] type_op_subtype:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, ()>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, ()>
+                >;
             [] type_op_normalize_poly_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::PolyFnSig<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::PolyFnSig<'_z>>
+                >;
             [] type_op_normalize_fn_sig:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::FnSig<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::FnSig<'_z>>
+                >;
             [] type_op_normalize_predicate:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Predicate<'tcx>>
                 >,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, rustc_middle::ty::Predicate<'_z>>
+                >;
             [] type_op_normalize_ty:
                 rustc_middle::infer::canonical::Canonical<'tcx,
                     rustc_middle::infer::canonical::QueryResponse<'tcx, rustc_middle::ty::Ty<'tcx>>
                 >,
-            [few] all_traits: Vec<rustc_hir::def_id::DefId>,
-            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels,
-            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule,
-            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>,
-            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>,
-            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation,
-            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>,
-            [] attribute: rustc_ast::ast::Attribute,
-            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>,
-            [] hir_id_set: rustc_hir::HirIdSet,
+                rustc_middle::infer::canonical::Canonical<'_x,
+                    rustc_middle::infer::canonical::QueryResponse<'_y, &'_z rustc_middle::ty::TyS<'_w>>
+                >;
+            [few] all_traits: Vec<rustc_hir::def_id::DefId>, Vec<rustc_hir::def_id::DefId>;
+            [few] privacy_access_levels: rustc_middle::middle::privacy::AccessLevels, rustc_middle::middle::privacy::AccessLevels;
+            [few] foreign_module: rustc_middle::middle::cstore::ForeignModule, rustc_middle::middle::cstore::ForeignModule;
+            [few] foreign_modules: Vec<rustc_middle::middle::cstore::ForeignModule>, Vec<rustc_middle::middle::cstore::ForeignModule>;
+            [] upvars_mentioned: rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>, rustc_data_structures::fx::FxIndexMap<rustc_hir::HirId, rustc_hir::Upvar>;
+            [] object_safety_violations: rustc_middle::traits::ObjectSafetyViolation, rustc_middle::traits::ObjectSafetyViolation;
+            [] codegen_unit: rustc_middle::mir::mono::CodegenUnit<$tcx>, rustc_middle::mir::mono::CodegenUnit<'_x>;
+            [] attribute: rustc_ast::ast::Attribute, rustc_ast::ast::Attribute;
+            [] name_set: rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>, rustc_data_structures::fx::FxHashSet<rustc_span::symbol::Symbol>;
+            [] hir_id_set: rustc_hir::HirIdSet, rustc_hir::HirIdSet;
 
             // Interned types
-            [] tys: rustc_middle::ty::TyS<$tcx>,
+            [] tys: rustc_middle::ty::TyS<$tcx>, rustc_middle::ty::TyS<'_x>;
 
             // HIR query types
-            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>,
-            [few] hir_definitions: rustc_hir::definitions::Definitions,
-            [] hir_owner: rustc_middle::hir::Owner<$tcx>,
-            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>,
+            [few] indexed_hir: rustc_middle::hir::map::IndexedHir<$tcx>, rustc_middle::hir::map::IndexedHir<'_x>;
+            [few] hir_definitions: rustc_hir::definitions::Definitions, rustc_hir::definitions::Definitions;
+            [] hir_owner: rustc_middle::hir::Owner<$tcx>, rustc_middle::hir::Owner<'_x>;
+            [] hir_owner_nodes: rustc_middle::hir::OwnerNodes<$tcx>, rustc_middle::hir::OwnerNodes<'_x>;
 
             // Note that this deliberately duplicates items in the `rustc_hir::arena`,
             // since we need to allocate this type on both the `rustc_hir` arena
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
-            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
+            [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece, rustc_ast::ast::InlineAsmTemplatePiece;
 
             // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
-            [decode] span: rustc_span::Span,
+            [decode] span: rustc_span::Span, rustc_span::Span;
         ], $tcx);
     )
 }
diff --git a/src/librustc_middle/dep_graph/dep_node.rs b/src/librustc_middle/dep_graph/dep_node.rs
index 2c0524fa99102..b14f17dee6060 100644
--- a/src/librustc_middle/dep_graph/dep_node.rs
+++ b/src/librustc_middle/dep_graph/dep_node.rs
@@ -128,7 +128,7 @@ macro_rules! define_dep_nodes {
                             // tuple args
                             $({
                                 return <$tuple_arg_ty as DepNodeParams<TyCtxt<'_>>>
-                                    ::CAN_RECONSTRUCT_QUERY_KEY;
+                                    ::can_reconstruct_query_key();
                             })*
 
                             true
@@ -304,7 +304,10 @@ rustc_dep_node_append!([define_dep_nodes!][ <'tcx>
 ]);
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         tcx.def_path_hash(*self).0
@@ -320,7 +323,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for DefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         self.to_def_id().to_fingerprint(tcx)
@@ -336,7 +342,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for LocalDefId {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = true;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        true
+    }
 
     fn to_fingerprint(&self, tcx: TyCtxt<'tcx>) -> Fingerprint {
         let def_id = DefId { krate: *self, index: CRATE_DEF_INDEX };
@@ -353,7 +362,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for CrateNum {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
@@ -375,7 +387,10 @@ impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for (DefId, DefId) {
 }
 
 impl<'tcx> DepNodeParams<TyCtxt<'tcx>> for HirId {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     // We actually would not need to specialize the implementation of this
     // method but it's faster to combine the hashes than to instantiate a full
diff --git a/src/librustc_middle/lib.rs b/src/librustc_middle/lib.rs
index 7c433574d1843..62c92e988ba60 100644
--- a/src/librustc_middle/lib.rs
+++ b/src/librustc_middle/lib.rs
@@ -42,7 +42,7 @@
 #![feature(option_expect_none)]
 #![feature(or_patterns)]
 #![feature(range_is_empty)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(track_caller)]
 #![feature(trusted_len)]
 #![feature(vec_remove_item)]
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index 129f9691ea521..84750a9ead02e 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -457,8 +457,39 @@ impl<T> ClearCrossCrate<T> {
     }
 }
 
-impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {}
-impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {}
+const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
+const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
+
+impl<T: Encodable> rustc_serialize::UseSpecializedEncodable for ClearCrossCrate<T> {
+    #[inline]
+    fn default_encode<E: rustc_serialize::Encoder>(&self, e: &mut E) -> Result<(), E::Error> {
+        match *self {
+            ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(e),
+            ClearCrossCrate::Set(ref val) => {
+                TAG_CLEAR_CROSS_CRATE_SET.encode(e)?;
+                val.encode(e)
+            }
+        }
+    }
+}
+impl<T: Decodable> rustc_serialize::UseSpecializedDecodable for ClearCrossCrate<T> {
+    #[inline]
+    fn default_decode<D>(d: &mut D) -> Result<ClearCrossCrate<T>, D::Error>
+    where
+        D: rustc_serialize::Decoder,
+    {
+        let discr = u8::decode(d)?;
+
+        match discr {
+            TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(ClearCrossCrate::Clear),
+            TAG_CLEAR_CROSS_CRATE_SET => {
+                let val = T::decode(d)?;
+                Ok(ClearCrossCrate::Set(val))
+            }
+            _ => unreachable!(),
+        }
+    }
+}
 
 /// Grouped information about the source code origin of a MIR entity.
 /// Intended to be inspected by diagnostics and debuginfo.
@@ -1957,8 +1988,6 @@ impl<V, T> ProjectionElem<V, T> {
 /// and the index is a local.
 pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 
-impl<'tcx> Copy for PlaceElem<'tcx> {}
-
 // At least on 64 bit systems, `PlaceElem` should not be larger than two pointers.
 #[cfg(target_arch = "x86_64")]
 static_assert_size!(PlaceElem<'_>, 16);
diff --git a/src/librustc_middle/ty/codec.rs b/src/librustc_middle/ty/codec.rs
index 8bc69a9d12312..1a8e5c45dd2f7 100644
--- a/src/librustc_middle/ty/codec.rs
+++ b/src/librustc_middle/ty/codec.rs
@@ -97,7 +97,7 @@ where
 
 pub fn encode_spanned_predicates<'tcx, E, C>(
     encoder: &mut E,
-    predicates: &'tcx [(ty::Predicate<'tcx>, Span)],
+    predicates: &[(ty::Predicate<'tcx>, Span)],
     cache: C,
 ) -> Result<(), E::Error>
 where
@@ -139,7 +139,7 @@ pub trait TyDecoder<'tcx>: Decoder {
 }
 
 #[inline]
-pub fn decode_arena_allocable<D, T: ArenaAllocatable + Decodable>(
+pub fn decode_arena_allocable<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
     decoder: &mut D,
 ) -> Result<&'tcx T, D::Error>
 where
@@ -149,7 +149,7 @@ where
 }
 
 #[inline]
-pub fn decode_arena_allocable_slice<D, T: ArenaAllocatable + Decodable>(
+pub fn decode_arena_allocable_slice<'tcx, D, T: ArenaAllocatable<'tcx> + Decodable>(
     decoder: &mut D,
 ) -> Result<&'tcx [T], D::Error>
 where
@@ -318,18 +318,38 @@ macro_rules! __impl_decoder_methods {
 macro_rules! impl_arena_allocatable_decoder {
     ([]$args:tt) => {};
     ([decode $(, $attrs:ident)*]
-     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty], $tcx:lifetime]) => {
-        impl<$($typaram),*> SpecializedDecoder<&$tcx $ty> for $DecoderName<$($typaram),*> {
+     [[$DecoderName:ident [$($typaram:tt),*]], [$name:ident: $ty:ty, $gen_ty:ty], $tcx:lifetime]) => {
+         // FIXME(#36588): These impls are horribly unsound as they allow
+         // the caller to pick any lifetime for `'tcx`, including `'static`.
+        #[allow(unused_lifetimes)]
+        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a $gen_ty>
+        for $DecoderName<$($typaram),*>
+        where &'_a $gen_ty: UseSpecializedDecodable
+        {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&$tcx $ty, Self::Error> {
-                decode_arena_allocable(self)
+            fn specialized_decode(&mut self) -> Result<&'_a $gen_ty, Self::Error> {
+                unsafe {
+                    std::mem::transmute::<
+                        Result<&$tcx $ty, Self::Error>,
+                        Result<&'_a $gen_ty, Self::Error>,
+                    >(decode_arena_allocable(self))
+                }
             }
         }
 
-        impl<$($typaram),*> SpecializedDecoder<&$tcx [$ty]> for $DecoderName<$($typaram),*> {
+        #[allow(unused_lifetimes)]
+        impl<'_x, '_y, '_z, '_w, '_a, $($typaram),*> SpecializedDecoder<&'_a [$gen_ty]>
+        for $DecoderName<$($typaram),*>
+        where &'_a [$gen_ty]: UseSpecializedDecodable
+        {
             #[inline]
-            fn specialized_decode(&mut self) -> Result<&$tcx [$ty], Self::Error> {
-                decode_arena_allocable_slice(self)
+            fn specialized_decode(&mut self) -> Result<&'_a [$gen_ty], Self::Error> {
+                unsafe {
+                    std::mem::transmute::<
+                        Result<&$tcx [$ty], Self::Error>,
+                        Result<&'_a [$gen_ty], Self::Error>,
+                    >(decode_arena_allocable_slice(self))
+                }
             }
         }
     };
@@ -340,9 +360,9 @@ macro_rules! impl_arena_allocatable_decoder {
 
 #[macro_export]
 macro_rules! impl_arena_allocatable_decoders {
-    ($args:tt, [$($a:tt $name:ident: $ty:ty,)*], $tcx:lifetime) => {
+    ($args:tt, [$($a:tt $name:ident: $ty:ty, $gen_ty:ty;)*], $tcx:lifetime) => {
         $(
-            impl_arena_allocatable_decoder!($a [$args, [$name: $ty], $tcx]);
+            impl_arena_allocatable_decoder!($a [$args, [$name: $ty, $gen_ty], $tcx]);
         )*
     }
 }
@@ -352,14 +372,15 @@ macro_rules! implement_ty_decoder {
     ($DecoderName:ident <$($typaram:tt),*>) => {
         mod __ty_decoder_impl {
             use std::borrow::Cow;
+            use std::mem::transmute;
 
-            use rustc_serialize::{Decoder, SpecializedDecoder};
+            use rustc_serialize::{Decoder, SpecializedDecoder, UseSpecializedDecodable};
 
             use $crate::infer::canonical::CanonicalVarInfos;
             use $crate::ty;
             use $crate::ty::codec::*;
-            use $crate::ty::subst::SubstsRef;
-            use rustc_hir::def_id::{CrateNum};
+            use $crate::ty::subst::InternalSubsts;
+            use rustc_hir::def_id::CrateNum;
 
             use rustc_span::Span;
 
@@ -398,8 +419,7 @@ macro_rules! implement_ty_decoder {
             }
 
             // FIXME(#36588): These impls are horribly unsound as they allow
-            // the caller to pick any lifetime for `'tcx`, including `'static`,
-            // by using the unspecialized proxies to them.
+            // the caller to pick any lifetime for `'tcx`, including `'static`.
 
             rustc_hir::arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
             arena_types!(impl_arena_allocatable_decoders, [$DecoderName [$($typaram),*]], 'tcx);
@@ -411,90 +431,98 @@ macro_rules! implement_ty_decoder {
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<ty::Ty<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Ty<'tcx>, Self::Error> {
-                    decode_ty(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::TyS<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::TyS<'_y>: UseSpecializedDecodable
+            {
+                fn specialized_decode(&mut self) -> Result<&'_x ty::TyS<'_y>, Self::Error> {
+                    unsafe { transmute::<Result<ty::Ty<'tcx>, Self::Error>, Result<&'_x ty::TyS<'_y>, Self::Error>>(decode_ty(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
-            for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x [(ty::Predicate<'_y>, Span)]>
+            for $DecoderName<$($typaram),*>
+            where &'_x [(ty::Predicate<'_y>, Span)]: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                                      -> Result<&'tcx [(ty::Predicate<'tcx>, Span)], Self::Error> {
-                    decode_spanned_predicates(self)
+                                      -> Result<&'_x [(ty::Predicate<'_y>, Span)], Self::Error>
+                {
+                    unsafe { transmute(decode_spanned_predicates(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<SubstsRef<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<SubstsRef<'tcx>, Self::Error> {
-                    decode_substs(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x InternalSubsts<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x InternalSubsts<'_y>: UseSpecializedDecodable {
+                fn specialized_decode(&mut self) -> Result<&'_x InternalSubsts<'_y>, Self::Error> {
+                    unsafe { transmute(decode_substs(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<$crate::mir::Place<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<$crate::mir::Place<'_x>>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(
                     &mut self
-                ) -> Result<$crate::mir::Place<'tcx>, Self::Error> {
-                    decode_place(self)
+                ) -> Result<$crate::mir::Place<'_x>, Self::Error> {
+                    unsafe { transmute(decode_place(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<ty::Region<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<ty::Region<'_x>>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<ty::Region<'tcx>, Self::Error> {
-                    decode_region(self)
+                fn specialized_decode(&mut self) -> Result<ty::Region<'_x>, Self::Error> {
+                    unsafe { transmute(decode_region(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::Ty<'tcx>>>
-            for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, '_z, $($typaram),*> SpecializedDecoder<&'_x ty::List<&'_y ty::TyS<'_z>>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::List<&'_y ty::TyS<'_z>>: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                                      -> Result<&'tcx ty::List<ty::Ty<'tcx>>, Self::Error> {
-                    decode_ty_slice(self)
+                                      -> Result<&'_x ty::List<&'_y ty::TyS<'_z>>, Self::Error> {
+                    unsafe { transmute(decode_ty_slice(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::AdtDef>
+            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x ty::AdtDef>
             for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::AdtDef, Self::Error> {
-                    decode_adt_def(self)
+                fn specialized_decode(&mut self) -> Result<&'_x ty::AdtDef, Self::Error> {
+                    unsafe { transmute(decode_adt_def(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>>
-                for $DecoderName<$($typaram),*> {
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x ty::List<ty::ExistentialPredicate<'_y>>>
+            for $DecoderName<$($typaram),*>
+            where &'_x ty::List<ty::ExistentialPredicate<'_y>>: UseSpecializedDecodable {
                 fn specialized_decode(&mut self)
-                    -> Result<&'tcx ty::List<ty::ExistentialPredicate<'tcx>>, Self::Error> {
-                    decode_existential_predicate_slice(self)
+                    -> Result<&'_x ty::List<ty::ExistentialPredicate<'_y>>, Self::Error> {
+                        unsafe { transmute(decode_existential_predicate_slice(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<CanonicalVarInfos<'tcx>>
+            impl<'_x, $($typaram),*> SpecializedDecoder<CanonicalVarInfos<'_x>>
                 for $DecoderName<$($typaram),*> {
                 fn specialized_decode(&mut self)
-                    -> Result<CanonicalVarInfos<'tcx>, Self::Error> {
-                    decode_canonical_var_infos(self)
+                    -> Result<CanonicalVarInfos<'_x>, Self::Error> {
+                        unsafe { transmute(decode_canonical_var_infos(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::ty::Const<'tcx>>
-            for $DecoderName<$($typaram),*> {
-                fn specialized_decode(&mut self) -> Result<&'tcx ty::Const<'tcx>, Self::Error> {
-                    decode_const(self)
+            impl<'_x, '_y, $($typaram),*> SpecializedDecoder<&'_x $crate::ty::Const<'_y>>
+            for $DecoderName<$($typaram),*>
+            where &'_x $crate::ty::Const<'_y>: UseSpecializedDecodable {
+                fn specialized_decode(&mut self) -> Result<&'_x ty::Const<'_y>, Self::Error> {
+                    unsafe { transmute(decode_const(self)) }
                 }
             }
 
-            impl<$($typaram),*> SpecializedDecoder<&'tcx $crate::mir::interpret::Allocation>
+            impl<'_x, $($typaram),*> SpecializedDecoder<&'_x $crate::mir::interpret::Allocation>
             for $DecoderName<$($typaram),*> {
                 fn specialized_decode(
                     &mut self
-                ) -> Result<&'tcx $crate::mir::interpret::Allocation, Self::Error> {
-                    decode_allocation(self)
+                ) -> Result<&'_x $crate::mir::interpret::Allocation, Self::Error> {
+                    unsafe { transmute(decode_allocation(self)) }
                 }
             }
         }
-    }
+    };
 }
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index d5be3508d2d80..4770993d9cb07 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1383,7 +1383,10 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
-    pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> {
+    pub fn return_type_impl_or_dyn_trait(
+        &self,
+        scope_def_id: DefId,
+    ) -> Option<&'tcx hir::Ty<'tcx>> {
         let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
         let hir_output = match self.hir().get(hir_id) {
             Node::Item(hir::Item {
@@ -1429,15 +1432,17 @@ impl<'tcx> TyCtxt<'tcx> {
                 let output = self.erase_late_bound_regions(&sig.output());
                 if output.is_impl_trait() {
                     let fn_decl = self.hir().fn_decl_by_hir_id(hir_id).unwrap();
-                    Some((fn_decl.output.span(), false))
+                    if let hir::FnRetTy::Return(ty) = fn_decl.output {
+                        return Some(ty);
+                    }
                 } else {
                     let mut v = TraitObjectVisitor(vec![]);
                     rustc_hir::intravisit::walk_ty(&mut v, hir_output);
                     if v.0.len() == 1 {
-                        return Some((v.0[0], true));
+                        return Some(v.0[0]);
                     }
-                    None
                 }
+                None
             }
             _ => None,
         }
diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs
index 2e9aa724ac5af..a2812e117ed39 100644
--- a/src/librustc_middle/ty/diagnostics.rs
+++ b/src/librustc_middle/ty/diagnostics.rs
@@ -236,21 +236,24 @@ pub fn suggest_constraining_type_param(
     }
 }
 
-pub struct TraitObjectVisitor(pub Vec<rustc_span::Span>);
-impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
+pub struct TraitObjectVisitor<'tcx>(pub Vec<&'tcx hir::Ty<'tcx>>);
+impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor<'v> {
     type Map = rustc_hir::intravisit::ErasedMap<'v>;
 
     fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
         hir::intravisit::NestedVisitorMap::None
     }
 
-    fn visit_ty(&mut self, ty: &hir::Ty<'_>) {
+    fn visit_ty(&mut self, ty: &'v hir::Ty<'v>) {
         if let hir::TyKind::TraitObject(
             _,
-            hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
+            hir::Lifetime {
+                name: hir::LifetimeName::ImplicitObjectLifetimeDefault | hir::LifetimeName::Static,
+                ..
+            },
         ) = ty.kind
         {
-            self.0.push(ty.span);
+            self.0.push(ty);
         }
     }
 }
diff --git a/src/librustc_middle/ty/query/on_disk_cache.rs b/src/librustc_middle/ty/query/on_disk_cache.rs
index 4eae06742d9d3..5374dff422425 100644
--- a/src/librustc_middle/ty/query/on_disk_cache.rs
+++ b/src/librustc_middle/ty/query/on_disk_cache.rs
@@ -1,6 +1,6 @@
 use crate::dep_graph::{DepNodeIndex, SerializedDepNodeIndex};
+use crate::mir::interpret;
 use crate::mir::interpret::{AllocDecodingSession, AllocDecodingState};
-use crate::mir::{self, interpret};
 use crate::ty::codec::{self as ty_codec, TyDecoder, TyEncoder};
 use crate::ty::context::TyCtxt;
 use crate::ty::{self, Ty};
@@ -26,9 +26,6 @@ use std::mem;
 
 const TAG_FILE_FOOTER: u128 = 0xC0FFEE_C0FFEE_C0FFEE_C0FFEE_C0FFEE;
 
-const TAG_CLEAR_CROSS_CRATE_CLEAR: u8 = 0;
-const TAG_CLEAR_CROSS_CRATE_SET: u8 = 1;
-
 const TAG_NO_EXPN_DATA: u8 = 0;
 const TAG_EXPN_DATA_SHORTHAND: u8 = 1;
 const TAG_EXPN_DATA_INLINE: u8 = 2;
@@ -667,24 +664,6 @@ impl<'a, 'tcx> SpecializedDecoder<Fingerprint> for CacheDecoder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, T: Decodable> SpecializedDecoder<mir::ClearCrossCrate<T>>
-    for CacheDecoder<'a, 'tcx>
-{
-    #[inline]
-    fn specialized_decode(&mut self) -> Result<mir::ClearCrossCrate<T>, Self::Error> {
-        let discr = u8::decode(self)?;
-
-        match discr {
-            TAG_CLEAR_CROSS_CRATE_CLEAR => Ok(mir::ClearCrossCrate::Clear),
-            TAG_CLEAR_CROSS_CRATE_SET => {
-                let val = T::decode(self)?;
-                Ok(mir::ClearCrossCrate::Set(val))
-            }
-            _ => unreachable!(),
-        }
-    }
-}
-
 //- ENCODING -------------------------------------------------------------------
 
 /// An encoder that can write the incr. comp. cache.
@@ -828,17 +807,20 @@ where
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<Ty<'tcx>> for CacheEncoder<'a, 'tcx, E>
+impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b ty::TyS<'c>> for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
+    &'b ty::TyS<'c>: UseSpecializedEncodable,
 {
     #[inline]
-    fn specialized_encode(&mut self, ty: &Ty<'tcx>) -> Result<(), Self::Error> {
+    fn specialized_encode(&mut self, ty: &&'b ty::TyS<'c>) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(ty).is_some());
+        let ty = unsafe { std::mem::transmute::<&&'b ty::TyS<'c>, &&'tcx ty::TyS<'tcx>>(ty) };
         ty_codec::encode_with_shorthand(self, ty, |encoder| &mut encoder.type_shorthands)
     }
 }
 
-impl<'a, 'tcx, E> SpecializedEncoder<&'tcx [(ty::Predicate<'tcx>, Span)]>
+impl<'a, 'b, 'c, 'tcx, E> SpecializedEncoder<&'b [(ty::Predicate<'c>, Span)]>
     for CacheEncoder<'a, 'tcx, E>
 where
     E: 'a + TyEncoder,
@@ -846,8 +828,15 @@ where
     #[inline]
     fn specialized_encode(
         &mut self,
-        predicates: &&'tcx [(ty::Predicate<'tcx>, Span)],
+        predicates: &&'b [(ty::Predicate<'c>, Span)],
     ) -> Result<(), Self::Error> {
+        debug_assert!(self.tcx.lift(*predicates).is_some());
+        let predicates = unsafe {
+            std::mem::transmute::<
+                &&'b [(ty::Predicate<'c>, Span)],
+                &&'tcx [(ty::Predicate<'tcx>, Span)],
+            >(predicates)
+        };
         ty_codec::encode_spanned_predicates(self, predicates, |encoder| {
             &mut encoder.predicate_shorthands
         })
@@ -890,23 +879,6 @@ impl<'a, 'tcx> SpecializedEncoder<Fingerprint> for CacheEncoder<'a, 'tcx, opaque
     }
 }
 
-impl<'a, 'tcx, E, T> SpecializedEncoder<mir::ClearCrossCrate<T>> for CacheEncoder<'a, 'tcx, E>
-where
-    E: 'a + TyEncoder,
-    T: Encodable,
-{
-    #[inline]
-    fn specialized_encode(&mut self, val: &mir::ClearCrossCrate<T>) -> Result<(), Self::Error> {
-        match *val {
-            mir::ClearCrossCrate::Clear => TAG_CLEAR_CROSS_CRATE_CLEAR.encode(self),
-            mir::ClearCrossCrate::Set(ref val) => {
-                TAG_CLEAR_CROSS_CRATE_SET.encode(self)?;
-                val.encode(self)
-            }
-        }
-    }
-}
-
 macro_rules! encoder_methods {
     ($($name:ident($ty:ty);)*) => {
         #[inline]
@@ -995,7 +967,7 @@ fn encode_query_results<'a, 'tcx, Q, E>(
     query_result_index: &mut EncodedQueryResultIndex,
 ) -> Result<(), E::Error>
 where
-    Q: super::QueryDescription<TyCtxt<'tcx>>,
+    Q: super::QueryDescription<TyCtxt<'tcx>> + super::QueryAccessors<TyCtxt<'tcx>>,
     Q::Value: Encodable,
     E: 'a + TyEncoder,
 {
diff --git a/src/librustc_middle/ty/query/profiling_support.rs b/src/librustc_middle/ty/query/profiling_support.rs
index e0d3e764dad83..3c44662441890 100644
--- a/src/librustc_middle/ty/query/profiling_support.rs
+++ b/src/librustc_middle/ty/query/profiling_support.rs
@@ -112,30 +112,53 @@ impl<T: Debug> IntoSelfProfilingString for T {
     }
 }
 
-impl IntoSelfProfilingString for DefId {
+impl<T: SpecIntoSelfProfilingString> IntoSelfProfilingString for T {
     fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+        self.spec_to_self_profile_string(builder)
+    }
+}
+
+#[rustc_specialization_trait]
+pub trait SpecIntoSelfProfilingString: Debug {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId;
+}
+
+impl SpecIntoSelfProfilingString for DefId {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(*self)
     }
 }
 
-impl IntoSelfProfilingString for CrateNum {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+impl SpecIntoSelfProfilingString for CrateNum {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(DefId { krate: *self, index: CRATE_DEF_INDEX })
     }
 }
 
-impl IntoSelfProfilingString for DefIndex {
-    fn to_self_profile_string(&self, builder: &mut QueryKeyStringBuilder<'_, '_, '_>) -> StringId {
+impl SpecIntoSelfProfilingString for DefIndex {
+    fn spec_to_self_profile_string(
+        &self,
+        builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
+    ) -> StringId {
         builder.def_id_to_string_id(DefId { krate: LOCAL_CRATE, index: *self })
     }
 }
 
-impl<T0, T1> IntoSelfProfilingString for (T0, T1)
+impl<T0, T1> SpecIntoSelfProfilingString for (T0, T1)
 where
-    T0: IntoSelfProfilingString + Debug,
-    T1: IntoSelfProfilingString + Debug,
+    T0: SpecIntoSelfProfilingString,
+    T1: SpecIntoSelfProfilingString,
 {
-    default fn to_self_profile_string(
+    fn spec_to_self_profile_string(
         &self,
         builder: &mut QueryKeyStringBuilder<'_, '_, '_>,
     ) -> StringId {
diff --git a/src/librustc_middle/ty/query/values.rs b/src/librustc_middle/ty/query/values.rs
index b01d15c29b2db..b1f76ff6a03bd 100644
--- a/src/librustc_middle/ty/query/values.rs
+++ b/src/librustc_middle/ty/query/values.rs
@@ -1,4 +1,4 @@
-use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt};
+use crate::ty::{self, AdtSizedConstraint, Ty, TyCtxt, TyS};
 
 use rustc_span::symbol::Symbol;
 
@@ -13,9 +13,11 @@ impl<'tcx, T> Value<'tcx> for T {
     }
 }
 
-impl<'tcx> Value<'tcx> for Ty<'tcx> {
-    fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
-        tcx.types.err
+impl<'tcx> Value<'tcx> for &'_ TyS<'_> {
+    fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
+        // SAFETY: This is never called when `Self` is not `Ty<'tcx>`.
+        // FIXME: Represent the above fact in the trait system somehow.
+        unsafe { std::mem::transmute::<Ty<'tcx>, Ty<'_>>(tcx.types.err) }
     }
 }
 
@@ -25,8 +27,14 @@ impl<'tcx> Value<'tcx> for ty::SymbolName {
     }
 }
 
-impl<'tcx> Value<'tcx> for AdtSizedConstraint<'tcx> {
+impl<'tcx> Value<'tcx> for AdtSizedConstraint<'_> {
     fn from_cycle_error(tcx: TyCtxt<'tcx>) -> Self {
-        AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err]))
+        // SAFETY: This is never called when `Self` is not `AdtSizedConstraint<'tcx>`.
+        // FIXME: Represent the above fact in the trait system somehow.
+        unsafe {
+            std::mem::transmute::<AdtSizedConstraint<'tcx>, AdtSizedConstraint<'_>>(
+                AdtSizedConstraint(tcx.intern_type_list(&[tcx.types.err])),
+            )
+        }
     }
 }
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index 7550be39d4ab0..fad96aa86cc0a 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -2409,8 +2409,6 @@ impl<'tcx> Const<'tcx> {
     }
 }
 
-impl<'tcx> rustc_serialize::UseSpecializedDecodable for &'tcx Const<'tcx> {}
-
 /// Represents a constant in Rust.
 #[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, RustcEncodable, RustcDecodable, Hash)]
 #[derive(HashStable)]
diff --git a/src/librustc_middle/ty/util.rs b/src/librustc_middle/ty/util.rs
index c61e27528cef1..866a35ebfa60d 100644
--- a/src/librustc_middle/ty/util.rs
+++ b/src/librustc_middle/ty/util.rs
@@ -878,7 +878,15 @@ impl<'tcx> ty::TyS<'tcx> {
                     // Find non representable fields with their spans
                     fold_repr(def.all_fields().map(|field| {
                         let ty = field.ty(tcx, substs);
-                        let span = tcx.hir().span_if_local(field.did).unwrap_or(sp);
+                        let span = match field
+                            .did
+                            .as_local()
+                            .map(|id| tcx.hir().as_local_hir_id(id))
+                            .and_then(|id| tcx.hir().find(id))
+                        {
+                            Some(hir::Node::Field(field)) => field.ty.span,
+                            _ => sp,
+                        };
                         match is_type_structurally_recursive(
                             tcx,
                             span,
diff --git a/src/librustc_query_system/dep_graph/dep_node.rs b/src/librustc_query_system/dep_graph/dep_node.rs
index d8875f8ac64a2..002b0f9c165dd 100644
--- a/src/librustc_query_system/dep_graph/dep_node.rs
+++ b/src/librustc_query_system/dep_graph/dep_node.rs
@@ -91,7 +91,7 @@ impl<K: DepKind> fmt::Debug for DepNode<K> {
 }
 
 pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
-    const CAN_RECONSTRUCT_QUERY_KEY: bool;
+    fn can_reconstruct_query_key() -> bool;
 
     /// This method turns the parameters of a DepNodeConstructor into an opaque
     /// Fingerprint to be used in DepNode.
@@ -108,7 +108,7 @@ pub trait DepNodeParams<Ctxt: DepContext>: fmt::Debug + Sized {
     /// This method tries to recover the query key from the given `DepNode`,
     /// something which is needed when forcing `DepNode`s during red-green
     /// evaluation. The query system will only call this method if
-    /// `CAN_RECONSTRUCT_QUERY_KEY` is `true`.
+    /// `can_reconstruct_query_key()` is `true`.
     /// It is always valid to return `None` here, in which case incremental
     /// compilation will treat the query as having changed instead of forcing it.
     fn recover(tcx: Ctxt, dep_node: &DepNode<Ctxt::DepKind>) -> Option<Self>;
@@ -118,7 +118,10 @@ impl<Ctxt: DepContext, T> DepNodeParams<Ctxt> for T
 where
     T: HashStable<Ctxt::StableHashingContext> + fmt::Debug,
 {
-    default const CAN_RECONSTRUCT_QUERY_KEY: bool = false;
+    #[inline]
+    default fn can_reconstruct_query_key() -> bool {
+        false
+    }
 
     default fn to_fingerprint(&self, tcx: Ctxt) -> Fingerprint {
         let mut hcx = tcx.create_stable_hashing_context();
diff --git a/src/librustc_query_system/lib.rs b/src/librustc_query_system/lib.rs
index 8e350d3ba267e..12450a4ccd3eb 100644
--- a/src/librustc_query_system/lib.rs
+++ b/src/librustc_query_system/lib.rs
@@ -4,7 +4,7 @@
 #![feature(const_panic)]
 #![feature(core_intrinsics)]
 #![feature(hash_raw_entry)]
-#![feature(specialization)] // FIXME: min_specialization rejects `default const`
+#![feature(min_specialization)]
 #![feature(stmt_expr_attributes)]
 #![feature(vec_remove_item)]
 
diff --git a/src/librustc_serialize/lib.rs b/src/librustc_serialize/lib.rs
index 7261d631a6f31..3dc3e78382096 100644
--- a/src/librustc_serialize/lib.rs
+++ b/src/librustc_serialize/lib.rs
@@ -10,7 +10,7 @@ Core encoding and decoding interfaces.
     test(attr(allow(unused_variables), deny(warnings)))
 )]
 #![feature(box_syntax)]
-#![feature(specialization)] // FIXME: min_specialization does not work
+#![feature(min_specialization)]
 #![feature(never_type)]
 #![feature(nll)]
 #![feature(associated_type_bounds)]
diff --git a/src/librustc_serialize/serialize.rs b/src/librustc_serialize/serialize.rs
index e80d16bb0c7ab..29c5737ad895a 100644
--- a/src/librustc_serialize/serialize.rs
+++ b/src/librustc_serialize/serialize.rs
@@ -635,24 +635,6 @@ impl<T> Decodable for PhantomData<T> {
     }
 }
 
-impl<'a, T: ?Sized + Encodable> Encodable for &'a T {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-
-impl<T: ?Sized + Encodable> Encodable for Box<T> {
-    fn encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
-        (**self).encode(s)
-    }
-}
-
-impl<T: Decodable> Decodable for Box<T> {
-    fn decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
-        Ok(box Decodable::decode(d)?)
-    }
-}
-
 impl<T: Decodable> Decodable for Box<[T]> {
     fn decode<D: Decoder>(d: &mut D) -> Result<Box<[T]>, D::Error> {
         let v: Vec<T> = Decodable::decode(d)?;
@@ -1008,8 +990,20 @@ impl<T: UseSpecializedDecodable> Decodable for T {
 // for this exact reason.
 // May be fixable in a simpler fashion via the
 // more complex lattice model for specialization.
-impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {}
-impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {}
-impl<T: Decodable> UseSpecializedDecodable for Box<T> {}
+impl<'a, T: ?Sized + Encodable> UseSpecializedEncodable for &'a T {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+impl<T: ?Sized + Encodable> UseSpecializedEncodable for Box<T> {
+    fn default_encode<S: Encoder>(&self, s: &mut S) -> Result<(), S::Error> {
+        (**self).encode(s)
+    }
+}
+impl<T: Decodable> UseSpecializedDecodable for Box<T> {
+    fn default_decode<D: Decoder>(d: &mut D) -> Result<Box<T>, D::Error> {
+        Ok(box Decodable::decode(d)?)
+    }
+}
 impl<'a, T: Decodable> UseSpecializedDecodable for &'a T {}
 impl<'a, T: Decodable> UseSpecializedDecodable for &'a [T] {}
diff --git a/src/librustc_target/spec/aarch64_apple_ios.rs b/src/librustc_target/spec/aarch64_apple_ios.rs
index eac2c3e6aa40c..1447716ca8484 100644
--- a/src/librustc_target/spec/aarch64_apple_ios.rs
+++ b/src/librustc_target/spec/aarch64_apple_ios.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/aarch64_apple_tvos.rs b/src/librustc_target/spec/aarch64_apple_tvos.rs
index f1cd14ffd11a6..21f660ac8b839 100644
--- a/src/librustc_target/spec/aarch64_apple_tvos.rs
+++ b/src/librustc_target/spec/aarch64_apple_tvos.rs
@@ -15,7 +15,7 @@ pub fn target() -> TargetResult {
         target_vendor: "apple".to_string(),
         linker_flavor: LinkerFlavor::Gcc,
         options: TargetOptions {
-            features: "+neon,+fp-armv8,+cyclone".to_string(),
+            features: "+neon,+fp-armv8,+apple-a7".to_string(),
             eliminate_frame_pointer: false,
             max_atomic_width: Some(128),
             abi_blacklist: super::arm_base::abi_blacklist(),
diff --git a/src/librustc_target/spec/apple_sdk_base.rs b/src/librustc_target/spec/apple_sdk_base.rs
index c7cff17b1544c..b07c2aef1caca 100644
--- a/src/librustc_target/spec/apple_sdk_base.rs
+++ b/src/librustc_target/spec/apple_sdk_base.rs
@@ -122,7 +122,7 @@ fn target_cpu(arch: Arch) -> String {
     match arch {
         Armv7 => "cortex-a8", // iOS7 is supported on iPhone 4 and higher
         Armv7s => "cortex-a9",
-        Arm64 => "cyclone",
+        Arm64 => "apple-a7",
         I386 => "yonah",
         X86_64 => "core2",
         X86_64_macabi => "core2",
diff --git a/src/librustc_trait_selection/infer.rs b/src/librustc_trait_selection/infer.rs
index 66df4fe951162..f244785b49d2f 100644
--- a/src/librustc_trait_selection/infer.rs
+++ b/src/librustc_trait_selection/infer.rs
@@ -90,7 +90,7 @@ pub trait InferCtxtBuilderExt<'tcx> {
     where
         K: TypeFoldable<'tcx>,
         R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable;
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>;
 }
 
 impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
@@ -118,7 +118,7 @@ impl<'tcx> InferCtxtBuilderExt<'tcx> for InferCtxtBuilder<'tcx> {
     where
         K: TypeFoldable<'tcx>,
         R: Debug + TypeFoldable<'tcx>,
-        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable,
+        Canonical<'tcx, QueryResponse<'tcx, R>>: ArenaAllocatable<'tcx>,
     {
         self.enter_with_canonical(
             DUMMY_SP,
diff --git a/src/librustc_trait_selection/lib.rs b/src/librustc_trait_selection/lib.rs
index 044239b047a4e..ea886cd1f9e9b 100644
--- a/src/librustc_trait_selection/lib.rs
+++ b/src/librustc_trait_selection/lib.rs
@@ -16,7 +16,6 @@
 #![feature(in_band_lifetimes)]
 #![feature(crate_visibility_modifier)]
 #![feature(or_patterns)]
-#![feature(option_zip)]
 #![recursion_limit = "512"] // For rustdoc
 
 #[macro_use]
diff --git a/src/librustc_trait_selection/traits/error_reporting/mod.rs b/src/librustc_trait_selection/traits/error_reporting/mod.rs
index 1b72a4bf84f19..d31e04cffd55f 100644
--- a/src/librustc_trait_selection/traits/error_reporting/mod.rs
+++ b/src/librustc_trait_selection/traits/error_reporting/mod.rs
@@ -1747,24 +1747,41 @@ impl<'a, 'tcx> InferCtxtPrivExt<'tcx> for InferCtxt<'a, 'tcx> {
 pub fn recursive_type_with_infinite_size_error(
     tcx: TyCtxt<'tcx>,
     type_def_id: DefId,
-) -> DiagnosticBuilder<'tcx> {
+    spans: Vec<Span>,
+) {
     assert!(type_def_id.is_local());
     let span = tcx.hir().span_if_local(type_def_id).unwrap();
     let span = tcx.sess.source_map().guess_head_span(span);
-    let mut err = struct_span_err!(
-        tcx.sess,
-        span,
-        E0072,
-        "recursive type `{}` has infinite size",
-        tcx.def_path_str(type_def_id)
-    );
+    let path = tcx.def_path_str(type_def_id);
+    let mut err =
+        struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size", path);
     err.span_label(span, "recursive type has infinite size");
-    err.help(&format!(
-        "insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                           at some point to make `{}` representable",
-        tcx.def_path_str(type_def_id)
-    ));
-    err
+    for &span in &spans {
+        err.span_label(span, "recursive without indirection");
+    }
+    let msg = format!(
+        "insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `{}` representable",
+        path,
+    );
+    if spans.len() <= 4 {
+        err.multipart_suggestion(
+            &msg,
+            spans
+                .iter()
+                .flat_map(|&span| {
+                    vec![
+                        (span.shrink_to_lo(), "Box<".to_string()),
+                        (span.shrink_to_hi(), ">".to_string()),
+                    ]
+                    .into_iter()
+                })
+                .collect(),
+            Applicability::HasPlaceholders,
+        );
+    } else {
+        err.help(&msg);
+    }
+    err.emit();
 }
 
 /// Summarizes information
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 7b8f180219688..a409e20953da1 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -2387,11 +2387,7 @@ fn check_representable(tcx: TyCtxt<'_>, sp: Span, item_def_id: LocalDefId) -> bo
     // caught by case 1.
     match rty.is_representable(tcx, sp) {
         Representability::SelfRecursive(spans) => {
-            let mut err = recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id());
-            for span in spans {
-                err.span_label(span, "recursive without indirection");
-            }
-            err.emit();
+            recursive_type_with_infinite_size_error(tcx, item_def_id.to_def_id(), spans);
             return false;
         }
         Representability::Representable | Representability::ContainsRecursive => (),
diff --git a/src/libstd/Cargo.toml b/src/libstd/Cargo.toml
index 6af1cbb34b6c4..83029a8642097 100644
--- a/src/libstd/Cargo.toml
+++ b/src/libstd/Cargo.toml
@@ -41,7 +41,7 @@ dlmalloc = { version = "0.1", features = ['rustc-dep-of-std'] }
 fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
 
 [target.'cfg(all(any(target_arch = "x86_64", target_arch = "aarch64"), target_os = "hermit"))'.dependencies]
-hermit-abi = { version = "0.1.13", features = ['rustc-dep-of-std'] }
+hermit-abi = { version = "0.1.14", features = ['rustc-dep-of-std'] }
 
 [target.wasm32-wasi.dependencies]
 wasi = { version = "0.9.0", features = ['rustc-dep-of-std'], default-features = false }
diff --git a/src/libstd/ffi/c_str.rs b/src/libstd/ffi/c_str.rs
index b324b1618966b..dca1fdde48242 100644
--- a/src/libstd/ffi/c_str.rs
+++ b/src/libstd/ffi/c_str.rs
@@ -234,15 +234,14 @@ pub struct NulError(usize, Vec<u8>);
 
 /// An error indicating that a nul byte was not in the expected position.
 ///
-/// The slice used to create a [`CStr`] must have one and only one nul
-/// byte at the end of the slice.
+/// The slice used to create a [`CStr`] must have one and only one nul byte,
+/// positioned at the end.
 ///
-/// This error is created by the
-/// [`from_bytes_with_nul`][`CStr::from_bytes_with_nul`] method on
-/// [`CStr`]. See its documentation for more.
+/// This error is created by the [`from_bytes_with_nul`] method on [`CStr`].
+/// See its documentation for more.
 ///
 /// [`CStr`]: struct.CStr.html
-/// [`CStr::from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
+/// [`from_bytes_with_nul`]: struct.CStr.html#method.from_bytes_with_nul
 ///
 /// # Examples
 ///
@@ -257,6 +256,32 @@ pub struct FromBytesWithNulError {
     kind: FromBytesWithNulErrorKind,
 }
 
+/// An error indicating that a nul byte was not in the expected position.
+///
+/// The vector used to create a [`CString`] must have one and only one nul byte,
+/// positioned at the end.
+///
+/// This error is created by the [`from_vec_with_nul`] method on [`CString`].
+/// See its documentation for more.
+///
+/// [`CString`]: struct.CString.html
+/// [`from_vec_with_nul`]: struct.CString.html#method.from_vec_with_nul
+///
+/// # Examples
+///
+/// ```
+/// #![feature(cstring_from_vec_with_nul)]
+/// use std::ffi::{CString, FromVecWithNulError};
+///
+/// let _: FromVecWithNulError = CString::from_vec_with_nul(b"f\0oo".to_vec()).unwrap_err();
+/// ```
+#[derive(Clone, PartialEq, Eq, Debug)]
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+pub struct FromVecWithNulError {
+    error_kind: FromBytesWithNulErrorKind,
+    bytes: Vec<u8>,
+}
+
 #[derive(Clone, PartialEq, Eq, Debug)]
 enum FromBytesWithNulErrorKind {
     InteriorNul(usize),
@@ -272,6 +297,59 @@ impl FromBytesWithNulError {
     }
 }
 
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl FromVecWithNulError {
+    /// Returns a slice of [`u8`]s bytes that were attempted to convert to a [`CString`].
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    ///
+    /// // Some invalid bytes in a vector
+    /// let bytes = b"f\0oo".to_vec();
+    ///
+    /// let value = CString::from_vec_with_nul(bytes.clone());
+    ///
+    /// assert_eq!(&bytes[..], value.unwrap_err().as_bytes());
+    /// ```
+    ///
+    /// [`CString`]: struct.CString.html
+    pub fn as_bytes(&self) -> &[u8] {
+        &self.bytes[..]
+    }
+
+    /// Returns the bytes that were attempted to convert to a [`CString`].
+    ///
+    /// This method is carefully constructed to avoid allocation. It will
+    /// consume the error, moving out the bytes, so that a copy of the bytes
+    /// does not need to be made.
+    ///
+    /// # Examples
+    ///
+    /// Basic usage:
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    ///
+    /// // Some invalid bytes in a vector
+    /// let bytes = b"f\0oo".to_vec();
+    ///
+    /// let value = CString::from_vec_with_nul(bytes.clone());
+    ///
+    /// assert_eq!(bytes, value.unwrap_err().into_bytes());
+    /// ```
+    ///
+    /// [`CString`]: struct.CString.html
+    pub fn into_bytes(self) -> Vec<u8> {
+        self.bytes
+    }
+}
+
 /// An error indicating invalid UTF-8 when converting a [`CString`] into a [`String`].
 ///
 /// `CString` is just a wrapper over a buffer of bytes with a nul
@@ -643,6 +721,86 @@ impl CString {
         let this = mem::ManuallyDrop::new(self);
         unsafe { ptr::read(&this.inner) }
     }
+
+    /// Converts a `Vec` of `u8` to a `CString` without checking the invariants
+    /// on the given `Vec`.
+    ///
+    /// # Safety
+    ///
+    /// The given `Vec` **must** have one nul byte as its last element.
+    /// This means it cannot be empty nor have any other nul byte anywhere else.
+    ///
+    /// # Example
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    /// assert_eq!(
+    ///     unsafe { CString::from_vec_with_nul_unchecked(b"abc\0".to_vec()) },
+    ///     unsafe { CString::from_vec_unchecked(b"abc".to_vec()) }
+    /// );
+    /// ```
+    #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+    pub unsafe fn from_vec_with_nul_unchecked(v: Vec<u8>) -> Self {
+        Self { inner: v.into_boxed_slice() }
+    }
+
+    /// Attempts to converts a `Vec` of `u8` to a `CString`.
+    ///
+    /// Runtime checks are present to ensure there is only one nul byte in the
+    /// `Vec`, its last element.
+    ///
+    /// # Errors
+    ///
+    /// If a nul byte is present and not the last element or no nul bytes
+    /// is present, an error will be returned.
+    ///
+    /// # Examples
+    ///
+    /// A successful conversion will produce the same result as [`new`] when
+    /// called without the ending nul byte.
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::CString;
+    /// assert_eq!(
+    ///     CString::from_vec_with_nul(b"abc\0".to_vec())
+    ///         .expect("CString::from_vec_with_nul failed"),
+    ///     CString::new(b"abc".to_vec()).expect("CString::new failed")
+    /// );
+    /// ```
+    ///
+    /// A incorrectly formatted vector will produce an error.
+    ///
+    /// ```
+    /// #![feature(cstring_from_vec_with_nul)]
+    /// use std::ffi::{CString, FromVecWithNulError};
+    /// // Interior nul byte
+    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"a\0bc".to_vec()).unwrap_err();
+    /// // No nul byte
+    /// let _: FromVecWithNulError = CString::from_vec_with_nul(b"abc".to_vec()).unwrap_err();
+    /// ```
+    ///
+    /// [`new`]: #method.new
+    #[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+    pub fn from_vec_with_nul(v: Vec<u8>) -> Result<Self, FromVecWithNulError> {
+        let nul_pos = memchr::memchr(0, &v);
+        match nul_pos {
+            Some(nul_pos) if nul_pos + 1 == v.len() => {
+                // SAFETY: We know there is only one nul byte, at the end
+                // of the vec.
+                Ok(unsafe { Self::from_vec_with_nul_unchecked(v) })
+            }
+            Some(nul_pos) => Err(FromVecWithNulError {
+                error_kind: FromBytesWithNulErrorKind::InteriorNul(nul_pos),
+                bytes: v,
+            }),
+            None => Err(FromVecWithNulError {
+                error_kind: FromBytesWithNulErrorKind::NotNulTerminated,
+                bytes: v,
+            }),
+        }
+    }
 }
 
 // Turns this `CString` into an empty string to prevent
@@ -976,6 +1134,23 @@ impl fmt::Display for FromBytesWithNulError {
     }
 }
 
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl Error for FromVecWithNulError {}
+
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+impl fmt::Display for FromVecWithNulError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.error_kind {
+            FromBytesWithNulErrorKind::InteriorNul(pos) => {
+                write!(f, "data provided contains an interior nul byte at pos {}", pos)
+            }
+            FromBytesWithNulErrorKind::NotNulTerminated => {
+                write!(f, "data provided is not nul terminated")
+            }
+        }
+    }
+}
+
 impl IntoStringError {
     /// Consumes this error, returning original [`CString`] which generated the
     /// error.
diff --git a/src/libstd/ffi/mod.rs b/src/libstd/ffi/mod.rs
index 5aca7b7476a52..f442d7fde1a5e 100644
--- a/src/libstd/ffi/mod.rs
+++ b/src/libstd/ffi/mod.rs
@@ -157,6 +157,8 @@
 
 #[stable(feature = "cstr_from_bytes", since = "1.10.0")]
 pub use self::c_str::FromBytesWithNulError;
+#[unstable(feature = "cstring_from_vec_with_nul", issue = "73179")]
+pub use self::c_str::FromVecWithNulError;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use self::c_str::{CStr, CString, IntoStringError, NulError};
 
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index b780340884e1f..b8fa1a7f744d3 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -694,42 +694,6 @@ impl PartialEq for SocketAddrV6 {
             && self.inner.sin6_scope_id == other.inner.sin6_scope_id
     }
 }
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddrV4> for SocketAddr {
-    fn eq(&self, other: &SocketAddrV4) -> bool {
-        match self {
-            SocketAddr::V4(v4) => v4 == other,
-            SocketAddr::V6(_) => false,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddrV6> for SocketAddr {
-    fn eq(&self, other: &SocketAddrV6) -> bool {
-        match self {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(v6) => v6 == other,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddr> for SocketAddrV4 {
-    fn eq(&self, other: &SocketAddr) -> bool {
-        match other {
-            SocketAddr::V4(v4) => self == v4,
-            SocketAddr::V6(_) => false,
-        }
-    }
-}
-#[stable(feature = "socketaddr_ordering", since = "1.45.0")]
-impl PartialEq<SocketAddr> for SocketAddrV6 {
-    fn eq(&self, other: &SocketAddr) -> bool {
-        match other {
-            SocketAddr::V4(_) => false,
-            SocketAddr::V6(v6) => self == v6,
-        }
-    }
-}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl Eq for SocketAddrV4 {}
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1242,12 +1206,8 @@ mod tests {
         // equality
         assert_eq!(v4_1, v4_1);
         assert_eq!(v6_1, v6_1);
-        assert_eq!(v4_1, SocketAddr::V4(v4_1));
-        assert_eq!(v6_1, SocketAddr::V6(v6_1));
         assert_eq!(SocketAddr::V4(v4_1), SocketAddr::V4(v4_1));
         assert_eq!(SocketAddr::V6(v6_1), SocketAddr::V6(v6_1));
-        assert!(v4_1 != SocketAddr::V6(v6_1));
-        assert!(v6_1 != SocketAddr::V4(v4_1));
         assert!(v4_1 != v4_2);
         assert!(v6_1 != v6_2);
 
@@ -1268,5 +1228,10 @@ mod tests {
         assert!(v6_1 < v6_3);
         assert!(v4_3 > v4_1);
         assert!(v6_3 > v6_1);
+
+        // compare with an inferred right-hand side
+        assert_eq!(v4_1, "224.120.45.1:23456".parse().unwrap());
+        assert_eq!(v6_1, "[2001:db8:f00::1002]:23456".parse().unwrap());
+        assert_eq!(SocketAddr::V4(v4_1), "224.120.45.1:23456".parse().unwrap());
     }
 }
diff --git a/src/libstd/sync/mutex.rs b/src/libstd/sync/mutex.rs
index 797b22fdd1279..8478457eabfc2 100644
--- a/src/libstd/sync/mutex.rs
+++ b/src/libstd/sync/mutex.rs
@@ -107,6 +107,60 @@ use crate::sys_common::poison::{self, LockResult, TryLockError, TryLockResult};
 ///
 /// *guard += 1;
 /// ```
+///
+/// It is sometimes necessary to manually drop the mutex guard to unlock it
+/// sooner than the end of the enclosing scope.
+///
+/// ```
+/// use std::sync::{Arc, Mutex};
+/// use std::thread;
+///
+/// const N: usize = 3;
+///
+/// let data_mutex = Arc::new(Mutex::new(vec![1, 2, 3, 4]));
+/// let res_mutex = Arc::new(Mutex::new(0));
+///
+/// let mut threads = Vec::with_capacity(N);
+/// (0..N).for_each(|_| {
+///     let data_mutex_clone = Arc::clone(&data_mutex);
+///     let res_mutex_clone = Arc::clone(&res_mutex);
+///
+///     threads.push(thread::spawn(move || {
+///         let mut data = data_mutex_clone.lock().unwrap();
+///         // This is the result of some important and long-ish work.
+///         let result = data.iter().fold(0, |acc, x| acc + x * 2);
+///         data.push(result);
+///         drop(data);
+///         *res_mutex_clone.lock().unwrap() += result;
+///     }));
+/// });
+///
+/// let mut data = data_mutex.lock().unwrap();
+/// // This is the result of some important and long-ish work.
+/// let result = data.iter().fold(0, |acc, x| acc + x * 2);
+/// data.push(result);
+/// // We drop the `data` explicitly because it's not necessary anymore and the
+/// // thread still has work to do. This allow other threads to start working on
+/// // the data immediately, without waiting for the rest of the unrelated work
+/// // to be done here.
+/// //
+/// // It's even more important here than in the threads because we `.join` the
+/// // threads after that. If we had not dropped the mutex guard, a thread could
+/// // be waiting forever for it, causing a deadlock.
+/// drop(data);
+/// // Here the mutex guard is not assigned to a variable and so, even if the
+/// // scope does not end after this line, the mutex is still released: there is
+/// // no deadlock.
+/// *res_mutex.lock().unwrap() += result;
+///
+/// threads.into_iter().for_each(|thread| {
+///     thread
+///         .join()
+///         .expect("The thread creating or execution failed !")
+/// });
+///
+/// assert_eq!(*res_mutex.lock().unwrap(), 800);
+/// ```
 #[stable(feature = "rust1", since = "1.0.0")]
 #[cfg_attr(not(test), rustc_diagnostic_item = "mutex_type")]
 pub struct Mutex<T: ?Sized> {
diff --git a/src/libstd/sys/hermit/net.rs b/src/libstd/sys/hermit/net.rs
index 5b5379c8b0581..9e588c4265ac2 100644
--- a/src/libstd/sys/hermit/net.rs
+++ b/src/libstd/sys/hermit/net.rs
@@ -1,10 +1,13 @@
 use crate::convert::TryFrom;
 use crate::fmt;
 use crate::io::{self, ErrorKind, IoSlice, IoSliceMut};
-use crate::net::{Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
+use crate::net::{IpAddr, Ipv4Addr, Ipv6Addr, Shutdown, SocketAddr};
 use crate::str;
+use crate::sync::Arc;
 use crate::sys::hermit::abi;
+use crate::sys::hermit::abi::IpAddress::{Ipv4, Ipv6};
 use crate::sys::{unsupported, Void};
+use crate::sys_common::AsInner;
 use crate::time::Duration;
 
 /// Checks whether the HermitCore's socket interface has been started already, and
@@ -17,14 +20,33 @@ pub fn init() -> io::Result<()> {
     Ok(())
 }
 
-pub struct TcpStream(abi::Handle);
+#[derive(Debug, Clone)]
+pub struct Socket(abi::Handle);
+
+impl AsInner<abi::Handle> for Socket {
+    fn as_inner(&self) -> &abi::Handle {
+        &self.0
+    }
+}
+
+impl Drop for Socket {
+    fn drop(&mut self) {
+        let _ = abi::tcpstream::close(self.0);
+    }
+}
+
+// Arc is used to count the number of used sockets.
+// Only if all sockets are released, the drop
+// method will close the socket.
+#[derive(Clone)]
+pub struct TcpStream(Arc<Socket>);
 
 impl TcpStream {
     pub fn connect(addr: io::Result<&SocketAddr>) -> io::Result<TcpStream> {
         let addr = addr?;
 
         match abi::tcpstream::connect(addr.ip().to_string().as_bytes(), addr.port(), None) {
-            Ok(handle) => Ok(TcpStream(handle)),
+            Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => {
                 Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
             }
@@ -37,7 +59,7 @@ impl TcpStream {
             saddr.port(),
             Some(duration.as_millis() as u64),
         ) {
-            Ok(handle) => Ok(TcpStream(handle)),
+            Ok(handle) => Ok(TcpStream(Arc::new(Socket(handle)))),
             _ => {
                 Err(io::Error::new(ErrorKind::Other, "Unable to initiate a connection on a socket"))
             }
@@ -45,31 +67,34 @@ impl TcpStream {
     }
 
     pub fn set_read_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
-        abi::tcpstream::set_read_timeout(self.0, duration.map(|d| d.as_millis() as u64))
+        abi::tcpstream::set_read_timeout(*self.0.as_inner(), duration.map(|d| d.as_millis() as u64))
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
     }
 
     pub fn set_write_timeout(&self, duration: Option<Duration>) -> io::Result<()> {
-        abi::tcpstream::set_write_timeout(self.0, duration.map(|d| d.as_millis() as u64))
-            .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
+        abi::tcpstream::set_write_timeout(
+            *self.0.as_inner(),
+            duration.map(|d| d.as_millis() as u64),
+        )
+        .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to set timeout value"))
     }
 
     pub fn read_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_read_timeout(self.0)
+        let duration = abi::tcpstream::get_read_timeout(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn write_timeout(&self) -> io::Result<Option<Duration>> {
-        let duration = abi::tcpstream::get_write_timeout(self.0)
+        let duration = abi::tcpstream::get_write_timeout(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to determine timeout value"))?;
 
         Ok(duration.map(|d| Duration::from_millis(d)))
     }
 
     pub fn peek(&self, buf: &mut [u8]) -> io::Result<usize> {
-        abi::tcpstream::peek(self.0, buf)
+        abi::tcpstream::peek(*self.0.as_inner(), buf)
             .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
     }
 
@@ -81,18 +106,11 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter_mut() {
-            let mut pos: usize = 0;
-
-            while pos < i.len() {
-                let ret = abi::tcpstream::read(self.0, &mut i[pos..])
-                    .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
-
-                if ret == 0 {
-                    return Ok(size);
-                } else {
-                    size += ret;
-                    pos += ret;
-                }
+            let ret = abi::tcpstream::read(*self.0.as_inner(), &mut i[0..])
+                .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to read on socket"))?;
+
+            if ret != 0 {
+                size += ret;
             }
         }
 
@@ -112,7 +130,7 @@ impl TcpStream {
         let mut size: usize = 0;
 
         for i in ioslice.iter() {
-            size += abi::tcpstream::write(self.0, i)
+            size += abi::tcpstream::write(*self.0.as_inner(), i)
                 .map_err(|_| io::Error::new(ErrorKind::Other, "Unable to write on socket"))?;
         }
 
@@ -125,7 +143,21 @@ impl TcpStream {
     }
 
     pub fn peer_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "peer_addr isn't supported"))
+        let (ipaddr, port) = abi::tcpstream::peer_addr(*self.0.as_inner())
+            .map_err(|_| io::Error::new(ErrorKind::Other, "peer_addr failed"))?;
+
+        let saddr = match ipaddr {
+            Ipv4(ref addr) => SocketAddr::new(
+                IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
+                port,
+            ),
+            Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
+            _ => {
+                return Err(io::Error::new(ErrorKind::Other, "peer_addr failed"));
+            }
+        };
+
+        Ok(saddr)
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
@@ -133,34 +165,31 @@ impl TcpStream {
     }
 
     pub fn shutdown(&self, how: Shutdown) -> io::Result<()> {
-        abi::tcpstream::shutdown(self.0, how as i32)
+        abi::tcpstream::shutdown(*self.0.as_inner(), how as i32)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to shutdown socket"))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpStream> {
-        let handle = abi::tcpstream::duplicate(self.0)
-            .map_err(|_| io::Error::new(ErrorKind::Other, "unable to duplicate stream"))?;
-
-        Ok(TcpStream(handle))
+        Ok(self.clone())
     }
 
     pub fn set_nodelay(&self, mode: bool) -> io::Result<()> {
-        abi::tcpstream::set_nodelay(self.0, mode)
+        abi::tcpstream::set_nodelay(*self.0.as_inner(), mode)
             .map_err(|_| io::Error::new(ErrorKind::Other, "set_nodelay failed"))
     }
 
     pub fn nodelay(&self) -> io::Result<bool> {
-        abi::tcpstream::nodelay(self.0)
+        abi::tcpstream::nodelay(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "nodelay failed"))
     }
 
     pub fn set_ttl(&self, tll: u32) -> io::Result<()> {
-        abi::tcpstream::set_tll(self.0, tll)
+        abi::tcpstream::set_tll(*self.0.as_inner(), tll)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set TTL"))
     }
 
     pub fn ttl(&self) -> io::Result<u32> {
-        abi::tcpstream::get_tll(self.0)
+        abi::tcpstream::get_tll(*self.0.as_inner())
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to get TTL"))
     }
 
@@ -169,40 +198,50 @@ impl TcpStream {
     }
 
     pub fn set_nonblocking(&self, mode: bool) -> io::Result<()> {
-        abi::tcpstream::set_nonblocking(self.0, mode)
+        abi::tcpstream::set_nonblocking(*self.0.as_inner(), mode)
             .map_err(|_| io::Error::new(ErrorKind::Other, "unable to set blocking mode"))
     }
 }
 
-impl Drop for TcpStream {
-    fn drop(&mut self) {
-        let _ = abi::tcpstream::close(self.0);
-    }
-}
-
 impl fmt::Debug for TcpStream {
     fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
         Ok(())
     }
 }
 
-pub struct TcpListener(abi::Handle);
+#[derive(Clone)]
+pub struct TcpListener(SocketAddr);
 
 impl TcpListener {
-    pub fn bind(_: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+    pub fn bind(addr: io::Result<&SocketAddr>) -> io::Result<TcpListener> {
+        let addr = addr?;
+
+        Ok(TcpListener(*addr))
     }
 
     pub fn socket_addr(&self) -> io::Result<SocketAddr> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Ok(self.0)
     }
 
     pub fn accept(&self) -> io::Result<(TcpStream, SocketAddr)> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        let (handle, ipaddr, port) = abi::tcplistener::accept(self.0.port())
+            .map_err(|_| io::Error::new(ErrorKind::Other, "accept failed"))?;
+        let saddr = match ipaddr {
+            Ipv4(ref addr) => SocketAddr::new(
+                IpAddr::V4(Ipv4Addr::new(addr.0[0], addr.0[1], addr.0[2], addr.0[3])),
+                port,
+            ),
+            Ipv6(ref addr) => SocketAddr::new(IpAddr::V6(Ipv6Addr::from(addr.0)), port),
+            _ => {
+                return Err(io::Error::new(ErrorKind::Other, "accept failed"));
+            }
+        };
+
+        Ok((TcpStream(Arc::new(Socket(handle))), saddr))
     }
 
     pub fn duplicate(&self) -> io::Result<TcpListener> {
-        Err(io::Error::new(ErrorKind::Other, "not supported"))
+        Ok(self.clone())
     }
 
     pub fn set_ttl(&self, _: u32) -> io::Result<()> {
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index af8fc2cd2ab45..0f58b158904db 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -1,13 +1,14 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
    |                               ^^^^^
    |                               |
-   |                               data with this lifetime...
+   |                               this data with an anonymous lifetime `'_`...
    |                               ...is captured here...
 LL |         foo(|| self.bar()).await;
-   |         --- ...and required to be `'static` by this
+   |         --- ...and is required to live as long as `'static` here
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
index 1806d2607a3ac..ca9ca8a9debe2 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.nll.stderr
@@ -26,7 +26,34 @@ LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                ^^^^^^^^^^^^^^
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |               -                              ^ returning this value requires that `'1` must outlive `'static`
+   |               |
+   |               let's call the lifetime of this reference `'1`
+   |
+   = help: consider replacing `'1` with `'static`
+
+error: lifetime may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |              -- lifetime `'a` defined here            ^ returning this value requires that `'a` must outlive `'static`
+   |
+   = help: consider replacing `'a` with `'static`
+   = help: consider replacing `'a` with `'static`
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/must_outlive_least_region_or_bound.rs:15:41
+   |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+   |               ----                      ^ lifetime `'a` required
+   |               |
+   |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error: lifetime may not live long enough
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    |               -- lifetime `'a` defined here                         ^ returning this value requires that `'a` must outlive `'static`
@@ -35,7 +62,7 @@ LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
    = help: consider replacing `'a` with `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:38:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                          --  -- lifetime `'b` defined here  ^^^^^^^^^^^^^^^^ opaque type requires that `'b` must outlive `'a`
@@ -45,13 +72,14 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    = help: consider adding the following bound: `'b: 'a`
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:43:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                                   ^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
 
-error: aborting due to 5 previous errors
+error: aborting due to 8 previous errors
 
-For more information about this error, try `rustc --explain E0310`.
+Some errors have detailed explanations: E0310, E0621.
+For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
index 00f3490991b52..837244b022721 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.rs
@@ -6,6 +6,27 @@ fn elided(x: &i32) -> impl Copy { x }
 fn explicit<'a>(x: &'a i32) -> impl Copy { x }
 //~^ ERROR cannot infer an appropriate lifetime
 
+fn elided2(x: &i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+//~^ ERROR explicit lifetime required in the type of `x`
+
+fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
+fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+//~^ ERROR cannot infer an appropriate lifetime
+
 trait LifetimeTrait<'a> {}
 impl<'a> LifetimeTrait<'a> for &'a i32 {}
 
diff --git a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
index d7dae6a08a7b9..e1fa4f02b6fcf 100644
--- a/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
+++ b/src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr
@@ -1,47 +1,113 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |              ----     ---------   ^ ...and is captured here
-   |              |        |
-   |              |        ...is required to be `'static` by this...
-   |              data with this lifetime...
+   |              ----                 ^ ...is captured here...
+   |              |
+   |              this data with an anonymous lifetime `'_`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:3:23
+   |
+LL | fn elided(x: &i32) -> impl Copy { x }
+   |                       ^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'_` lifetime bound
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
    |                                 ^^^^
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:6:44
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |                    -------     ---------   ^ ...and is captured here
-   |                    |           |
-   |                    |           ...is required to be `'static` by this...
-   |                    data with this lifetime...
+   |                    -------                 ^ ...is captured here...
+   |                    |
+   |                    this data with lifetime `'a`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 6:13
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:6:32
+   |
+LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
+   |                                ^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `x`, you can add an explicit `'a` lifetime bound
    |
 LL | fn explicit<'a>(x: &'a i32) -> impl Copy + 'a { x }
    |                                          ^^^^
 
-error: cannot infer an appropriate lifetime
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:69
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:46
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |               ----                           ^ ...is captured here...
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:9:24
+   |
+LL | fn elided2(x: &i32) -> impl Copy + 'static { x }
+   |                        ^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn elided2(x: &i32) -> impl Copy + '_ { x }
+   |                                    ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn elided2(x: &'static i32) -> impl Copy + 'static { x }
+   |               ^^^^^^^^^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:55
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |                     -------                           ^ ...is captured here...
+   |                     |
+   |                     this data with lifetime `'a`...
+   |
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:12:33
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'static { x }
+   |                                 ^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn explicit2<'a>(x: &'a i32) -> impl Copy + 'a { x }
+   |                                             ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn explicit2<'a>(x: &'static i32) -> impl Copy + 'static { x }
+   |                     ^^^^^^^^^^^^
+
+error[E0621]: explicit lifetime required in the type of `x`
+  --> $DIR/must_outlive_least_region_or_bound.rs:15:24
+   |
+LL | fn foo<'a>(x: &i32) -> impl Copy + 'a { x }
+   |               ----     ^^^^^^^^^^^^^^ lifetime `'a` required
+   |               |
+   |               help: add explicit lifetime `'a` to the type of `x`: `&'a i32`
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:69
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                      -------     --------------------------------   ^ ...and is captured here
-   |                      |           |
-   |                      |           ...is required to be `'static` by this...
-   |                      data with this lifetime...
+   |                      ------- this data with lifetime `'a`...        ^ ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the function body at 12:15
+note: ...and is required to live as long as `'static` here
+  --> $DIR/must_outlive_least_region_or_bound.rs:33:34
+   |
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: consider changing the `impl Trait`'s explicit `'static` bound to the lifetime of argument `x`
    |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
-   |                                                                   ^^^^
+LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'a { x }
+   |                                                           ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn with_bound<'a>(x: &'static i32) -> impl LifetimeTrait<'a> + 'static { x }
+   |                      ^^^^^^^^^^^^
 
 error[E0623]: lifetime mismatch
-  --> $DIR/must_outlive_least_region_or_bound.rs:17:61
+  --> $DIR/must_outlive_least_region_or_bound.rs:38:61
    |
 LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32) {
    |                                                 -------     ^^^^^^^^^^^^^^^^
@@ -50,14 +116,72 @@ LL | fn move_lifetime_into_fn<'a, 'b>(x: &'a u32, y: &'b u32) -> impl Fn(&'a u32
    |                                                 this parameter and the return type are declared with different lifetimes...
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
+  --> $DIR/must_outlive_least_region_or_bound.rs:43:51
    |
 LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
    |                                 --                ^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |                                 |
    |                                 help: consider adding an explicit lifetime bound...: `T: 'static +`
 
-error: aborting due to 5 previous errors
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:18:50
+   |
+LL | fn elided3(x: &i32) -> Box<dyn Debug> { Box::new(x) }
+   |               ----                               ^ ...is captured here, requiring it to live as long as `'static`
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+help: to declare that the trait object captures data from argument `x`, you can add an explicit `'_` lifetime bound
+   |
+LL | fn elided3(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
+   |                                      ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:21:59
+   |
+LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug> { Box::new(x) }
+   |                     -------                               ^ ...is captured here, requiring it to live as long as `'static`
+   |                     |
+   |                     this data with lifetime `'a`...
+   |
+help: to declare that the trait object captures data from argument `x`, you can add an explicit `'a` lifetime bound
+   |
+LL | fn explicit3<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
+   |                                               ^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:24:60
+   |
+LL | fn elided4(x: &i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |               ----                                         ^ ...is captured here, requiring it to live as long as `'static`
+   |               |
+   |               this data with an anonymous lifetime `'_`...
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn elided4(x: &i32) -> Box<dyn Debug + '_> { Box::new(x) }
+   |                                        ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn elided4(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |               ^^^^^^^^^^^^
+
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/must_outlive_least_region_or_bound.rs:27:69
+   |
+LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |                     ------- this data with lifetime `'a`...         ^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn explicit4<'a>(x: &'a i32) -> Box<dyn Debug + 'a> { Box::new(x) }
+   |                                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn explicit4<'a>(x: &'static i32) -> Box<dyn Debug + 'static> { Box::new(x) }
+   |                     ^^^^^^^^^^^^
+
+error: aborting due to 12 previous errors
 
-Some errors have detailed explanations: E0310, E0623.
+Some errors have detailed explanations: E0310, E0621, E0623, E0759.
 For more information about an error, try `rustc --explain E0310`.
diff --git a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
index 1c3a5979ee55b..df0db6e4fc6df 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -1,36 +1,43 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:7:16
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                         -----     ----------------------- ...is required to be `'static` by this...
-   |                         |
-   |                         data with this lifetime...
+   |                         ----- this data with an anonymous lifetime `'_`...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...and is captured here
+   |         ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+note: ...and is required to live as long as `'static` here
+  --> $DIR/static-return-lifetime-infered.rs:6:35
+   |
+LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
+   |                                   ^^^^^^^^^^^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
    |                                                           ^^^^
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:11:16
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                        --------     ----------------------- ...is required to be `'static` by this...
-   |                        |
-   |                        data with this lifetime...
+   |                        -------- this data with lifetime `'a`...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...and is captured here
+   |         ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the lifetime `'a` as defined on the method body at 10:20
+note: ...and is required to live as long as `'static` here
+  --> $DIR/static-return-lifetime-infered.rs:10:37
+   |
+LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
+   |                                     ^^^^^^^^^^^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'a` lifetime bound
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
    |                                                             ^^^^
 
 error: aborting due to 2 previous errors
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/infinite/infinite-tag-type-recursion.stderr b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
index 11f82b842ba6f..6d1df4fda2eb0 100644
--- a/src/test/ui/infinite/infinite-tag-type-recursion.stderr
+++ b/src/test/ui/infinite/infinite-tag-type-recursion.stderr
@@ -6,7 +6,10 @@ LL | enum MList { Cons(isize, MList), Nil }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `MList` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `MList` representable
+   |
+LL | enum MList { Cons(isize, Box<MList>), Nil }
+   |                          ^^^^     ^
 
 error[E0391]: cycle detected when computing drop-check constraints for `MList`
   --> $DIR/infinite-tag-type-recursion.rs:1:1
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 02d33aae023ff..919594fc9af4b 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -1,18 +1,16 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/issue-16922.rs:4:14
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
-   |                       -- data with this lifetime...
+   |                       -- this data with an anonymous lifetime `'_`...
 LL |     Box::new(value) as Box<dyn Any>
-   |     ---------^^^^^-
-   |     |        |
-   |     |        ...and is captured here
-   |     ...is required to be `'static` by this...
+   |              ^^^^^ ...is captured here, requiring it to live as long as `'static`
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 3:1
+help: to declare that the trait object captures data from argument `value`, you can add an explicit `'_` lifetime bound
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any + '_> {
    |                                          ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/issues/issue-17431-1.stderr b/src/test/ui/issues/issue-17431-1.stderr
index eb5a1366e8953..58d087ca1998b 100644
--- a/src/test/ui/issues/issue-17431-1.stderr
+++ b/src/test/ui/issues/issue-17431-1.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-1.rs:1:1
    |
 LL | struct Foo { foo: Option<Option<Foo>> }
-   | ^^^^^^^^^^   ------------------------ recursive without indirection
+   | ^^^^^^^^^^        ------------------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { foo: Box<Option<Option<Foo>>> }
+   |                   ^^^^                   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-2.stderr b/src/test/ui/issues/issue-17431-2.stderr
index 3a7b0e9ce7997..eba4bf6d1d5ea 100644
--- a/src/test/ui/issues/issue-17431-2.stderr
+++ b/src/test/ui/issues/issue-17431-2.stderr
@@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
   --> $DIR/issue-17431-2.rs:1:1
    |
 LL | struct Baz { q: Option<Foo> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
+   |
+LL | struct Baz { q: Box<Option<Foo>> }
+   |                 ^^^^           ^
 
 error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-2.rs:4:1
    |
 LL | struct Foo { q: Option<Baz> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { q: Box<Option<Baz>> }
+   |                 ^^^^           ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-17431-3.stderr b/src/test/ui/issues/issue-17431-3.stderr
index 675a2e2714209..f6b15d0528ae8 100644
--- a/src/test/ui/issues/issue-17431-3.stderr
+++ b/src/test/ui/issues/issue-17431-3.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-3.rs:3:1
    |
 LL | struct Foo { foo: Mutex<Option<Foo>> }
-   | ^^^^^^^^^^   ----------------------- recursive without indirection
+   | ^^^^^^^^^^        ------------------ recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { foo: Box<Mutex<Option<Foo>>> }
+   |                   ^^^^                  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-4.stderr b/src/test/ui/issues/issue-17431-4.stderr
index aff9071095ca0..aa709e1ad5183 100644
--- a/src/test/ui/issues/issue-17431-4.stderr
+++ b/src/test/ui/issues/issue-17431-4.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/issue-17431-4.rs:3:1
    |
 LL | struct Foo<T> { foo: Option<Option<Foo<T>>>, marker: marker::PhantomData<T> }
-   | ^^^^^^^^^^^^^   --------------------------- recursive without indirection
+   | ^^^^^^^^^^^^^        ---------------------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo<T> { foo: Box<Option<Option<Foo<T>>>>, marker: marker::PhantomData<T> }
+   |                      ^^^^                      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-5.stderr b/src/test/ui/issues/issue-17431-5.stderr
index 537f9f34f55ca..1558cffb036b3 100644
--- a/src/test/ui/issues/issue-17431-5.stderr
+++ b/src/test/ui/issues/issue-17431-5.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/issue-17431-5.rs:5:1
    |
 LL | struct Bar<T> { x: Bar<Foo> , marker: marker::PhantomData<T> }
-   | ^^^^^^^^^^^^^   ----------- recursive without indirection
+   | ^^^^^^^^^^^^^      -------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL | struct Bar<T> { x: Box<Bar<Foo>> , marker: marker::PhantomData<T> }
+   |                    ^^^^        ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-6.stderr b/src/test/ui/issues/issue-17431-6.stderr
index cb2dab9501488..f2aa2a79c8200 100644
--- a/src/test/ui/issues/issue-17431-6.stderr
+++ b/src/test/ui/issues/issue-17431-6.stderr
@@ -6,7 +6,10 @@ LL | enum Foo { X(Mutex<Option<Foo>>) }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | enum Foo { X(Box<Mutex<Option<Foo>>>) }
+   |              ^^^^                  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-17431-7.stderr b/src/test/ui/issues/issue-17431-7.stderr
index de70851da4b5f..684c3089e85ec 100644
--- a/src/test/ui/issues/issue-17431-7.stderr
+++ b/src/test/ui/issues/issue-17431-7.stderr
@@ -6,7 +6,10 @@ LL | enum Foo { Voo(Option<Option<Foo>>) }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | enum Foo { Voo(Box<Option<Option<Foo>>>) }
+   |                ^^^^                   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-2718-a.stderr b/src/test/ui/issues/issue-2718-a.stderr
index 0f52c79192843..d152ffde4e57d 100644
--- a/src/test/ui/issues/issue-2718-a.stderr
+++ b/src/test/ui/issues/issue-2718-a.stderr
@@ -7,7 +7,10 @@ LL |     pub struct Pong(SendPacket<Ping>);
    |     |               recursive without indirection
    |     recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `pingpong::Pong` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `pingpong::Pong` representable
+   |
+LL |     pub struct Pong(Box<SendPacket<Ping>>);
+   |                     ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-1.stderr b/src/test/ui/issues/issue-3008-1.stderr
index f12274134ee05..87ee36df21696 100644
--- a/src/test/ui/issues/issue-3008-1.stderr
+++ b/src/test/ui/issues/issue-3008-1.stderr
@@ -7,7 +7,10 @@ LL | enum Bar {
 LL |     BarSome(Bar)
    |             --- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL |     BarSome(Box<Bar>)
+   |             ^^^^   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-2.stderr b/src/test/ui/issues/issue-3008-2.stderr
index acc15f4b57c73..369a19d37e6f6 100644
--- a/src/test/ui/issues/issue-3008-2.stderr
+++ b/src/test/ui/issues/issue-3008-2.stderr
@@ -2,11 +2,14 @@ error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/issue-3008-2.rs:2:1
    |
 LL | struct Bar { x: Bar }
-   | ^^^^^^^^^^   ------ recursive without indirection
+   | ^^^^^^^^^^      --- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
+   |
+LL | struct Bar { x: Box<Bar> }
+   |                 ^^^^   ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3008-3.stderr b/src/test/ui/issues/issue-3008-3.stderr
index d08a3d9708db3..0b162eff94a7c 100644
--- a/src/test/ui/issues/issue-3008-3.stderr
+++ b/src/test/ui/issues/issue-3008-3.stderr
@@ -6,7 +6,10 @@ LL | enum E2<T> { V2(E2<E1>, marker::PhantomData<T>), }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `E2` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `E2` representable
+   |
+LL | enum E2<T> { V2(Box<E2<E1>>, marker::PhantomData<T>), }
+   |                 ^^^^      ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-32326.stderr b/src/test/ui/issues/issue-32326.stderr
index 5967627e51a4b..0f3d3690b732e 100644
--- a/src/test/ui/issues/issue-32326.stderr
+++ b/src/test/ui/issues/issue-32326.stderr
@@ -8,7 +8,10 @@ LL |     Plus(Expr, Expr),
    |          |
    |          recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Expr` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Expr` representable
+   |
+LL |     Plus(Box<Expr>, Box<Expr>),
+   |          ^^^^    ^  ^^^^    ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-3779.stderr b/src/test/ui/issues/issue-3779.stderr
index ba1e842c610ba..7b17e91421660 100644
--- a/src/test/ui/issues/issue-3779.stderr
+++ b/src/test/ui/issues/issue-3779.stderr
@@ -5,9 +5,12 @@ LL | struct S {
    | ^^^^^^^^ recursive type has infinite size
 LL |
 LL |     element: Option<S>
-   |     ------------------ recursive without indirection
+   |              --------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `S` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `S` representable
+   |
+LL |     element: Box<Option<S>>
+   |              ^^^^         ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-57271.stderr b/src/test/ui/issues/issue-57271.stderr
index 4f164624f7a53..b7c799e163cee 100644
--- a/src/test/ui/issues/issue-57271.stderr
+++ b/src/test/ui/issues/issue-57271.stderr
@@ -7,7 +7,10 @@ LL |     Class(ClassTypeSignature),
 LL |     Array(TypeSignature),
    |           ------------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ObjectType` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ObjectType` representable
+   |
+LL |     Array(Box<TypeSignature>),
+   |           ^^^^             ^
 
 error[E0072]: recursive type `TypeSignature` has infinite size
   --> $DIR/issue-57271.rs:19:1
@@ -18,7 +21,10 @@ LL |     Base(BaseType),
 LL |     Object(ObjectType),
    |            ---------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `TypeSignature` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `TypeSignature` representable
+   |
+LL |     Object(Box<ObjectType>),
+   |            ^^^^          ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-72554.stderr b/src/test/ui/issues/issue-72554.stderr
index 9db65f4a2ee8f..9de94c393a711 100644
--- a/src/test/ui/issues/issue-72554.stderr
+++ b/src/test/ui/issues/issue-72554.stderr
@@ -6,7 +6,10 @@ LL | pub enum ElemDerived {
 LL |     A(ElemDerived)
    |       ----------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ElemDerived` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ElemDerived` representable
+   |
+LL |     A(Box<ElemDerived>)
+   |       ^^^^           ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
index 70a9bf22b8db3..1b1e0d9610724 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr
@@ -1,13 +1,13 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
-   |             --------------- data with this lifetime...
+   |             --------------- this data with an anonymous lifetime `'_`...
 ...
 LL |     ss.r
-   |     ^^^^ ...is captured and required to be `'static` here
+   |     ^^^^ ...is captured and required to live as long as `'static` here
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #2 defined on the function body at 14:1
+help: to declare that the trait object captures data from argument `ss`, you can add an explicit `'_` lifetime bound
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {
    |                                                   ^^^^
@@ -23,4 +23,5 @@ LL |     ss.r = b;
 
 error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0621`.
+Some errors have detailed explanations: E0621, E0759.
+For more information about an error, try `rustc --explain E0621`.
diff --git a/src/test/ui/recursion/recursive-enum.stderr b/src/test/ui/recursion/recursive-enum.stderr
index e4674b57a6d21..ab4709d8e709e 100644
--- a/src/test/ui/recursion/recursive-enum.stderr
+++ b/src/test/ui/recursion/recursive-enum.stderr
@@ -6,7 +6,10 @@ LL | enum List<T> { Cons(T, List<T>), Nil }
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `List` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `List` representable
+   |
+LL | enum List<T> { Cons(T, Box<List<T>>), Nil }
+   |                        ^^^^       ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
index bf02ba8eb9199..7e8f78067e08a 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr
@@ -1,21 +1,21 @@
-error[E0621]: explicit lifetime required in the type of `v`
+error: lifetime may not live long enough
   --> $DIR/region-object-lifetime-in-coercion.rs:8:12
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         - let's call the lifetime of this reference `'1`
 LL |     let x: Box<dyn Foo + 'static> = Box::new(v);
-   |            ^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+   |            ^^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'1` must outlive `'static`
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error: lifetime may not live long enough
+  --> $DIR/region-object-lifetime-in-coercion.rs:13:5
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         - let's call the lifetime of this reference `'1`
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^ lifetime `'static` required
+   |     ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/region-object-lifetime-in-coercion.rs:20:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:19:5
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
    |         - let's call the lifetime of this reference `'1`
@@ -24,7 +24,7 @@ LL |     Box::new(v)
    |     ^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:5
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      -- -- lifetime `'b` defined here
@@ -37,4 +37,3 @@ LL |     Box::new(v)
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0621`.
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.rs b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
index d56eaf77b6646..5d199149c39b8 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -5,13 +5,12 @@ trait Foo {}
 impl<'a> Foo for &'a [u8] {}
 
 fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-    let x: Box<dyn Foo + 'static> = Box::new(v);
-    //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+    let x: Box<dyn Foo + 'static> = Box::new(v); //~ ERROR cannot infer an appropriate lifetime
     x
 }
 
 fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-    Box::new(v) //~ ERROR explicit lifetime required in the type of `v` [E0621]
+    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn c(v: &[u8]) -> Box<dyn Foo> {
diff --git a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
index 1462af44cb15a..7f5a3a47976c7 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -1,61 +1,76 @@
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:8:37
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:8:46
    |
 LL | fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         ----- this data with an anonymous lifetime `'_`...
 LL |     let x: Box<dyn Foo + 'static> = Box::new(v);
-   |                                     ^^^^^^^^^^^ lifetime `'static` required
+   |                                              ^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+   |
+LL | fn a(v: &[u8]) -> Box<dyn Foo + '_> {
+   |                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn a(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+   |         ^^^^^^^^^^^^^
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:14:5
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:13:14
    |
 LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         ----- this data with an anonymous lifetime `'_`...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^ lifetime `'static` required
+   |              ^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
+   |
+LL | fn b(v: &[u8]) -> Box<dyn Foo + '_> {
+   |                                 ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn b(v: &'static [u8]) -> Box<dyn Foo + 'static> {
+   |         ^^^^^^^^^^^^^
 
-error: cannot infer an appropriate lifetime
-  --> $DIR/region-object-lifetime-in-coercion.rs:20:14
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:19:14
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
-   |         ----- data with this lifetime...
+   |         ----- this data with an anonymous lifetime `'_`...
 ...
 LL |     Box::new(v)
-   |     ---------^-
-   |     |        |
-   |     |        ...and is captured here
-   |     ...is required to be `'static` by this...
+   |              ^ ...is captured here, requiring it to live as long as `'static`
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 17:1
+help: to declare that the trait object captures data from argument `v`, you can add an explicit `'_` lifetime bound
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo + '_> {
    |                               ^^^^
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:14
    |
 LL |     Box::new(v)
    |              ^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 23:6...
-  --> $DIR/region-object-lifetime-in-coercion.rs:23:6
+note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 22:6...
+  --> $DIR/region-object-lifetime-in-coercion.rs:22:6
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      ^^
 note: ...so that the expression is assignable
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:14
    |
 LL |     Box::new(v)
    |              ^
    = note: expected `&[u8]`
               found `&'a [u8]`
-note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 23:9...
-  --> $DIR/region-object-lifetime-in-coercion.rs:23:9
+note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 22:9...
+  --> $DIR/region-object-lifetime-in-coercion.rs:22:9
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |         ^^
 note: ...so that the expression is assignable
-  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:23:5
    |
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
@@ -64,5 +79,5 @@ LL |     Box::new(v)
 
 error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0495, E0621.
+Some errors have detailed explanations: E0495, E0759.
 For more information about an error, try `rustc --explain E0495`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-2.stderr b/src/test/ui/regions/regions-close-object-into-object-2.stderr
index 147f7f3541816..114e4052aae09 100644
--- a/src/test/ui/regions/regions-close-object-into-object-2.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-2.stderr
@@ -1,28 +1,20 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/regions-close-object-into-object-2.rs:10:11
    |
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
+   |                         ------------------ this data with lifetime `'a`...
 LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
-  --> $DIR/regions-close-object-into-object-2.rs:9:6
+   |           ^^^ ...is captured here, requiring it to live as long as `'static`
    |
-LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'static> {
-   |      ^^
-note: ...so that the type `(dyn A<T> + 'a)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-2.rs:10:11
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
-LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/regions-close-object-into-object-2.rs:10:5
+LL | fn g<'a, T: 'static>(v: Box<dyn A<T> + 'a>) -> Box<dyn X + 'a> {
+   |                                                            ^^
+help: alternatively, add an explicit `'static` bound to this reference
    |
-LL |     box B(&*v) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `std::boxed::Box<(dyn X + 'static)>`
-              found `std::boxed::Box<dyn X>`
+LL | fn g<'a, T: 'static>(v: std::boxed::Box<(dyn A<T> + 'static)>) -> Box<dyn X + 'static> {
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/regions/regions-close-object-into-object-4.stderr b/src/test/ui/regions/regions-close-object-into-object-4.stderr
index 6e7d6152cd09a..850d81940791f 100644
--- a/src/test/ui/regions/regions-close-object-into-object-4.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-4.stderr
@@ -1,28 +1,20 @@
-error[E0495]: cannot infer an appropriate lifetime for borrow expression due to conflicting requirements
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/regions-close-object-into-object-4.rs:10:11
    |
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
+   |                   ---------------- this data with lifetime `'a`...
 LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 9:6...
-  --> $DIR/regions-close-object-into-object-4.rs:9:6
+   |           ^^^ ...is captured here, requiring it to live as long as `'static`
    |
-LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'static> {
-   |      ^^
-note: ...so that the type `(dyn A<U> + 'a)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-4.rs:10:11
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `v`
    |
-LL |     box B(&*v) as Box<dyn X>
-   |           ^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/regions-close-object-into-object-4.rs:10:5
+LL | fn i<'a, T, U>(v: Box<dyn A<U>+'a>) -> Box<dyn X + 'a> {
+   |                                                    ^^
+help: alternatively, add an explicit `'static` bound to this reference
    |
-LL |     box B(&*v) as Box<dyn X>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected `std::boxed::Box<(dyn X + 'static)>`
-              found `std::boxed::Box<dyn X>`
+LL | fn i<'a, T, U>(v: std::boxed::Box<(dyn A<U> + 'static)>) -> Box<dyn X + 'static> {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0495`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/regions/regions-proc-bound-capture.nll.stderr b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
new file mode 100644
index 0000000000000..75890b8581537
--- /dev/null
+++ b/src/test/ui/regions/regions-proc-bound-capture.nll.stderr
@@ -0,0 +1,11 @@
+error: lifetime may not live long enough
+  --> $DIR/regions-proc-bound-capture.rs:9:5
+   |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                   - let's call the lifetime of this reference `'1`
+LL |     // This is illegal, because the region bound on `proc` is 'static.
+LL |     Box::new(move || { *x })
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/regions/regions-proc-bound-capture.rs b/src/test/ui/regions/regions-proc-bound-capture.rs
index 0c903b7384992..8617c0e9da8f7 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.rs
+++ b/src/test/ui/regions/regions-proc-bound-capture.rs
@@ -4,9 +4,9 @@ fn borrowed_proc<'a>(x: &'a isize) -> Box<dyn FnMut()->(isize) + 'a> {
     Box::new(move|| { *x })
 }
 
-fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
+fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
     // This is illegal, because the region bound on `proc` is 'static.
-    Box::new(move|| { *x }) //~ ERROR explicit lifetime required in the type of `x` [E0621]
+    Box::new(move || { *x }) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() { }
diff --git a/src/test/ui/regions/regions-proc-bound-capture.stderr b/src/test/ui/regions/regions-proc-bound-capture.stderr
index c53af34456ef3..67eee3bb6e281 100644
--- a/src/test/ui/regions/regions-proc-bound-capture.stderr
+++ b/src/test/ui/regions/regions-proc-bound-capture.stderr
@@ -1,12 +1,21 @@
-error[E0621]: explicit lifetime required in the type of `x`
-  --> $DIR/regions-proc-bound-capture.rs:9:5
+error[E0759]: cannot infer an appropriate lifetime
+  --> $DIR/regions-proc-bound-capture.rs:9:14
    |
-LL | fn static_proc(x: &isize) -> Box<dyn FnMut()->(isize) + 'static> {
-   |                   ------ help: add explicit lifetime `'static` to the type of `x`: `&'static isize`
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                   ------ this data with an anonymous lifetime `'_`...
 LL |     // This is illegal, because the region bound on `proc` is 'static.
-LL |     Box::new(move|| { *x })
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'static` required
+LL |     Box::new(move || { *x })
+   |              ^^^^^^^^^^^^^^ ...is captured here, requiring it to live as long as `'static`
+   |
+help: consider changing the trait object's explicit `'static` bound to the lifetime of argument `x`
+   |
+LL | fn static_proc(x: &isize) -> Box<dyn FnMut() -> (isize) + '_> {
+   |                                                           ^^
+help: alternatively, add an explicit `'static` bound to this reference
+   |
+LL | fn static_proc(x: &'static isize) -> Box<dyn FnMut() -> (isize) + 'static> {
+   |                   ^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0621`.
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
index 1aeabce5e8aaf..88bd990b1e81b 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr
@@ -1,11 +1,12 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:16
    |
 LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                ^^^^  ----------     ---------- ...and required to be `'static` by this
+   |                ^^^^  ----------     ---------- ...and is required to live as long as `'static` here
    |                |     |
-   |                |     data with this lifetime...
+   |                |     this data with an anonymous lifetime `'_`...
    |                ...is captured here...
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
index 04c475be787b8..2e10ab3d3f9b8 100644
--- a/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
+++ b/src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr
@@ -1,16 +1,21 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:44
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                ----------     ----------   ^^^^ ...and is captured here
-   |                |              |
-   |                |              ...is required to be `'static` by this...
-   |                data with this lifetime...
+   |                ----------                  ^^^^ ...is captured here...
+   |                |
+   |                this data with an anonymous lifetime `'_`...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the method body at 6:5
+note: ...and is required to live as long as `'static` here
+  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:31
+   |
+LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
+   |                               ^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `self`, you can add an explicit `'_` lifetime bound
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
    |                                          ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/sized-cycle-note.stderr b/src/test/ui/sized-cycle-note.stderr
index 95bdc34942645..45062c2ea6c72 100644
--- a/src/test/ui/sized-cycle-note.stderr
+++ b/src/test/ui/sized-cycle-note.stderr
@@ -2,21 +2,27 @@ error[E0072]: recursive type `Baz` has infinite size
   --> $DIR/sized-cycle-note.rs:9:1
    |
 LL | struct Baz { q: Option<Foo> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Baz` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Baz` representable
+   |
+LL | struct Baz { q: Box<Option<Foo>> }
+   |                 ^^^^           ^
 
 error[E0072]: recursive type `Foo` has infinite size
   --> $DIR/sized-cycle-note.rs:11:1
    |
 LL | struct Foo { q: Option<Baz> }
-   | ^^^^^^^^^^   -------------- recursive without indirection
+   | ^^^^^^^^^^      ----------- recursive without indirection
    | |
    | recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL | struct Foo { q: Box<Option<Baz>> }
+   |                 ^^^^           ^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/span/E0072.stderr b/src/test/ui/span/E0072.stderr
index d4a5e7400d2a4..06493f05142e6 100644
--- a/src/test/ui/span/E0072.stderr
+++ b/src/test/ui/span/E0072.stderr
@@ -5,9 +5,12 @@ LL | struct ListNode {
    | ^^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     head: u8,
 LL |     tail: Option<ListNode>,
-   |     ---------------------- recursive without indirection
+   |           ---------------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+   |
+LL |     tail: Box<Option<ListNode>>,
+   |           ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/multiline-span-E0072.stderr b/src/test/ui/span/multiline-span-E0072.stderr
index dd322fe833b49..55128347f7404 100644
--- a/src/test/ui/span/multiline-span-E0072.stderr
+++ b/src/test/ui/span/multiline-span-E0072.stderr
@@ -6,11 +6,14 @@ LL | | ListNode
 LL | | {
 LL | |     head: u8,
 LL | |     tail: Option<ListNode>,
-   | |     ---------------------- recursive without indirection
+   | |           ---------------- recursive without indirection
 LL | | }
    | |_^ recursive type has infinite size
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `ListNode` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `ListNode` representable
+   |
+LL |     tail: Box<Option<ListNode>>,
+   |           ^^^^                ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/span/recursive-type-field.stderr b/src/test/ui/span/recursive-type-field.stderr
index d240872647e50..fb1d98b58dfbe 100644
--- a/src/test/ui/span/recursive-type-field.stderr
+++ b/src/test/ui/span/recursive-type-field.stderr
@@ -4,9 +4,12 @@ error[E0072]: recursive type `Foo` has infinite size
 LL | struct Foo<'a> {
    | ^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     bar: Bar<'a>,
-   |     ------------ recursive without indirection
+   |          ------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Foo` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Foo` representable
+   |
+LL |     bar: Box<Bar<'a>>,
+   |          ^^^^       ^
 
 error[E0072]: recursive type `Bar` has infinite size
   --> $DIR/recursive-type-field.rs:8:1
@@ -14,18 +17,18 @@ error[E0072]: recursive type `Bar` has infinite size
 LL | struct Bar<'a> {
    | ^^^^^^^^^^^^^^ recursive type has infinite size
 LL |     y: (Foo<'a>, Foo<'a>),
-   |     --------------------- recursive without indirection
+   |        ------------------ recursive without indirection
 LL |     z: Option<Bar<'a>>,
-   |     ------------------ recursive without indirection
+   |        --------------- recursive without indirection
 ...
 LL |     d: [Bar<'a>; 1],
-   |     --------------- recursive without indirection
+   |        ------------ recursive without indirection
 LL |     e: Foo<'a>,
-   |     ---------- recursive without indirection
+   |        ------- recursive without indirection
 LL |     x: Bar<'a>,
-   |     ---------- recursive without indirection
+   |        ------- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `Bar` representable
+   = help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `Bar` representable
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
index 5cf170d566ca9..9ab060328537b 100644
--- a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -6,20 +6,23 @@ LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |        |
    |        help: consider introducing lifetime `'a` here: `'a,`
 
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/missing-lifetimes-in-signature.rs:19:5
    |
 LL |   fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
-   |                            ------     ------------- ...is required to be `'static` by this...
-   |                            |
-   |                            data with this lifetime...
+   |                            ------ this data with an anonymous lifetime `'_`...
 ...
 LL | /     move || {
 LL | |         *dest = g.get();
 LL | |     }
-   | |_____^ ...and is captured here
+   | |_____^ ...is captured here...
    |
-help: to permit non-static references in an `impl Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 15:1
+note: ...and is required to live as long as `'static` here
+  --> $DIR/missing-lifetimes-in-signature.rs:15:37
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+   |                                     ^^^^^^^^^^^^^
+help: to declare that the `impl Trait` captures data from argument `dest`, you can add an explicit `'_` lifetime bound
    |
 LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
    |                                                   ^^^^
@@ -122,5 +125,5 @@ LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
 
 error: aborting due to 7 previous errors
 
-Some errors have detailed explanations: E0261, E0309, E0621.
+Some errors have detailed explanations: E0261, E0309, E0621, E0759.
 For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/type/type-recursive.stderr b/src/test/ui/type/type-recursive.stderr
index 72bf372e561d6..d6d32cc5d6f39 100644
--- a/src/test/ui/type/type-recursive.stderr
+++ b/src/test/ui/type/type-recursive.stderr
@@ -5,9 +5,12 @@ LL | struct T1 {
    | ^^^^^^^^^ recursive type has infinite size
 LL |     foo: isize,
 LL |     foolish: T1
-   |     ----------- recursive without indirection
+   |              -- recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `T1` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `T1` representable
+   |
+LL |     foolish: Box<T1>
+   |              ^^^^  ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index 3577dd59289e5..dda5de431d309 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,16 +1,17 @@
-error: cannot infer an appropriate lifetime
+error[E0759]: cannot infer an appropriate lifetime
   --> $DIR/dyn-trait-underscore.rs:8:20
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
-   |                ---- data with this lifetime...
+   |                ---- this data with an anonymous lifetime `'_`...
 LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter())
-   |     ---------------^^^^--- ...is captured and required to be `'static` here
+   |     ---------------^^^^--- ...is captured and required to live as long as `'static` here
    |
-help: to permit non-static references in a `dyn Trait` value, you can add an explicit bound for the anonymous lifetime #1 defined on the function body at 6:1
+help: to declare that the trait object captures data from argument `items`, you can add an explicit `'_` lifetime bound
    |
 LL | fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T> + '_> {
    |                                                   ^^^^
 
 error: aborting due to previous error
 
+For more information about this error, try `rustc --explain E0759`.
diff --git a/src/test/ui/union/union-nonrepresentable.stderr b/src/test/ui/union/union-nonrepresentable.stderr
index 746c1033ea348..c54d04de12c50 100644
--- a/src/test/ui/union/union-nonrepresentable.stderr
+++ b/src/test/ui/union/union-nonrepresentable.stderr
@@ -5,9 +5,12 @@ LL | union U {
    | ^^^^^^^ recursive type has infinite size
 LL |     a: u8,
 LL |     b: U,
-   |     ---- recursive without indirection
+   |        - recursive without indirection
    |
-   = help: insert indirection (e.g., a `Box`, `Rc`, or `&`) at some point to make `U` representable
+help: insert some indirection (e.g., a `Box`, `Rc`, or `&`) to make `U` representable
+   |
+LL |     b: Box<U>,
+   |        ^^^^ ^
 
 error: aborting due to previous error
 
diff --git a/src/tools/clippy/clippy_lints/src/checked_conversions.rs b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
index e845ef99c7cc0..88145015ba8bd 100644
--- a/src/tools/clippy/clippy_lints/src/checked_conversions.rs
+++ b/src/tools/clippy/clippy_lints/src/checked_conversions.rs
@@ -88,7 +88,7 @@ fn double_check<'a>(cx: &LateContext<'_, '_>, left: &'a Expr<'_>, right: &'a Exp
         let upper = check_upper_bound(l);
         let lower = check_lower_bound(r);
 
-        transpose(upper, lower).and_then(|(l, r)| l.combine(r, cx))
+        upper.zip(lower).and_then(|(l, r)| l.combine(r, cx))
     };
 
     upper_lower(left, right).or_else(|| upper_lower(right, left))
@@ -131,7 +131,10 @@ impl<'a> Conversion<'a> {
 
     /// Checks if the to-type is the same (if there is a type constraint)
     fn has_compatible_to_type(&self, other: &Self) -> bool {
-        transpose(self.to_type.as_ref(), other.to_type.as_ref()).map_or(true, |(l, r)| l == r)
+        match (self.to_type, other.to_type) {
+            (Some(l), Some(r)) => l == r,
+            _ => true,
+        }
     }
 
     /// Try to construct a new conversion if the conversion type is valid
@@ -322,14 +325,6 @@ fn int_ty_to_sym<'tcx>(path: &QPath<'_>) -> Option<&'tcx str> {
     }
 }
 
-/// (Option<T>, Option<U>) -> Option<(T, U)>
-fn transpose<T, U>(lhs: Option<T>, rhs: Option<U>) -> Option<(T, U)> {
-    match (lhs, rhs) {
-        (Some(l), Some(r)) => Some((l, r)),
-        _ => None,
-    }
-}
-
 /// Will return the expressions as if they were expr1 <= expr2
 fn normalize_le_ge<'a>(op: &BinOp, left: &'a Expr<'a>, right: &'a Expr<'a>) -> Option<(&'a Expr<'a>, &'a Expr<'a>)> {
     match op.node {