about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock1
-rw-r--r--RELEASES.md160
-rw-r--r--src/doc/unstable-book/src/library-features/asm.md11
-rw-r--r--src/liballoc/boxed.rs27
-rw-r--r--src/liballoc/collections/binary_heap.rs20
-rw-r--r--src/liballoc/collections/btree/map.rs10
-rw-r--r--src/liballoc/collections/btree/set.rs10
-rw-r--r--src/liballoc/collections/linked_list.rs10
-rw-r--r--src/liballoc/collections/vec_deque.rs20
-rw-r--r--src/liballoc/lib.rs1
-rw-r--r--src/liballoc/raw_vec.rs2
-rw-r--r--src/liballoc/string.rs35
-rw-r--r--src/liballoc/tests/boxed.rs33
-rw-r--r--src/liballoc/vec.rs20
-rw-r--r--src/libcore/intrinsics.rs2
-rw-r--r--src/libcore/iter/adapters/mod.rs63
-rw-r--r--src/libcore/iter/range.rs84
-rw-r--r--src/libcore/iter/traits/collect.rs17
-rw-r--r--src/libcore/iter/traits/iterator.rs14
-rw-r--r--src/libcore/lib.rs1
-rw-r--r--src/libcore/num/f32.rs74
-rw-r--r--src/libcore/num/f64.rs74
-rw-r--r--src/libcore/ops/range.rs14
-rw-r--r--src/libcore/ptr/const_ptr.rs18
-rw-r--r--src/libcore/ptr/mut_ptr.rs18
-rw-r--r--src/libcore/tests/iter.rs36
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/librustc_ast/token.rs56
-rw-r--r--src/librustc_ast/tokenstream.rs125
-rw-r--r--src/librustc_ast_lowering/expr.rs70
-rw-r--r--src/librustc_ast_lowering/item.rs11
-rw-r--r--src/librustc_ast_lowering/pat.rs33
-rw-r--r--src/librustc_codegen_llvm/asm.rs8
-rw-r--r--src/librustc_codegen_ssa/back/link.rs29
-rw-r--r--src/librustc_codegen_ssa/back/linker.rs227
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs3
-rw-r--r--src/librustc_data_structures/lib.rs1
-rw-r--r--src/librustc_data_structures/thin_vec.rs14
-rw-r--r--src/librustc_error_codes/error_codes/E0055.md2
-rw-r--r--src/librustc_error_codes/error_codes/E0619.md1
-rw-r--r--src/librustc_errors/diagnostic.rs15
-rw-r--r--src/librustc_expand/base.rs4
-rw-r--r--src/librustc_expand/expand.rs7
-rw-r--r--src/librustc_feature/active.rs3
-rw-r--r--src/librustc_hir/definitions.rs11
-rw-r--r--src/librustc_index/lib.rs1
-rw-r--r--src/librustc_index/vec.rs10
-rw-r--r--src/librustc_infer/infer/error_reporting/mod.rs174
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs6
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs2
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs37
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/static_impl_trait.rs83
-rw-r--r--src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs107
-rw-r--r--src/librustc_infer/infer/error_reporting/note.rs59
-rw-r--r--src/librustc_infer/lib.rs1
-rw-r--r--src/librustc_infer/traits/util.rs8
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_lint/levels.rs21
-rw-r--r--src/librustc_middle/middle/limits.rs8
-rw-r--r--src/librustc_middle/mir/interpret/error.rs4
-rw-r--r--src/librustc_middle/mir/interpret/mod.rs9
-rw-r--r--src/librustc_middle/mir/interpret/pointer.rs26
-rw-r--r--src/librustc_middle/mir/mod.rs5
-rw-r--r--src/librustc_middle/mir/query.rs14
-rw-r--r--src/librustc_middle/mir/tcx.rs13
-rw-r--r--src/librustc_middle/query/mod.rs10
-rw-r--r--src/librustc_middle/ty/context.rs114
-rw-r--r--src/librustc_middle/ty/diagnostics.rs19
-rw-r--r--src/librustc_middle/ty/layout.rs3
-rw-r--r--src/librustc_middle/ty/mod.rs5
-rw-r--r--src/librustc_middle/ty/sty.rs17
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs89
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/move_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_errors.rs2
-rw-r--r--src/librustc_mir/borrow_check/diagnostics/region_name.rs9
-rw-r--r--src/librustc_mir/borrow_check/mod.rs16
-rw-r--r--src/librustc_mir/borrow_check/nll.rs6
-rw-r--r--src/librustc_mir/const_eval/machine.rs5
-rw-r--r--src/librustc_mir/interpret/eval_context.rs2
-rw-r--r--src/librustc_mir/interpret/intrinsics.rs67
-rw-r--r--src/librustc_mir/interpret/operand.rs163
-rw-r--r--src/librustc_mir/interpret/place.rs8
-rw-r--r--src/librustc_mir/interpret/step.rs3
-rw-r--r--src/librustc_mir/interpret/validity.rs2
-rw-r--r--src/librustc_mir/monomorphize/collector.rs15
-rw-r--r--src/librustc_mir/transform/check_unsafety.rs157
-rw-r--r--src/librustc_mir_build/build/block.rs12
-rw-r--r--src/librustc_mir_build/build/mod.rs4
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs2
-rw-r--r--src/librustc_parse/Cargo.toml1
-rw-r--r--src/librustc_parse/lib.rs212
-rw-r--r--src/librustc_parse/parser/item.rs21
-rw-r--r--src/librustc_passes/liveness.rs321
-rw-r--r--src/librustc_resolve/build_reduced_graph.rs20
-rw-r--r--src/librustc_resolve/late.rs3
-rw-r--r--src/librustc_resolve/lib.rs40
-rw-r--r--src/librustc_resolve/macros.rs8
-rw-r--r--src/librustc_session/lint/builtin.rs7
-rw-r--r--src/librustc_session/session.rs54
-rw-r--r--src/librustc_span/symbol.rs3
-rw-r--r--src/librustc_target/asm/mod.rs29
-rw-r--r--src/librustc_target/asm/nvptx.rs49
-rw-r--r--src/librustc_target/spec/mod.rs5
-rw-r--r--src/librustc_trait_selection/traits/project.rs9
-rw-r--r--src/librustc_trait_selection/traits/query/normalize.rs4
-rw-r--r--src/librustc_trait_selection/traits/select.rs13
-rw-r--r--src/librustc_traits/dropck_outlives.rs2
-rw-r--r--src/librustc_ty/needs_drop.rs5
-rw-r--r--src/librustc_typeck/astconv.rs310
-rw-r--r--src/librustc_typeck/check/autoderef.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs28
-rw-r--r--src/librustc_typeck/check/method/confirm.rs11
-rw-r--r--src/librustc_typeck/check/mod.rs28
-rw-r--r--src/librustc_typeck/check/op.rs8
-rw-r--r--src/librustc_typeck/check/upvar.rs8
-rw-r--r--src/librustc_typeck/check/writeback.rs4
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/libstd/collections/hash/map.rs28
-rw-r--r--src/libstd/collections/hash/set.rs20
-rw-r--r--src/libstd/f32.rs143
-rw-r--r--src/libstd/f64.rs143
-rw-r--r--src/libstd/lib.rs2
-rw-r--r--src/libstd/net/addr.rs68
-rw-r--r--src/libstd/net/ip.rs158
-rw-r--r--src/libstd/path.rs5
-rw-r--r--src/libstd/sys_common/wtf8.rs11
-rw-r--r--src/test/assembly/asm/nvptx-types.rs133
-rw-r--r--src/test/run-make-fulldeps/long-linker-command-lines/foo.rs2
-rw-r--r--src/test/ui/asm/issue-72570.rs10
-rw-r--r--src/test/ui/asm/issue-72570.stderr8
-rw-r--r--src/test/ui/asm/sym.rs38
-rw-r--r--src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr8
-rw-r--r--src/test/ui/ast-json/ast-json-noexpand-output.stdout2
-rw-r--r--src/test/ui/ast-json/ast-json-output.stdout2
-rw-r--r--src/test/ui/async-await/issue-72590-type-error-sized.rs22
-rw-r--r--src/test/ui/async-await/issue-72590-type-error-sized.stderr28
-rw-r--r--src/test/ui/async-await/issues/issue-62097.stderr13
-rw-r--r--src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr8
-rw-r--r--src/test/ui/closures/closure-immutable-outer-variable.fixed2
-rw-r--r--src/test/ui/closures/closure-immutable-outer-variable.rs2
-rw-r--r--src/test/ui/closures/closure-immutable-outer-variable.stderr4
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs4
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs2
-rw-r--r--src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr25
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.rs10
-rw-r--r--src/test/ui/consts/miri_unleashed/ptr_arith.stderr21
-rw-r--r--src/test/ui/consts/offset.rs115
-rw-r--r--src/test/ui/consts/offset_ub.rs25
-rw-r--r--src/test/ui/consts/offset_ub.stderr169
-rw-r--r--src/test/ui/did_you_mean/recursion_limit.stderr3
-rw-r--r--src/test/ui/did_you_mean/recursion_limit_deref.stderr2
-rw-r--r--src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr4
-rw-r--r--src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr4
-rw-r--r--src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr6
-rw-r--r--src/test/ui/error-codes/E0040.stderr5
-rw-r--r--src/test/ui/error-codes/E0055.rs2
-rw-r--r--src/test/ui/error-codes/E0055.stderr2
-rw-r--r--src/test/ui/error-codes/E0275.stderr3
-rw-r--r--src/test/ui/error-codes/E0490.stderr4
-rw-r--r--src/test/ui/explicit/explicit-call-to-dtor.stderr5
-rw-r--r--src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr5
-rw-r--r--src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr8
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs6
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr30
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr6
-rw-r--r--src/test/ui/illegal-ufcs-drop.stderr5
-rw-r--r--src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr8
-rw-r--r--src/test/ui/impl-trait/issue-56445.rs26
-rw-r--r--src/test/ui/impl-trait/issue-68532.rs13
-rw-r--r--src/test/ui/impl-trait/must_outlive_least_region_or_bound.stderr56
-rw-r--r--src/test/ui/impl-trait/static-return-lifetime-infered.stderr32
-rw-r--r--src/test/ui/impl-trait/type_parameters_captured.stderr8
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr6
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr6
-rw-r--r--src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr6
-rw-r--r--src/test/ui/issues/issue-11958.rs3
-rw-r--r--src/test/ui/issues/issue-11958.stderr20
-rw-r--r--src/test/ui/issues/issue-16683.stderr4
-rw-r--r--src/test/ui/issues/issue-16922.nll.stderr10
-rw-r--r--src/test/ui/issues/issue-16922.rs2
-rw-r--r--src/test/ui/issues/issue-16922.stderr17
-rw-r--r--src/test/ui/issues/issue-17758.stderr4
-rw-r--r--src/test/ui/issues/issue-18400.stderr1
-rw-r--r--src/test/ui/issues/issue-20413.stderr6
-rw-r--r--src/test/ui/issues/issue-20831-debruijn.stderr8
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr8
-rw-r--r--src/test/ui/issues/issue-38940.rs2
-rw-r--r--src/test/ui/issues/issue-38940.stderr2
-rw-r--r--src/test/ui/issues/issue-52213.stderr4
-rw-r--r--src/test/ui/issues/issue-55796.stderr8
-rw-r--r--src/test/ui/issues/issue-67552.rs30
-rw-r--r--src/test/ui/issues/issue-67552.stderr14
-rw-r--r--src/test/ui/issues/issue-72278.rs19
-rw-r--r--src/test/ui/issues/issue-72278.stderr15
-rw-r--r--src/test/ui/issues/issue-72574-1.rs8
-rw-r--r--src/test/ui/issues/issue-72574-1.stderr14
-rw-r--r--src/test/ui/issues/issue-72574-2.rs10
-rw-r--r--src/test/ui/issues/issue-72574-2.stderr14
-rw-r--r--src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr46
-rw-r--r--src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr6
-rw-r--r--src/test/ui/liveness/liveness-upvars.rs108
-rw-r--r--src/test/ui/liveness/liveness-upvars.stderr150
-rw-r--r--src/test/ui/nll/issue-55394.stderr4
-rw-r--r--src/test/ui/nll/normalization-bounds-error.stderr4
-rw-r--r--src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr6
-rw-r--r--src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr6
-rw-r--r--src/test/ui/nll/type-alias-free-regions.stderr16
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr4
-rw-r--r--src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr4
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-elision.stderr8
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr6
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs2
-rw-r--r--src/test/ui/object-lifetime/object-lifetime-default-from-box-error.stderr11
-rw-r--r--src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs9
-rw-r--r--src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr8
-rw-r--r--src/test/ui/proc-macro/macro-rules-capture.rs18
-rw-r--r--src/test/ui/proc-macro/macro-rules-capture.stderr12
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.nll.stderr10
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.rs9
-rw-r--r--src/test/ui/regions/region-object-lifetime-in-coercion.stderr38
-rw-r--r--src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr8
-rw-r--r--src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr4
-rw-r--r--src/test/ui/regions/regions-close-associated-type-into-object.stderr24
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-2.stderr4
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-4.stderr4
-rw-r--r--src/test/ui/regions/regions-close-object-into-object-5.stderr48
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-1.stderr16
-rw-r--r--src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr4
-rw-r--r--src/test/ui/regions/regions-close-param-into-object.stderr32
-rw-r--r--src/test/ui/regions/regions-creating-enums4.stderr8
-rw-r--r--src/test/ui/regions/regions-enum-not-wf.stderr35
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr8
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait-self.stderr6
-rw-r--r--src/test/ui/regions/regions-infer-bound-from-trait.stderr16
-rw-r--r--src/test/ui/regions/regions-nested-fns.stderr4
-rw-r--r--src/test/ui/regions/regions-normalize-in-where-clause-list.stderr12
-rw-r--r--src/test/ui/regions/regions-ret-borrowed-1.stderr4
-rw-r--r--src/test/ui/regions/regions-ret-borrowed.stderr4
-rw-r--r--src/test/ui/regions/regions-trait-object-subtyping.stderr4
-rw-r--r--src/test/ui/reject-specialized-drops-8142.stderr4
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr8
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr35
-rw-r--r--src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr16
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait-async.stderr13
-rw-r--r--src/test/ui/self/arbitrary_self_types_pin_lifetime_impl_trait.stderr16
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr115
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs110
-rw-r--r--src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr126
-rw-r--r--src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr8
-rw-r--r--src/test/ui/traits/self-without-lifetime-constraint.rs53
-rw-r--r--src/test/ui/traits/self-without-lifetime-constraint.stderr19
-rw-r--r--src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr4
-rw-r--r--src/test/ui/traits/trait-param-without-lifetime-constraint.rs20
-rw-r--r--src/test/ui/traits/trait-param-without-lifetime-constraint.stderr19
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-70121.rs23
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr27
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs4
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr19
-rw-r--r--src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr31
-rw-r--r--src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs67
-rw-r--r--src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr60
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs76
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr104
-rw-r--r--src/test/ui/unused-crate-deps/test-use-ok.rs15
-rw-r--r--src/test/ui/wf/wf-impl-associated-type-region.stderr8
-rw-r--r--src/test/ui/wf/wf-in-fn-type-static.stderr16
-rw-r--r--src/test/ui/wf/wf-in-obj-type-static.stderr8
-rw-r--r--src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr16
-rw-r--r--src/test/ui/wf/wf-trait-associated-type-region.stderr6
272 files changed, 5502 insertions, 1941 deletions
diff --git a/Cargo.lock b/Cargo.lock
index feb9ac96bd0..b2f5d058f5c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -4144,7 +4144,6 @@ dependencies = [
  "rustc_lexer",
  "rustc_session",
  "rustc_span",
- "smallvec 1.4.0",
  "unicode-normalization",
 ]
 
diff --git a/RELEASES.md b/RELEASES.md
index 8ea481f7e18..7cba27e134a 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,163 @@
+Version 1.44.0 (2020-06-04)
+==========================
+
+Language
+--------
+- [You can now use `async/.await` with `#[no_std]` enabled.][69033]
+- [Added the `unused_braces` lint.][70081]
+
+**Syntax-only changes**
+
+- [Expansion-driven outline module parsing][69838]
+```rust
+#[cfg(FALSE)]
+mod foo {
+    mod bar {
+        mod baz; // `foo/bar/baz.rs` doesn't exist, but no error!
+    }
+}
+```
+
+These are still rejected semantically, so you will likely receive an error but
+these changes can be seen and parsed by macros and conditional compilation.
+
+Compiler
+--------
+- [Rustc now respects the `-C codegen-units` flag in incremental mode.][70156]
+  Additionally when in incremental mode rustc defaults to 256 codegen units.
+- [Refactored `catch_unwind`, to have zero-cost unless unwinding is enabled and
+  a panic is thrown.][67502]
+- [Added tier 3\* support for the `aarch64-unknown-none` and
+  `aarch64-unknown-none-softfloat` targets.][68334]
+- [Added tier 3 support for `arm64-apple-tvos` and
+  `x86_64-apple-tvos` targets.][68191]
+
+
+Libraries
+---------
+- [Special cased `vec![]` to map directly to `Vec::new()`.][70632] This allows
+  `vec![]` to be able to be used in `const` contexts.
+- [`convert::Infallible` now implements `Hash`.][70281]
+- [`OsString` now implements `DerefMut` and `IndexMut` returning
+  a `&mut OsStr`.][70048]
+- [Unicode 13 is now supported.][69929]
+- [`String` now implements `From<&mut str>`.][69661]
+- [`IoSlice` now implements `Copy`.][69403]
+- [`Vec<T>` now implements `From<[T; N]>`.][68692] Where `N` is less than 32.
+- [`proc_macro::LexError` now implements `fmt::Display` and `Error`.][68899]
+- [`from_le_bytes`, `to_le_bytes`, `from_be_bytes`, `to_be_bytes`,
+  `from_ne_bytes`, and `to_ne_bytes` methods are now `const` for all
+  integer types.][69373]
+
+Stabilized APIs
+---------------
+- [`PathBuf::with_capacity`]
+- [`PathBuf::capacity`]
+- [`PathBuf::clear`]
+- [`PathBuf::reserve`]
+- [`PathBuf::reserve_exact`]
+- [`PathBuf::shrink_to_fit`]
+- [`f32::to_int_unchecked`]
+- [`f64::to_int_unchecked`]
+- [`Layout::align_to`]
+- [`Layout::pad_to_align`]
+- [`Layout::array`]
+- [`Layout::extend`]
+
+Cargo
+-----
+- [Added the `cargo tree` command which will print a tree graph of
+  your dependencies.][cargo/8062] E.g.
+  ```
+    mdbook v0.3.2 (/Users/src/rust/mdbook)
+  ├── ammonia v3.0.0
+  │   ├── html5ever v0.24.0
+  │   │   ├── log v0.4.8
+  │   │   │   └── cfg-if v0.1.9
+  │   │   ├── mac v0.1.1
+  │   │   └── markup5ever v0.9.0
+  │   │       ├── log v0.4.8 (*)
+  │   │       ├── phf v0.7.24
+  │   │       │   └── phf_shared v0.7.24
+  │   │       │       ├── siphasher v0.2.3
+  │   │       │       └── unicase v1.4.2
+  │   │       │           [build-dependencies]
+  │   │       │           └── version_check v0.1.5
+  ...
+  ```
+
+Misc
+----
+- [Rustdoc now allows you to specify `--crate-version` to have rustdoc include
+  the version in the sidebar.][69494]
+
+Compatibility Notes
+-------------------
+- [Rustc now correctly generates static libraries on Windows GNU targets with
+  the `.a` extension, rather than the previous `.lib`.][70937]
+- [Removed the `-C no_integrated_as` flag from rustc.][70345]
+- [The `file_name` property in JSON output of macro errors now points the actual
+  source file rather than the previous format of `<NAME macros>`.][70969]
+  **Note:** this may not point a file that actually exists on the user's system.
+- [The minimum required external LLVM version has been bumped to LLVM 8.][71147]
+- [`mem::{zeroed, uninitialised, MaybeUninit}` will now panic when used with types
+  that do not allow zero initialization such as `NonZeroU8`.][66059] This was
+  previously a warning.
+- [In 1.45.0 (the next release) converting a `f64` to `u32` using the `as`
+  operator has been defined as a saturating operation.][71269] This was previously
+  undefined behaviour, you can use the `{f64, f32}::to_int_unchecked` methods to
+  continue using the current behaviour which may desirable in rare performance
+  sensitive situations.
+
+Internal Only
+-------------
+These changes provide no direct user facing benefits, but represent significant
+improvements to the internals and overall performance of rustc and
+related tools.
+
+- [dep_graph Avoid allocating a set on when the number reads are small.][69778]
+- [Replace big JS dict with JSON parsing.][71250]
+
+[69373]: https://github.com/rust-lang/rust/pull/69373/
+[66059]: https://github.com/rust-lang/rust/pull/66059/
+[68191]: https://github.com/rust-lang/rust/pull/68191/
+[68899]: https://github.com/rust-lang/rust/pull/68899/
+[71147]: https://github.com/rust-lang/rust/pull/71147/
+[71250]: https://github.com/rust-lang/rust/pull/71250/
+[70937]: https://github.com/rust-lang/rust/pull/70937/
+[70969]: https://github.com/rust-lang/rust/pull/70969/
+[70632]: https://github.com/rust-lang/rust/pull/70632/
+[70281]: https://github.com/rust-lang/rust/pull/70281/
+[70345]: https://github.com/rust-lang/rust/pull/70345/
+[70048]: https://github.com/rust-lang/rust/pull/70048/
+[70081]: https://github.com/rust-lang/rust/pull/70081/
+[70156]: https://github.com/rust-lang/rust/pull/70156/
+[71269]: https://github.com/rust-lang/rust/pull/71269/
+[69838]: https://github.com/rust-lang/rust/pull/69838/
+[69929]: https://github.com/rust-lang/rust/pull/69929/
+[69661]: https://github.com/rust-lang/rust/pull/69661/
+[69778]: https://github.com/rust-lang/rust/pull/69778/
+[69494]: https://github.com/rust-lang/rust/pull/69494/
+[69403]: https://github.com/rust-lang/rust/pull/69403/
+[69033]: https://github.com/rust-lang/rust/pull/69033/
+[68692]: https://github.com/rust-lang/rust/pull/68692/
+[68334]: https://github.com/rust-lang/rust/pull/68334/
+[67502]: https://github.com/rust-lang/rust/pull/67502/
+[cargo/8062]: https://github.com/rust-lang/cargo/pull/8062/
+[`PathBuf::with_capacity`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.with_capacity
+[`PathBuf::capacity`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.capacity
+[`PathBuf::clear`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.clear
+[`PathBuf::reserve`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.reserve
+[`PathBuf::reserve_exact`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.reserve_exact
+[`PathBuf::shrink_to_fit`]: https://doc.rust-lang.org/std/path/struct.PathBuf.html#method.shrink_to_fit
+[`f32::to_int_unchecked`]: https://doc.rust-lang.org/std/primitive.f32.html#method.to_int_unchecked
+[`f64::to_int_unchecked`]: https://doc.rust-lang.org/std/primitive.f64.html#method.to_int_unchecked
+[`Layout::align_to`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.align_to
+[`Layout::pad_to_align`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.pad_to_align
+[`Layout::array`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.array
+[`Layout::extend`]: https://doc.rust-lang.org/std/alloc/struct.Layout.html#method.extend
+
+
 Version 1.43.1 (2020-05-07)
 ===========================
 
diff --git a/src/doc/unstable-book/src/library-features/asm.md b/src/doc/unstable-book/src/library-features/asm.md
index 0b68991fce2..ea560a6d709 100644
--- a/src/doc/unstable-book/src/library-features/asm.md
+++ b/src/doc/unstable-book/src/library-features/asm.md
@@ -468,12 +468,17 @@ Here is the list of currently supported register classes:
 | ARM | `qreg` | `q[0-15]` | `w` |
 | ARM | `qreg_low8` | `q[0-7]` | `t` |
 | ARM | `qreg_low4` | `q[0-3]` | `x` |
+| NVPTX | `reg16` | None\* | `h` |
+| NVPTX | `reg32` | None\* | `r` |
+| NVPTX | `reg64` | None\* | `l` |
 | RISC-V | `reg` | `x1`, `x[5-7]`, `x[9-15]`, `x[16-31]` (non-RV32E) | `r` |
 | RISC-V | `freg` | `f[0-31]` | `f` |
 
 > **Note**: On x86 we treat `reg_byte` differently from `reg` because the compiler can allocate `al` and `ah` separately whereas `reg` reserves the whole register.
 >
 > Note #2: On x86-64 the high byte registers (e.g. `ah`) are only available when used as an explicit register. Specifying the `reg_byte` register class for an operand will always allocate a low byte register.
+>
+> Note #3: NVPTX doesn't have a fixed register set, so named registers are not supported.
 
 Additional register classes may be added in the future based on demand (e.g. MMX, x87, etc).
 
@@ -495,6 +500,9 @@ Each register class has constraints on which value types they can be used with.
 | ARM | `sreg` | `vfp2` | `i32`, `f32` |
 | ARM | `dreg` | `vfp2` | `i64`, `f64`, `i8x8`, `i16x4`, `i32x2`, `i64x1`, `f32x2` |
 | ARM | `qreg` | `neon` | `i8x16`, `i16x8`, `i32x4`, `i64x2`, `f32x4` |
+| NVPTX | `reg16` | None | `i8`, `i16` |
+| NVPTX | `reg32` | None | `i8`, `i16`, `i32`, `f32` |
+| NVPTX | `reg64` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | RISC-V32 | `reg` | None | `i8`, `i16`, `i32`, `f32` |
 | RISC-V64 | `reg` | None | `i8`, `i16`, `i32`, `f32`, `i64`, `f64` |
 | RISC-V | `freg` | `f` | `f32` |
@@ -610,6 +618,9 @@ The supported modifiers are a subset of LLVM's (and GCC's) [asm template argumen
 | ARM | `dreg` | None | `d0` | `P` |
 | ARM | `qreg` | None | `q0` | `q` |
 | ARM | `qreg` | `e` / `f` | `d0` / `d1` | `e` / `f` |
+| NVPTX | `reg16` | None | `rs0` | None |
+| NVPTX | `reg32` | None | `r0` | None |
+| NVPTX | `reg64` | None | `rd0` | None |
 | RISC-V | `reg` | None | `x1` | None |
 | RISC-V | `freg` | None | `f0` | None |
 
diff --git a/src/liballoc/boxed.rs b/src/liballoc/boxed.rs
index 8ef6090c743..22c344323a2 100644
--- a/src/liballoc/boxed.rs
+++ b/src/liballoc/boxed.rs
@@ -865,6 +865,25 @@ impl From<Box<str>> for Box<[u8]> {
     }
 }
 
+#[stable(feature = "box_from_array", since = "1.45.0")]
+impl<T, const N: usize> From<[T; N]> for Box<[T]>
+where
+    [T; N]: LengthAtMost32,
+{
+    /// Converts a `[T; N]` into a `Box<[T]>`
+    ///
+    /// This conversion moves the array to newly heap-allocated memory.
+    ///
+    /// # Examples
+    /// ```rust
+    /// let boxed: Box<[u8]> = Box::from([4, 2]);
+    /// println!("{:?}", boxed);
+    /// ```
+    fn from(array: [T; N]) -> Box<[T]> {
+        box array
+    }
+}
+
 #[stable(feature = "boxed_slice_try_from", since = "1.43.0")]
 impl<T, const N: usize> TryFrom<Box<[T]>> for Box<[T; N]>
 where
@@ -1090,6 +1109,14 @@ impl<T: Clone> Clone for Box<[T]> {
     fn clone(&self) -> Self {
         self.to_vec().into_boxed_slice()
     }
+
+    fn clone_from(&mut self, other: &Self) {
+        if self.len() == other.len() {
+            self.clone_from_slice(&other);
+        } else {
+            *self = other.clone();
+        }
+    }
 }
 
 #[stable(feature = "box_borrow", since = "1.1.0")]
diff --git a/src/liballoc/collections/binary_heap.rs b/src/liballoc/collections/binary_heap.rs
index a3ef9989184..c2fe4691b34 100644
--- a/src/liballoc/collections/binary_heap.rs
+++ b/src/liballoc/collections/binary_heap.rs
@@ -1376,6 +1376,16 @@ impl<T: Ord> Extend<T> for BinaryHeap<T> {
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         <Self as SpecExtend<I>>::spec_extend(self, iter);
     }
+
+    #[inline]
+    fn extend_one(&mut self, item: T) {
+        self.push(item);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 impl<T: Ord, I: IntoIterator<Item = T>> SpecExtend<I> for BinaryHeap<T> {
@@ -1406,4 +1416,14 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BinaryHeap<T> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &item: &'a T) {
+        self.push(item);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
diff --git a/src/liballoc/collections/btree/map.rs b/src/liballoc/collections/btree/map.rs
index c6cb39b1bf5..fa1c09d9ece 100644
--- a/src/liballoc/collections/btree/map.rs
+++ b/src/liballoc/collections/btree/map.rs
@@ -1901,6 +1901,11 @@ impl<K: Ord, V> Extend<(K, V)> for BTreeMap<K, V> {
             self.insert(k, v);
         });
     }
+
+    #[inline]
+    fn extend_one(&mut self, (k, v): (K, V)) {
+        self.insert(k, v);
+    }
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
@@ -1908,6 +1913,11 @@ impl<'a, K: Ord + Copy, V: Copy> Extend<(&'a K, &'a V)> for BTreeMap<K, V> {
     fn extend<I: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: I) {
         self.extend(iter.into_iter().map(|(&key, &value)| (key, value)));
     }
+
+    #[inline]
+    fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) {
+        self.insert(k, v);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/collections/btree/set.rs b/src/liballoc/collections/btree/set.rs
index dee5fb878ff..525ef38c32f 100644
--- a/src/liballoc/collections/btree/set.rs
+++ b/src/liballoc/collections/btree/set.rs
@@ -1152,6 +1152,11 @@ impl<T: Ord> Extend<T> for BTreeSet<T> {
             self.insert(elem);
         });
     }
+
+    #[inline]
+    fn extend_one(&mut self, elem: T) {
+        self.insert(elem);
+    }
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
@@ -1159,6 +1164,11 @@ impl<'a, T: 'a + Ord + Copy> Extend<&'a T> for BTreeSet<T> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &elem: &'a T) {
+        self.insert(elem);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/collections/linked_list.rs b/src/liballoc/collections/linked_list.rs
index cc0f07b8227..85f2505f756 100644
--- a/src/liballoc/collections/linked_list.rs
+++ b/src/liballoc/collections/linked_list.rs
@@ -1748,6 +1748,11 @@ impl<T> Extend<T> for LinkedList<T> {
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         <Self as SpecExtend<I>>::spec_extend(self, iter);
     }
+
+    #[inline]
+    fn extend_one(&mut self, elem: T) {
+        self.push_back(elem);
+    }
 }
 
 impl<I: IntoIterator> SpecExtend<I> for LinkedList<I::Item> {
@@ -1767,6 +1772,11 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for LinkedList<T> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &elem: &'a T) {
+        self.push_back(elem);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/collections/vec_deque.rs b/src/liballoc/collections/vec_deque.rs
index 540649c61b3..ae54d3971ba 100644
--- a/src/liballoc/collections/vec_deque.rs
+++ b/src/liballoc/collections/vec_deque.rs
@@ -2881,6 +2881,16 @@ impl<A> Extend<A> for VecDeque<A> {
             }
         }
     }
+
+    #[inline]
+    fn extend_one(&mut self, elem: A) {
+        self.push_back(elem);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
@@ -2888,6 +2898,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for VecDeque<T> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &elem: &T) {
+        self.push_back(elem);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/liballoc/lib.rs b/src/liballoc/lib.rs
index 7aaa91ee10d..9bcfc9457f5 100644
--- a/src/liballoc/lib.rs
+++ b/src/liballoc/lib.rs
@@ -93,6 +93,7 @@
 #![feature(container_error_extra)]
 #![feature(dropck_eyepatch)]
 #![feature(exact_size_is_empty)]
+#![feature(extend_one)]
 #![feature(fmt_internals)]
 #![feature(fn_traits)]
 #![feature(fundamental)]
diff --git a/src/liballoc/raw_vec.rs b/src/liballoc/raw_vec.rs
index 2bd4733db42..56e284a12fa 100644
--- a/src/liballoc/raw_vec.rs
+++ b/src/liballoc/raw_vec.rs
@@ -315,7 +315,7 @@ impl<T, A: AllocRef> RawVec<T, A> {
     /// `used_capacity + needed_extra_capacity` elements. If it doesn't already,
     /// will reallocate the minimum possible amount of memory necessary.
     /// Generally this will be exactly the amount of memory necessary,
-    /// but in principle the allocator is free to give back more than
+    /// but in principle the allocator is free to give back more than what
     /// we asked for.
     ///
     /// If `used_capacity` exceeds `self.capacity()`, this may fail to actually allocate
diff --git a/src/liballoc/string.rs b/src/liballoc/string.rs
index f3fe1adebb1..0378ff5362a 100644
--- a/src/liballoc/string.rs
+++ b/src/liballoc/string.rs
@@ -1799,6 +1799,16 @@ impl Extend<char> for String {
         self.reserve(lower_bound);
         iterator.for_each(move |c| self.push(c));
     }
+
+    #[inline]
+    fn extend_one(&mut self, c: char) {
+        self.push(c);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 #[stable(feature = "extend_ref", since = "1.2.0")]
@@ -1806,6 +1816,16 @@ impl<'a> Extend<&'a char> for String {
     fn extend<I: IntoIterator<Item = &'a char>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &c: &'a char) {
+        self.push(c);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -1813,6 +1833,11 @@ impl<'a> Extend<&'a str> for String {
     fn extend<I: IntoIterator<Item = &'a str>>(&mut self, iter: I) {
         iter.into_iter().for_each(move |s| self.push_str(s));
     }
+
+    #[inline]
+    fn extend_one(&mut self, s: &'a str) {
+        self.push_str(s);
+    }
 }
 
 #[stable(feature = "extend_string", since = "1.4.0")]
@@ -1820,6 +1845,11 @@ impl Extend<String> for String {
     fn extend<I: IntoIterator<Item = String>>(&mut self, iter: I) {
         iter.into_iter().for_each(move |s| self.push_str(&s));
     }
+
+    #[inline]
+    fn extend_one(&mut self, s: String) {
+        self.push_str(&s);
+    }
 }
 
 #[stable(feature = "herd_cows", since = "1.19.0")]
@@ -1827,6 +1857,11 @@ impl<'a> Extend<Cow<'a, str>> for String {
     fn extend<I: IntoIterator<Item = Cow<'a, str>>>(&mut self, iter: I) {
         iter.into_iter().for_each(move |s| self.push_str(&s));
     }
+
+    #[inline]
+    fn extend_one(&mut self, s: Cow<'a, str>) {
+        self.push_str(&s);
+    }
 }
 
 /// A convenience impl that delegates to the impl for `&str`.
diff --git a/src/liballoc/tests/boxed.rs b/src/liballoc/tests/boxed.rs
index 66782ecbeb7..5377485da8f 100644
--- a/src/liballoc/tests/boxed.rs
+++ b/src/liballoc/tests/boxed.rs
@@ -16,3 +16,36 @@ fn unitialized_zero_size_box() {
         NonNull::<MaybeUninit<String>>::dangling().as_ptr(),
     );
 }
+
+#[derive(Clone, PartialEq, Eq, Debug)]
+struct Dummy {
+    _data: u8,
+}
+
+#[test]
+fn box_clone_and_clone_from_equivalence() {
+    for size in (0..8).map(|i| 2usize.pow(i)) {
+        let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
+        let clone = control.clone();
+        let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
+        copy.clone_from(&control);
+        assert_eq!(control, clone);
+        assert_eq!(control, copy);
+    }
+}
+
+/// This test might give a false positive in case the box realocates, but the alocator keeps the
+/// original pointer.
+///
+/// On the other hand it won't give a false negative, if it fails than the memory was definitly not
+/// reused
+#[test]
+fn box_clone_from_ptr_stability() {
+    for size in (0..8).map(|i| 2usize.pow(i)) {
+        let control = vec![Dummy { _data: 42 }; size].into_boxed_slice();
+        let mut copy = vec![Dummy { _data: 84 }; size].into_boxed_slice();
+        let copy_raw = copy.as_ptr() as usize;
+        copy.clone_from(&control);
+        assert_eq!(copy.as_ptr() as usize, copy_raw);
+    }
+}
diff --git a/src/liballoc/vec.rs b/src/liballoc/vec.rs
index d26cd77aae4..42fb1f8c737 100644
--- a/src/liballoc/vec.rs
+++ b/src/liballoc/vec.rs
@@ -2045,6 +2045,16 @@ impl<T> Extend<T> for Vec<T> {
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         <Self as SpecExtend<T, I::IntoIter>>::spec_extend(self, iter.into_iter())
     }
+
+    #[inline]
+    fn extend_one(&mut self, item: T) {
+        self.push(item);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 // Specialization trait used for Vec::from_iter and Vec::extend
@@ -2316,6 +2326,16 @@ impl<'a, T: 'a + Copy> Extend<&'a T> for Vec<T> {
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.spec_extend(iter.into_iter())
     }
+
+    #[inline]
+    fn extend_one(&mut self, &item: &'a T) {
+        self.push(item);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.reserve(additional);
+    }
 }
 
 macro_rules! __impl_slice_eq1 {
diff --git a/src/libcore/intrinsics.rs b/src/libcore/intrinsics.rs
index 9006e4cfaf7..2d97fecf8a7 100644
--- a/src/libcore/intrinsics.rs
+++ b/src/libcore/intrinsics.rs
@@ -1314,6 +1314,7 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is
     /// [`std::pointer::offset`](../../std/primitive.pointer.html#method.offset).
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     pub fn offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Calculates the offset from a pointer, potentially wrapping.
@@ -1331,6 +1332,7 @@ extern "rust-intrinsic" {
     /// The stabilized version of this intrinsic is
     /// [`std::pointer::wrapping_offset`](../../std/primitive.pointer.html#method.wrapping_offset).
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     pub fn arith_offset<T>(dst: *const T, offset: isize) -> *const T;
 
     /// Equivalent to the appropriate `llvm.memcpy.p0i8.0i8.*` intrinsic, with
diff --git a/src/libcore/iter/adapters/mod.rs b/src/libcore/iter/adapters/mod.rs
index 195847ee98d..00529f0e2d5 100644
--- a/src/libcore/iter/adapters/mod.rs
+++ b/src/libcore/iter/adapters/mod.rs
@@ -1619,6 +1619,69 @@ impl<I: Iterator> Peekable<I> {
         let iter = &mut self.iter;
         self.peeked.get_or_insert_with(|| iter.next()).as_ref()
     }
+
+    /// Consume the next value of this iterator if a condition is true.
+    ///
+    /// If `func` returns `true` for the next value of this iterator, consume and return it.
+    /// Otherwise, return `None`.
+    ///
+    /// # Examples
+    /// Consume a number if it's equal to 0.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (0..5).peekable();
+    /// // The first item of the iterator is 0; consume it.
+    /// assert_eq!(iter.next_if(|&x| x == 0), Some(0));
+    /// // The next item returned is now 1, so `consume` will return `false`.
+    /// assert_eq!(iter.next_if(|&x| x == 0), None);
+    /// // `next_if` saves the value of the next item if it was not equal to `expected`.
+    /// assert_eq!(iter.next(), Some(1));
+    /// ```
+    ///
+    /// Consume any number less than 10.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (1..20).peekable();
+    /// // Consume all numbers less than 10
+    /// while iter.next_if(|&x| x < 10).is_some() {}
+    /// // The next value returned will be 10
+    /// assert_eq!(iter.next(), Some(10));
+    /// ```
+    #[unstable(feature = "peekable_next_if", issue = "72480")]
+    pub fn next_if(&mut self, func: impl FnOnce(&I::Item) -> bool) -> Option<I::Item> {
+        match self.next() {
+            Some(matched) if func(&matched) => Some(matched),
+            other => {
+                // Since we called `self.next()`, we consumed `self.peeked`.
+                assert!(self.peeked.is_none());
+                self.peeked = Some(other);
+                None
+            }
+        }
+    }
+
+    /// Consume the next item if it is equal to `expected`.
+    ///
+    /// # Example
+    /// Consume a number if it's equal to 0.
+    /// ```
+    /// #![feature(peekable_next_if)]
+    /// let mut iter = (0..5).peekable();
+    /// // The first item of the iterator is 0; consume it.
+    /// assert_eq!(iter.next_if_eq(&0), Some(0));
+    /// // The next item returned is now 1, so `consume` will return `false`.
+    /// assert_eq!(iter.next_if_eq(&0), None);
+    /// // `next_if_eq` saves the value of the next item if it was not equal to `expected`.
+    /// assert_eq!(iter.next(), Some(1));
+    /// ```
+    #[unstable(feature = "peekable_next_if", issue = "72480")]
+    pub fn next_if_eq<R>(&mut self, expected: &R) -> Option<I::Item>
+    where
+        R: ?Sized,
+        I::Item: PartialEq<R>,
+    {
+        self.next_if(|next| next == expected)
+    }
 }
 
 /// An iterator that rejects elements while `predicate` returns `true`.
diff --git a/src/libcore/iter/range.rs b/src/libcore/iter/range.rs
index 388a5548a31..bd7e6cfa5a7 100644
--- a/src/libcore/iter/range.rs
+++ b/src/libcore/iter/range.rs
@@ -1,3 +1,4 @@
+use crate::char;
 use crate::convert::TryFrom;
 use crate::mem;
 use crate::ops::{self, Add, Sub, Try};
@@ -400,6 +401,73 @@ step_integer_impls! {
     wider than usize: [u32 i32], [u64 i64], [u128 i128];
 }
 
+#[unstable(feature = "step_trait", reason = "recently redesigned", issue = "42168")]
+unsafe impl Step for char {
+    #[inline]
+    fn steps_between(&start: &char, &end: &char) -> Option<usize> {
+        let start = start as u32;
+        let end = end as u32;
+        if start <= end {
+            let count = end - start;
+            if start < 0xD800 && 0xE000 <= end {
+                usize::try_from(count - 0x800).ok()
+            } else {
+                usize::try_from(count).ok()
+            }
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn forward_checked(start: char, count: usize) -> Option<char> {
+        let start = start as u32;
+        let mut res = Step::forward_checked(start, count)?;
+        if start < 0xD800 && 0xD800 <= res {
+            res = Step::forward_checked(res, 0x800)?;
+        }
+        if res <= char::MAX as u32 {
+            // SAFETY: res is a valid unicode scalar
+            // (below 0x110000 and not in 0xD800..0xE000)
+            Some(unsafe { char::from_u32_unchecked(res) })
+        } else {
+            None
+        }
+    }
+
+    #[inline]
+    fn backward_checked(start: char, count: usize) -> Option<char> {
+        let start = start as u32;
+        let mut res = Step::backward_checked(start, count)?;
+        if start >= 0xE000 && 0xE000 > res {
+            res = Step::backward_checked(res, 0x800)?;
+        }
+        // SAFETY: res is a valid unicode scalar
+        // (below 0x110000 and not in 0xD800..0xE000)
+        Some(unsafe { char::from_u32_unchecked(res) })
+    }
+
+    #[inline]
+    unsafe fn forward_unchecked(start: char, count: usize) -> char {
+        let start = start as u32;
+        let mut res = Step::forward_unchecked(start, count);
+        if start < 0xD800 && 0xD800 <= res {
+            res = Step::forward_unchecked(res, 0x800);
+        }
+        char::from_u32_unchecked(res)
+    }
+
+    #[inline]
+    unsafe fn backward_unchecked(start: char, count: usize) -> char {
+        let start = start as u32;
+        let mut res = Step::backward_unchecked(start, count);
+        if start >= 0xE000 && 0xE000 > res {
+            res = Step::backward_unchecked(res, 0x800);
+        }
+        char::from_u32_unchecked(res)
+    }
+}
+
 macro_rules! range_exact_iter_impl {
     ($($t:ty)*) => ($(
         #[stable(feature = "rust1", since = "1.0.0")]
@@ -551,15 +619,7 @@ impl<A: Step> Iterator for ops::RangeFrom<A> {
 
     #[inline]
     fn nth(&mut self, n: usize) -> Option<A> {
-        // If we would jump over the maximum value, panic immediately.
-        // This is consistent with behavior before the Step redesign,
-        // even though it's inconsistent with n `next` calls.
-        // To get consistent behavior, change it to use `forward` instead.
-        // This change should go through FCP separately to the redesign, so is for now left as a
-        // FIXME: make this consistent
-        let plus_n =
-            Step::forward_checked(self.start.clone(), n).expect("overflow in RangeFrom::nth");
-        // The final step should always be debug-checked.
+        let plus_n = Step::forward(self.start.clone(), n);
         self.start = Step::forward(plus_n.clone(), 1);
         Some(plus_n)
     }
@@ -582,7 +642,11 @@ impl<A: Step> Iterator for ops::RangeInclusive<A> {
         }
         let is_iterating = self.start < self.end;
         Some(if is_iterating {
-            let n = Step::forward(self.start.clone(), 1);
+            // SAFETY: just checked precondition
+            // We use the unchecked version here, because
+            // otherwise `for _ in '\0'..=char::MAX`
+            // does not successfully remove panicking code.
+            let n = unsafe { Step::forward_unchecked(self.start.clone(), 1) };
             mem::replace(&mut self.start, n)
         } else {
             self.exhausted = true;
diff --git a/src/libcore/iter/traits/collect.rs b/src/libcore/iter/traits/collect.rs
index f21ab8dbc37..9d20022b6ed 100644
--- a/src/libcore/iter/traits/collect.rs
+++ b/src/libcore/iter/traits/collect.rs
@@ -322,7 +322,7 @@ impl<I: Iterator> IntoIterator for I {
 pub trait Extend<A> {
     /// Extends a collection with the contents of an iterator.
     ///
-    /// As this is the only method for this trait, the [trait-level] docs
+    /// As this is the only required method for this trait, the [trait-level] docs
     /// contain more details.
     ///
     /// [trait-level]: trait.Extend.html
@@ -341,6 +341,20 @@ pub trait Extend<A> {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     fn extend<T: IntoIterator<Item = A>>(&mut self, iter: T);
+
+    /// Extends a collection with exactly one element.
+    #[unstable(feature = "extend_one", issue = "72631")]
+    fn extend_one(&mut self, item: A) {
+        self.extend(Some(item));
+    }
+
+    /// Reserves capacity in a collection for the given number of additional elements.
+    ///
+    /// The default implementation does nothing.
+    #[unstable(feature = "extend_one", issue = "72631")]
+    fn extend_reserve(&mut self, additional: usize) {
+        let _ = additional;
+    }
 }
 
 #[stable(feature = "extend_for_unit", since = "1.28.0")]
@@ -348,4 +362,5 @@ impl Extend<()> for () {
     fn extend<T: IntoIterator<Item = ()>>(&mut self, iter: T) {
         iter.into_iter().for_each(drop)
     }
+    fn extend_one(&mut self, _item: ()) {}
 }
diff --git a/src/libcore/iter/traits/iterator.rs b/src/libcore/iter/traits/iterator.rs
index 7f081f732fd..a10b34d931d 100644
--- a/src/libcore/iter/traits/iterator.rs
+++ b/src/libcore/iter/traits/iterator.rs
@@ -1711,9 +1711,9 @@ pub trait Iterator {
         ) -> impl FnMut((), T) + 'a {
             move |(), x| {
                 if f(&x) {
-                    left.extend(Some(x));
+                    left.extend_one(x);
                 } else {
-                    right.extend(Some(x));
+                    right.extend_one(x);
                 }
             }
         }
@@ -2686,14 +2686,20 @@ pub trait Iterator {
             us: &'a mut impl Extend<B>,
         ) -> impl FnMut((), (A, B)) + 'a {
             move |(), (t, u)| {
-                ts.extend(Some(t));
-                us.extend(Some(u));
+                ts.extend_one(t);
+                us.extend_one(u);
             }
         }
 
         let mut ts: FromA = Default::default();
         let mut us: FromB = Default::default();
 
+        let (lower_bound, _) = self.size_hint();
+        if lower_bound > 0 {
+            ts.extend_reserve(lower_bound);
+            us.extend_reserve(lower_bound);
+        }
+
         self.fold((), extend(&mut ts, &mut us));
 
         (ts, us)
diff --git a/src/libcore/lib.rs b/src/libcore/lib.rs
index ca13433caec..7d21f9a9a66 100644
--- a/src/libcore/lib.rs
+++ b/src/libcore/lib.rs
@@ -85,6 +85,7 @@
 #![feature(const_panic)]
 #![feature(const_fn_union)]
 #![feature(const_generics)]
+#![feature(const_ptr_offset)]
 #![feature(const_ptr_offset_from)]
 #![feature(const_result)]
 #![feature(const_slice_from_raw_parts)]
diff --git a/src/libcore/num/f32.rs b/src/libcore/num/f32.rs
index 434569020d2..6313de31ce4 100644
--- a/src/libcore/num/f32.rs
+++ b/src/libcore/num/f32.rs
@@ -810,4 +810,78 @@ impl f32 {
     pub fn from_ne_bytes(bytes: [u8; 4]) -> Self {
         Self::from_bits(u32::from_ne_bytes(bytes))
     }
+
+    /// Returns an ordering between self and other values.
+    /// Unlike the standard partial comparison between floating point numbers,
+    /// this comparison always produces an ordering in accordance to
+    /// the totalOrder predicate as defined in IEEE 754 (2008 revision)
+    /// floating point standard. The values are ordered in following order:
+    /// - Negative quiet NaN
+    /// - Negative signaling NaN
+    /// - Negative infinity
+    /// - Negative numbers
+    /// - Negative subnormal numbers
+    /// - Negative zero
+    /// - Positive zero
+    /// - Positive subnormal numbers
+    /// - Positive numbers
+    /// - Positive infinity
+    /// - Positive signaling NaN
+    /// - Positive quiet NaN
+    ///
+    /// # Example
+    /// ```
+    /// #![feature(total_cmp)]
+    /// struct GoodBoy {
+    ///     name: String,
+    ///     weight: f32,
+    /// }
+    ///
+    /// let mut bois = vec![
+    ///     GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
+    ///     GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
+    ///     GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
+    ///     GoodBoy { name: "Chonk".to_owned(), weight: f32::INFINITY },
+    ///     GoodBoy { name: "Abs. Unit".to_owned(), weight: f32::NAN },
+    ///     GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
+    /// ];
+    ///
+    /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
+    /// # assert!(bois.into_iter().map(|b| b.weight)
+    /// #     .zip([-5.0, 0.1, 10.0, 99.0, f32::INFINITY, f32::NAN].iter())
+    /// #     .all(|(a, b)| a.to_bits() == b.to_bits()))
+    /// ```
+    #[unstable(feature = "total_cmp", issue = "72599")]
+    #[inline]
+    pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
+        let mut left = self.to_bits() as i32;
+        let mut right = other.to_bits() as i32;
+
+        // In case of negatives, flip all the bits except the sign
+        // to achieve a similar layout as two's complement integers
+        //
+        // Why does this work? IEEE 754 floats consist of three fields:
+        // Sign bit, exponent and mantissa. The set of exponent and mantissa
+        // fields as a whole have the property that their bitwise order is
+        // equal to the numeric magnitude where the magnitude is defined.
+        // The magnitude is not normally defined on NaN values, but
+        // IEEE 754 totalOrder defines the NaN values also to follow the
+        // bitwise order. This leads to order explained in the doc comment.
+        // However, the representation of magnitude is the same for negative
+        // and positive numbers – only the sign bit is different.
+        // To easily compare the floats as signed integers, we need to
+        // flip the exponent and mantissa bits in case of negative numbers.
+        // We effectively convert the numbers to "two's complement" form.
+        //
+        // To do the flipping, we construct a mask and XOR against it.
+        // We branchlessly calculate an "all-ones except for the sign bit"
+        // mask from negative-signed values: right shifting sign-extends
+        // the integer, so we "fill" the mask with sign bits, and then
+        // convert to unsigned to push one more zero bit.
+        // On positive values, the mask is all zeros, so it's a no-op.
+        left ^= (((left >> 31) as u32) >> 1) as i32;
+        right ^= (((right >> 31) as u32) >> 1) as i32;
+
+        left.cmp(&right)
+    }
 }
diff --git a/src/libcore/num/f64.rs b/src/libcore/num/f64.rs
index 6476ddb4541..d42e5392c58 100644
--- a/src/libcore/num/f64.rs
+++ b/src/libcore/num/f64.rs
@@ -824,4 +824,78 @@ impl f64 {
     pub fn from_ne_bytes(bytes: [u8; 8]) -> Self {
         Self::from_bits(u64::from_ne_bytes(bytes))
     }
+
+    /// Returns an ordering between self and other values.
+    /// Unlike the standard partial comparison between floating point numbers,
+    /// this comparison always produces an ordering in accordance to
+    /// the totalOrder predicate as defined in IEEE 754 (2008 revision)
+    /// floating point standard. The values are ordered in following order:
+    /// - Negative quiet NaN
+    /// - Negative signaling NaN
+    /// - Negative infinity
+    /// - Negative numbers
+    /// - Negative subnormal numbers
+    /// - Negative zero
+    /// - Positive zero
+    /// - Positive subnormal numbers
+    /// - Positive numbers
+    /// - Positive infinity
+    /// - Positive signaling NaN
+    /// - Positive quiet NaN
+    ///
+    /// # Example
+    /// ```
+    /// #![feature(total_cmp)]
+    /// struct GoodBoy {
+    ///     name: String,
+    ///     weight: f64,
+    /// }
+    ///
+    /// let mut bois = vec![
+    ///     GoodBoy { name: "Pucci".to_owned(), weight: 0.1 },
+    ///     GoodBoy { name: "Woofer".to_owned(), weight: 99.0 },
+    ///     GoodBoy { name: "Yapper".to_owned(), weight: 10.0 },
+    ///     GoodBoy { name: "Chonk".to_owned(), weight: f64::INFINITY },
+    ///     GoodBoy { name: "Abs. Unit".to_owned(), weight: f64::NAN },
+    ///     GoodBoy { name: "Floaty".to_owned(), weight: -5.0 },
+    /// ];
+    ///
+    /// bois.sort_by(|a, b| a.weight.total_cmp(&b.weight));
+    /// # assert!(bois.into_iter().map(|b| b.weight)
+    /// #     .zip([-5.0, 0.1, 10.0, 99.0, f64::INFINITY, f64::NAN].iter())
+    /// #     .all(|(a, b)| a.to_bits() == b.to_bits()))
+    /// ```
+    #[unstable(feature = "total_cmp", issue = "72599")]
+    #[inline]
+    pub fn total_cmp(&self, other: &Self) -> crate::cmp::Ordering {
+        let mut left = self.to_bits() as i64;
+        let mut right = other.to_bits() as i64;
+
+        // In case of negatives, flip all the bits except the sign
+        // to achieve a similar layout as two's complement integers
+        //
+        // Why does this work? IEEE 754 floats consist of three fields:
+        // Sign bit, exponent and mantissa. The set of exponent and mantissa
+        // fields as a whole have the property that their bitwise order is
+        // equal to the numeric magnitude where the magnitude is defined.
+        // The magnitude is not normally defined on NaN values, but
+        // IEEE 754 totalOrder defines the NaN values also to follow the
+        // bitwise order. This leads to order explained in the doc comment.
+        // However, the representation of magnitude is the same for negative
+        // and positive numbers – only the sign bit is different.
+        // To easily compare the floats as signed integers, we need to
+        // flip the exponent and mantissa bits in case of negative numbers.
+        // We effectively convert the numbers to "two's complement" form.
+        //
+        // To do the flipping, we construct a mask and XOR against it.
+        // We branchlessly calculate an "all-ones except for the sign bit"
+        // mask from negative-signed values: right shifting sign-extends
+        // the integer, so we "fill" the mask with sign bits, and then
+        // convert to unsigned to push one more zero bit.
+        // On positive values, the mask is all zeros, so it's a no-op.
+        left ^= (((left >> 63) as u64) >> 1) as i64;
+        right ^= (((right >> 63) as u64) >> 1) as i64;
+
+        left.cmp(&right)
+    }
 }
diff --git a/src/libcore/ops/range.rs b/src/libcore/ops/range.rs
index d4e6048579a..d86f39c4550 100644
--- a/src/libcore/ops/range.rs
+++ b/src/libcore/ops/range.rs
@@ -151,10 +151,16 @@ impl<Idx: PartialOrd<Idx>> Range<Idx> {
 ///
 /// The `RangeFrom` `start..` contains all values with `x >= start`.
 ///
-/// *Note*: Currently, no overflow checking is done for the [`Iterator`]
-/// implementation; if you use an integer range and the integer overflows, it
-/// might panic in debug mode or create an endless loop in release mode. **This
-/// overflow behavior might change in the future.**
+/// *Note*: Overflow in the [`Iterator`] implementation (when the contained
+/// data type reaches its numerical limit) is allowed to panic, wrap, or
+/// saturate. This behavior is defined by the implementation of the [`Step`]
+/// trait. For primitive integers, this follows the normal rules, and respects
+/// the overflow checks profile (panic in debug, wrap in release). Note also
+/// that overflow happens earlier than you might assume: the overflow happens
+/// in the call to `next` that yields the maximum value, as the range must be
+/// set to a state to yield the next value.
+///
+/// [`Step`]: crate::iter::Step
 ///
 /// # Examples
 ///
diff --git a/src/libcore/ptr/const_ptr.rs b/src/libcore/ptr/const_ptr.rs
index 85ba5fc0638..835183d171a 100644
--- a/src/libcore/ptr/const_ptr.rs
+++ b/src/libcore/ptr/const_ptr.rs
@@ -151,8 +151,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn offset(self, count: isize) -> *const T
+    pub const unsafe fn offset(self, count: isize) -> *const T
     where
         T: Sized,
     {
@@ -210,8 +211,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *const T
+    pub const fn wrapping_offset(self, count: isize) -> *const T
     where
         T: Sized,
     {
@@ -393,8 +395,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn add(self, count: usize) -> Self
+    pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -455,8 +458,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn sub(self, count: usize) -> Self
+    pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -511,8 +515,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_add(self, count: usize) -> Self
+    pub const fn wrapping_add(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -567,8 +572,9 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_sub(self, count: usize) -> Self
+    pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
     {
diff --git a/src/libcore/ptr/mut_ptr.rs b/src/libcore/ptr/mut_ptr.rs
index 0781d7e6cac..40b5e4e2234 100644
--- a/src/libcore/ptr/mut_ptr.rs
+++ b/src/libcore/ptr/mut_ptr.rs
@@ -145,8 +145,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn offset(self, count: isize) -> *mut T
+    pub const unsafe fn offset(self, count: isize) -> *mut T
     where
         T: Sized,
     {
@@ -203,8 +204,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "ptr_wrapping_offset", since = "1.16.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_offset(self, count: isize) -> *mut T
+    pub const fn wrapping_offset(self, count: isize) -> *mut T
     where
         T: Sized,
     {
@@ -439,8 +441,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn add(self, count: usize) -> Self
+    pub const unsafe fn add(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -501,8 +504,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub unsafe fn sub(self, count: usize) -> Self
+    pub const unsafe fn sub(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -557,8 +561,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_add(self, count: usize) -> Self
+    pub const fn wrapping_add(self, count: usize) -> Self
     where
         T: Sized,
     {
@@ -613,8 +618,9 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "pointer_methods", since = "1.26.0")]
     #[must_use = "returns a new pointer rather than modifying its argument"]
+    #[rustc_const_unstable(feature = "const_ptr_offset", issue = "71499")]
     #[inline]
-    pub fn wrapping_sub(self, count: usize) -> Self
+    pub const fn wrapping_sub(self, count: usize) -> Self
     where
         T: Sized,
     {
diff --git a/src/libcore/tests/iter.rs b/src/libcore/tests/iter.rs
index 52cf068f0a5..ab4f4aa7c73 100644
--- a/src/libcore/tests/iter.rs
+++ b/src/libcore/tests/iter.rs
@@ -813,6 +813,30 @@ fn test_iterator_peekable_rfold() {
     assert_eq!(i, xs.len());
 }
 
+#[test]
+fn test_iterator_peekable_next_if_eq() {
+    // first, try on references
+    let xs = vec!["Heart", "of", "Gold"];
+    let mut it = xs.into_iter().peekable();
+    // try before `peek()`
+    assert_eq!(it.next_if_eq(&"trillian"), None);
+    assert_eq!(it.next_if_eq(&"Heart"), Some("Heart"));
+    // try after peek()
+    assert_eq!(it.peek(), Some(&"of"));
+    assert_eq!(it.next_if_eq(&"of"), Some("of"));
+    assert_eq!(it.next_if_eq(&"zaphod"), None);
+    // make sure `next()` still behaves
+    assert_eq!(it.next(), Some("Gold"));
+
+    // make sure comparison works for owned values
+    let xs = vec![String::from("Ludicrous"), "speed".into()];
+    let mut it = xs.into_iter().peekable();
+    // make sure basic functionality works
+    assert_eq!(it.next_if_eq("Ludicrous"), Some("Ludicrous".into()));
+    assert_eq!(it.next_if_eq("speed"), Some("speed".into()));
+    assert_eq!(it.next_if_eq(""), None);
+}
+
 /// This is an iterator that follows the Iterator contract,
 /// but it is not fused. After having returned None once, it will start
 /// producing elements if .next() is called again.
@@ -1933,6 +1957,18 @@ fn test_range() {
 }
 
 #[test]
+fn test_char_range() {
+    use std::char;
+    assert!(('\0'..=char::MAX).eq((0..=char::MAX as u32).filter_map(char::from_u32)));
+    assert!(('\0'..=char::MAX).rev().eq((0..=char::MAX as u32).filter_map(char::from_u32).rev()));
+
+    assert_eq!(('\u{D7FF}'..='\u{E000}').count(), 2);
+    assert_eq!(('\u{D7FF}'..='\u{E000}').size_hint(), (2, Some(2)));
+    assert_eq!(('\u{D7FF}'..'\u{E000}').count(), 1);
+    assert_eq!(('\u{D7FF}'..'\u{E000}').size_hint(), (1, Some(1)));
+}
+
+#[test]
 fn test_range_exhaustion() {
     let mut r = 10..10;
     assert!(r.is_empty());
diff --git a/src/libcore/tests/lib.rs b/src/libcore/tests/lib.rs
index 6a8e908b9c6..37ebf411280 100644
--- a/src/libcore/tests/lib.rs
+++ b/src/libcore/tests/lib.rs
@@ -43,6 +43,7 @@
 #![feature(leading_trailing_ones)]
 #![feature(const_forget)]
 #![feature(option_unwrap_none)]
+#![feature(peekable_next_if)]
 
 extern crate test;
 
diff --git a/src/librustc_ast/token.rs b/src/librustc_ast/token.rs
index 2e2bc380e84..a5b9c2a95bb 100644
--- a/src/librustc_ast/token.rs
+++ b/src/librustc_ast/token.rs
@@ -673,6 +673,62 @@ impl Token {
 
         Some(Token::new(kind, self.span.to(joint.span)))
     }
+
+    // See comments in `Nonterminal::to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    crate fn probably_equal_for_proc_macro(&self, other: &Token) -> bool {
+        if mem::discriminant(&self.kind) != mem::discriminant(&other.kind) {
+            return false;
+        }
+        match (&self.kind, &other.kind) {
+            (&Eq, &Eq)
+            | (&Lt, &Lt)
+            | (&Le, &Le)
+            | (&EqEq, &EqEq)
+            | (&Ne, &Ne)
+            | (&Ge, &Ge)
+            | (&Gt, &Gt)
+            | (&AndAnd, &AndAnd)
+            | (&OrOr, &OrOr)
+            | (&Not, &Not)
+            | (&Tilde, &Tilde)
+            | (&At, &At)
+            | (&Dot, &Dot)
+            | (&DotDot, &DotDot)
+            | (&DotDotDot, &DotDotDot)
+            | (&DotDotEq, &DotDotEq)
+            | (&Comma, &Comma)
+            | (&Semi, &Semi)
+            | (&Colon, &Colon)
+            | (&ModSep, &ModSep)
+            | (&RArrow, &RArrow)
+            | (&LArrow, &LArrow)
+            | (&FatArrow, &FatArrow)
+            | (&Pound, &Pound)
+            | (&Dollar, &Dollar)
+            | (&Question, &Question)
+            | (&Whitespace, &Whitespace)
+            | (&Comment, &Comment)
+            | (&Eof, &Eof) => true,
+
+            (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
+
+            (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
+
+            (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
+
+            (&Literal(a), &Literal(b)) => a == b,
+
+            (&Lifetime(a), &Lifetime(b)) => a == b,
+            (&Ident(a, b), &Ident(c, d)) => {
+                b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
+            }
+
+            (&Interpolated(_), &Interpolated(_)) => false,
+
+            _ => panic!("forgot to add a token?"),
+        }
+    }
 }
 
 impl PartialEq<TokenKind> for Token {
diff --git a/src/librustc_ast/tokenstream.rs b/src/librustc_ast/tokenstream.rs
index 9d0199078fa..075aaa7e5bc 100644
--- a/src/librustc_ast/tokenstream.rs
+++ b/src/librustc_ast/tokenstream.rs
@@ -21,6 +21,8 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::{Span, DUMMY_SP};
 use smallvec::{smallvec, SmallVec};
 
+use log::debug;
+
 use std::{iter, mem};
 
 /// When the main rust parser encounters a syntax-extension invocation, it
@@ -66,6 +68,23 @@ impl TokenTree {
         }
     }
 
+    // See comments in `Nonterminal::to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    //
+    // This is otherwise the same as `eq_unspanned`, only recursing with a
+    // different method.
+    pub fn probably_equal_for_proc_macro(&self, other: &TokenTree) -> bool {
+        match (self, other) {
+            (TokenTree::Token(token), TokenTree::Token(token2)) => {
+                token.probably_equal_for_proc_macro(token2)
+            }
+            (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
+                delim == delim2 && tts.probably_equal_for_proc_macro(&tts2)
+            }
+            _ => false,
+        }
+    }
+
     /// Retrieves the TokenTree's span.
     pub fn span(&self) -> Span {
         match self {
@@ -288,6 +307,112 @@ impl TokenStream {
         t1.next().is_none() && t2.next().is_none()
     }
 
+    // See comments in `Nonterminal::to_tokenstream` for why we care about
+    // *probably* equal here rather than actual equality
+    //
+    // This is otherwise the same as `eq_unspanned`, only recursing with a
+    // different method.
+    pub fn probably_equal_for_proc_macro(&self, other: &TokenStream) -> bool {
+        // When checking for `probably_eq`, we ignore certain tokens that aren't
+        // preserved in the AST. Because they are not preserved, the pretty
+        // printer arbitrarily adds or removes them when printing as token
+        // streams, making a comparison between a token stream generated from an
+        // AST and a token stream which was parsed into an AST more reliable.
+        fn semantic_tree(tree: &TokenTree) -> bool {
+            if let TokenTree::Token(token) = tree {
+                if let
+                    // The pretty printer tends to add trailing commas to
+                    // everything, and in particular, after struct fields.
+                    | token::Comma
+                    // The pretty printer emits `NoDelim` as whitespace.
+                    | token::OpenDelim(DelimToken::NoDelim)
+                    | token::CloseDelim(DelimToken::NoDelim)
+                    // The pretty printer collapses many semicolons into one.
+                    | token::Semi
+                    // The pretty printer collapses whitespace arbitrarily and can
+                    // introduce whitespace from `NoDelim`.
+                    | token::Whitespace
+                    // The pretty printer can turn `$crate` into `::crate_name`
+                    | token::ModSep = token.kind {
+                    return false;
+                }
+            }
+            true
+        }
+
+        // When comparing two `TokenStream`s, we ignore the `IsJoint` information.
+        //
+        // However, `rustc_parse::lexer::tokentrees::TokenStreamBuilder` will
+        // use `Token.glue` on adjacent tokens with the proper `IsJoint`.
+        // Since we are ignoreing `IsJoint`, a 'glued' token (e.g. `BinOp(Shr)`)
+        // and its 'split'/'unglued' compoenents (e.g. `Gt, Gt`) are equivalent
+        // when determining if two `TokenStream`s are 'probably equal'.
+        //
+        // Therefore, we use `break_two_token_op` to convert all tokens
+        // to the 'unglued' form (if it exists). This ensures that two
+        // `TokenStream`s which differ only in how their tokens are glued
+        // will be considered 'probably equal', which allows us to keep spans.
+        //
+        // This is important when the original `TokenStream` contained
+        // extra spaces (e.g. `f :: < Vec < _ > > ( ) ;'). These extra spaces
+        // will be omitted when we pretty-print, which can cause the original
+        // and reparsed `TokenStream`s to differ in the assignment of `IsJoint`,
+        // leading to some tokens being 'glued' together in one stream but not
+        // the other. See #68489 for more details.
+        fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
+            // In almost all cases, we should have either zero or one levels
+            // of 'unglueing'. However, in some unusual cases, we may need
+            // to iterate breaking tokens mutliple times. For example:
+            // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
+            let mut token_trees: SmallVec<[_; 2]>;
+            if let TokenTree::Token(token) = &tree {
+                let mut out = SmallVec::<[_; 2]>::new();
+                out.push(token.clone());
+                // Iterate to fixpoint:
+                // * We start off with 'out' containing our initial token, and `temp` empty
+                // * If we are able to break any tokens in `out`, then `out` will have
+                //   at least one more element than 'temp', so we will try to break tokens
+                //   again.
+                // * If we cannot break any tokens in 'out', we are done
+                loop {
+                    let mut temp = SmallVec::<[_; 2]>::new();
+                    let mut changed = false;
+
+                    for token in out.into_iter() {
+                        if let Some((first, second)) = token.kind.break_two_token_op() {
+                            temp.push(Token::new(first, DUMMY_SP));
+                            temp.push(Token::new(second, DUMMY_SP));
+                            changed = true;
+                        } else {
+                            temp.push(token);
+                        }
+                    }
+                    out = temp;
+                    if !changed {
+                        break;
+                    }
+                }
+                token_trees = out.into_iter().map(|t| TokenTree::Token(t)).collect();
+                if token_trees.len() != 1 {
+                    debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
+                }
+            } else {
+                token_trees = SmallVec::new();
+                token_trees.push(tree);
+            }
+            token_trees.into_iter()
+        }
+
+        let mut t1 = self.trees().filter(semantic_tree).flat_map(break_tokens);
+        let mut t2 = other.trees().filter(semantic_tree).flat_map(break_tokens);
+        for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
+            if !t1.probably_equal_for_proc_macro(&t2) {
+                return false;
+            }
+        }
+        t1.next().is_none() && t2.next().is_none()
+    }
+
     pub fn map_enumerated<F: FnMut(usize, TokenTree) -> TokenTree>(self, mut f: F) -> TokenStream {
         TokenStream(Lrc::new(
             self.0
diff --git a/src/librustc_ast_lowering/expr.rs b/src/librustc_ast_lowering/expr.rs
index fd69f5c1e5f..c9037da377e 100644
--- a/src/librustc_ast_lowering/expr.rs
+++ b/src/librustc_ast_lowering/expr.rs
@@ -974,20 +974,18 @@ impl<'hir> LoweringContext<'_, 'hir> {
     }
 
     fn lower_expr_asm(&mut self, sp: Span, asm: &InlineAsm) -> hir::ExprKind<'hir> {
-        let asm_arch = if let Some(asm_arch) = self.sess.asm_arch {
-            asm_arch
-        } else {
+        if self.sess.asm_arch.is_none() {
             struct_span_err!(self.sess, sp, E0472, "asm! is unsupported on this target").emit();
-            return hir::ExprKind::Err;
-        };
-        if asm.options.contains(InlineAsmOptions::ATT_SYNTAX) {
-            match asm_arch {
-                asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64 => {}
-                _ => self
-                    .sess
-                    .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
-                    .emit(),
-            }
+        }
+        if asm.options.contains(InlineAsmOptions::ATT_SYNTAX)
+            && !matches!(
+                self.sess.asm_arch,
+                Some(asm::InlineAsmArch::X86 | asm::InlineAsmArch::X86_64)
+            )
+        {
+            self.sess
+                .struct_span_err(sp, "the `att_syntax` option is only supported on x86")
+                .emit();
         }
 
         // Lower operands to HIR, filter_map skips any operands with invalid
@@ -1001,10 +999,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     Some(match reg {
                         InlineAsmRegOrRegClass::Reg(s) => asm::InlineAsmRegOrRegClass::Reg(
                             asm::InlineAsmReg::parse(
-                                asm_arch,
-                                |feature| {
-                                    self.sess.target_features.contains(&Symbol::intern(feature))
-                                },
+                                sess.asm_arch?,
+                                |feature| sess.target_features.contains(&Symbol::intern(feature)),
                                 s,
                             )
                             .map_err(|e| {
@@ -1015,7 +1011,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         ),
                         InlineAsmRegOrRegClass::RegClass(s) => {
                             asm::InlineAsmRegOrRegClass::RegClass(
-                                asm::InlineAsmRegClass::parse(asm_arch, s)
+                                asm::InlineAsmRegClass::parse(sess.asm_arch?, s)
                                     .map_err(|e| {
                                         let msg = format!(
                                             "invalid register class `{}`: {}",
@@ -1029,33 +1025,38 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         }
                     })
                 };
-                let op = match op {
-                    InlineAsmOperand::In { reg, expr } => hir::InlineAsmOperand::In {
-                        reg: lower_reg(*reg)?,
+
+                // lower_reg is executed last because we need to lower all
+                // sub-expressions even if we throw them away later.
+                let op = match *op {
+                    InlineAsmOperand::In { reg, ref expr } => hir::InlineAsmOperand::In {
                         expr: self.lower_expr_mut(expr),
+                        reg: lower_reg(reg)?,
                     },
-                    InlineAsmOperand::Out { reg, late, expr } => hir::InlineAsmOperand::Out {
-                        reg: lower_reg(*reg)?,
-                        late: *late,
+                    InlineAsmOperand::Out { reg, late, ref expr } => hir::InlineAsmOperand::Out {
+                        late,
                         expr: expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                        reg: lower_reg(reg)?,
                     },
-                    InlineAsmOperand::InOut { reg, late, expr } => hir::InlineAsmOperand::InOut {
-                        reg: lower_reg(*reg)?,
-                        late: *late,
-                        expr: self.lower_expr_mut(expr),
-                    },
-                    InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
+                    InlineAsmOperand::InOut { reg, late, ref expr } => {
+                        hir::InlineAsmOperand::InOut {
+                            late,
+                            expr: self.lower_expr_mut(expr),
+                            reg: lower_reg(reg)?,
+                        }
+                    }
+                    InlineAsmOperand::SplitInOut { reg, late, ref in_expr, ref out_expr } => {
                         hir::InlineAsmOperand::SplitInOut {
-                            reg: lower_reg(*reg)?,
-                            late: *late,
+                            late,
                             in_expr: self.lower_expr_mut(in_expr),
                             out_expr: out_expr.as_ref().map(|expr| self.lower_expr_mut(expr)),
+                            reg: lower_reg(reg)?,
                         }
                     }
-                    InlineAsmOperand::Const { expr } => {
+                    InlineAsmOperand::Const { ref expr } => {
                         hir::InlineAsmOperand::Const { expr: self.lower_expr_mut(expr) }
                     }
-                    InlineAsmOperand::Sym { expr } => {
+                    InlineAsmOperand::Sym { ref expr } => {
                         hir::InlineAsmOperand::Sym { expr: self.lower_expr_mut(expr) }
                     }
                 };
@@ -1069,6 +1070,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
 
         // Validate template modifiers against the register classes for the operands
+        let asm_arch = sess.asm_arch.unwrap();
         for p in &asm.template {
             if let InlineAsmTemplatePiece::Placeholder {
                 operand_idx,
diff --git a/src/librustc_ast_lowering/item.rs b/src/librustc_ast_lowering/item.rs
index eced17c9245..47d10f86d03 100644
--- a/src/librustc_ast_lowering/item.rs
+++ b/src/librustc_ast_lowering/item.rs
@@ -1321,12 +1321,15 @@ impl<'hir> LoweringContext<'_, 'hir> {
                                     .get_partial_res(bound_pred.bounded_ty.id)
                                     .map(|d| d.base_res())
                                 {
-                                    if let Some(node_id) =
-                                        self.resolver.definitions().as_local_node_id(def_id)
-                                    {
+                                    if let Some(def_id) = def_id.as_local() {
                                         for param in &generics.params {
                                             if let GenericParamKind::Type { .. } = param.kind {
-                                                if node_id == param.id {
+                                                if def_id
+                                                    == self
+                                                        .resolver
+                                                        .definitions()
+                                                        .local_def_id(param.id)
+                                                {
                                                     add_bounds
                                                         .entry(param.id)
                                                         .or_default()
diff --git a/src/librustc_ast_lowering/pat.rs b/src/librustc_ast_lowering/pat.rs
index 496e401d061..55c1f802663 100644
--- a/src/librustc_ast_lowering/pat.rs
+++ b/src/librustc_ast_lowering/pat.rs
@@ -3,6 +3,7 @@ use super::{ImplTraitContext, LoweringContext, ParamMode};
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_data_structures::stack::ensure_sufficient_stack;
+use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
 use rustc_span::symbol::Ident;
@@ -102,10 +103,36 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
             // Note that unlike for slice patterns,
             // where `xs @ ..` is a legal sub-slice pattern,
             // it is not a legal sub-tuple pattern.
-            if pat.is_rest() {
-                rest = Some((idx, pat.span));
-                break;
+            match pat.kind {
+                // Found a sub-tuple rest pattern
+                PatKind::Rest => {
+                    rest = Some((idx, pat.span));
+                    break;
+                }
+                // Found a sub-tuple pattern `$binding_mode $ident @ ..`.
+                // This is not allowed as a sub-tuple pattern
+                PatKind::Ident(ref _bm, ident, Some(ref sub)) if sub.is_rest() => {
+                    rest = Some((idx, pat.span));
+                    let sp = pat.span;
+                    self.diagnostic()
+                        .struct_span_err(
+                            sp,
+                            &format!("`{} @` is not allowed in a {}", ident.name, ctx),
+                        )
+                        .span_label(sp, "this is only allowed in slice patterns")
+                        .help("remove this and bind each tuple field independently")
+                        .span_suggestion_verbose(
+                            sp,
+                            &format!("if you don't need to use the contents of {}, discard the tuple's remaining fields", ident),
+                            "..".to_string(),
+                            Applicability::MaybeIncorrect,
+                        )
+                        .emit();
+                    break;
+                }
+                _ => {}
             }
+
             // It was not a sub-tuple pattern so lower it normally.
             elems.push(self.lower_pat(pat));
         }
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index f3bee85e6fc..9d4a30f23a2 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -254,6 +254,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                     ]);
                 }
                 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
+                InlineAsmArch::Nvptx64 => {}
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
@@ -426,6 +427,9 @@ fn reg_to_llvm(reg: InlineAsmRegOrRegClass) -> String {
             | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => "x",
             InlineAsmRegClass::Arm(ArmInlineAsmRegClass::dreg)
             | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg) => "w",
+            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => "h",
+            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => "r",
+            InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => "l",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => "r",
             InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => "f",
             InlineAsmRegClass::X86(X86InlineAsmRegClass::reg) => "r",
@@ -468,6 +472,7 @@ fn modifier_to_llvm(
                 modifier
             }
         }
+        InlineAsmRegClass::Nvptx(_) => None,
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
         | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
@@ -518,6 +523,9 @@ fn dummy_output_type(cx: &CodegenCx<'ll, 'tcx>, reg: InlineAsmRegClass) -> &'ll
         | InlineAsmRegClass::Arm(ArmInlineAsmRegClass::qreg_low4) => {
             cx.type_vector(cx.type_i64(), 2)
         }
+        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg16) => cx.type_i16(),
+        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg32) => cx.type_i32(),
+        InlineAsmRegClass::Nvptx(NvptxInlineAsmRegClass::reg64) => cx.type_i64(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg) => cx.type_i32(),
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => cx.type_f32(),
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
diff --git a/src/librustc_codegen_ssa/back/link.rs b/src/librustc_codegen_ssa/back/link.rs
index 9a7c4907754..dcce1d45298 100644
--- a/src/librustc_codegen_ssa/back/link.rs
+++ b/src/librustc_codegen_ssa/back/link.rs
@@ -1194,9 +1194,10 @@ fn link_output_kind(sess: &Session, crate_type: CrateType) -> LinkOutputKind {
     };
 
     // Adjust the output kind to target capabilities.
-    let pic_exe_supported = sess.target.target.options.position_independent_executables;
-    let static_pic_exe_supported = false; // FIXME: Add this option to target specs.
-    let static_dylib_supported = sess.target.target.options.crt_static_allows_dylibs;
+    let opts = &sess.target.target.options;
+    let pic_exe_supported = opts.position_independent_executables;
+    let static_pic_exe_supported = opts.static_position_independent_executables;
+    let static_dylib_supported = opts.crt_static_allows_dylibs;
     match kind {
         LinkOutputKind::DynamicPicExe if !pic_exe_supported => LinkOutputKind::DynamicNoPicExe,
         LinkOutputKind::StaticPicExe if !static_pic_exe_supported => LinkOutputKind::StaticNoPicExe,
@@ -1580,16 +1581,7 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
     }
 
     // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Support `StaticPicExe` correctly.
-    match link_output_kind {
-        LinkOutputKind::DynamicPicExe | LinkOutputKind::StaticPicExe => {
-            cmd.position_independent_executable()
-        }
-        LinkOutputKind::DynamicNoPicExe | LinkOutputKind::StaticNoPicExe => {
-            cmd.no_position_independent_executable()
-        }
-        _ => {}
-    }
+    cmd.set_output_kind(link_output_kind, out_filename);
 
     // OBJECT-FILES-NO, AUDIT-ORDER
     add_relro_args(cmd, sess);
@@ -1618,17 +1610,6 @@ fn linker_with_args<'a, B: ArchiveBuilder<'a>>(
         tmpdir,
     );
 
-    // NO-OPT-OUT, OBJECT-FILES-NO, AUDIT-ORDER
-    // FIXME: Merge with the previous `link_output_kind` match,
-    // and support `StaticPicExe` and `StaticDylib` correctly.
-    match link_output_kind {
-        LinkOutputKind::StaticNoPicExe | LinkOutputKind::StaticPicExe => {
-            cmd.build_static_executable()
-        }
-        LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => cmd.build_dylib(out_filename),
-        _ => {}
-    }
-
     // OBJECT-FILES-NO, AUDIT-ORDER
     if sess.opts.cg.profile_generate.enabled() {
         cmd.pgo_gen();
diff --git a/src/librustc_codegen_ssa/back/linker.rs b/src/librustc_codegen_ssa/back/linker.rs
index 49de8c5e28a..46c365efdb5 100644
--- a/src/librustc_codegen_ssa/back/linker.rs
+++ b/src/librustc_codegen_ssa/back/linker.rs
@@ -17,7 +17,7 @@ use rustc_serialize::{json, Encoder};
 use rustc_session::config::{self, CrateType, DebugInfo, LinkerPluginLto, Lto, OptLevel, Strip};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_target::spec::{LinkerFlavor, LldFlavor};
+use rustc_target::spec::{LinkOutputKind, LinkerFlavor, LldFlavor};
 
 /// Disables non-English messages from localized linkers.
 /// Such messages may cause issues with text encoding on Windows (#35785)
@@ -101,6 +101,7 @@ impl LinkerInfo {
 /// MSVC linker (e.g., `link.exe`) is being used.
 pub trait Linker {
     fn cmd(&mut self) -> &mut Command;
+    fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path);
     fn link_dylib(&mut self, lib: Symbol);
     fn link_rust_dylib(&mut self, lib: Symbol, path: &Path);
     fn link_framework(&mut self, framework: Symbol);
@@ -113,8 +114,6 @@ pub trait Linker {
     fn output_filename(&mut self, path: &Path);
     fn add_object(&mut self, path: &Path);
     fn gc_sections(&mut self, keep_metadata: bool);
-    fn position_independent_executable(&mut self);
-    fn no_position_independent_executable(&mut self);
     fn full_relro(&mut self);
     fn partial_relro(&mut self);
     fn no_relro(&mut self);
@@ -124,8 +123,6 @@ pub trait Linker {
     fn debuginfo(&mut self, strip: Strip);
     fn no_crt_objects(&mut self);
     fn no_default_libraries(&mut self);
-    fn build_dylib(&mut self, out_filename: &Path);
-    fn build_static_executable(&mut self);
     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType);
     fn subsystem(&mut self, subsystem: &str);
     fn group_start(&mut self);
@@ -232,12 +229,94 @@ impl<'a> GccLinker<'a> {
         let target_cpu = self.target_cpu;
         self.linker_arg(&format!("-plugin-opt=mcpu={}", target_cpu));
     }
+
+    fn build_dylib(&mut self, out_filename: &Path) {
+        // On mac we need to tell the linker to let this library be rpathed
+        if self.sess.target.target.options.is_like_osx {
+            self.cmd.arg("-dynamiclib");
+            self.linker_arg("-dylib");
+
+            // Note that the `osx_rpath_install_name` option here is a hack
+            // purely to support rustbuild right now, we should get a more
+            // principled solution at some point to force the compiler to pass
+            // the right `-Wl,-install_name` with an `@rpath` in it.
+            if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
+                self.linker_arg("-install_name");
+                let mut v = OsString::from("@rpath/");
+                v.push(out_filename.file_name().unwrap());
+                self.linker_arg(&v);
+            }
+        } else {
+            self.cmd.arg("-shared");
+            if self.sess.target.target.options.is_like_windows {
+                // The output filename already contains `dll_suffix` so
+                // the resulting import library will have a name in the
+                // form of libfoo.dll.a
+                let implib_name =
+                    out_filename.file_name().and_then(|file| file.to_str()).map(|file| {
+                        format!(
+                            "{}{}{}",
+                            self.sess.target.target.options.staticlib_prefix,
+                            file,
+                            self.sess.target.target.options.staticlib_suffix
+                        )
+                    });
+                if let Some(implib_name) = implib_name {
+                    let implib = out_filename.parent().map(|dir| dir.join(&implib_name));
+                    if let Some(implib) = implib {
+                        self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
+                    }
+                }
+            }
+        }
+    }
 }
 
 impl<'a> Linker for GccLinker<'a> {
     fn cmd(&mut self) -> &mut Command {
         &mut self.cmd
     }
+
+    fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
+        match output_kind {
+            LinkOutputKind::DynamicNoPicExe => {
+                if !self.is_ld {
+                    self.cmd.arg("-no-pie");
+                }
+            }
+            LinkOutputKind::DynamicPicExe => {
+                // `-pie` works for both gcc wrapper and ld.
+                self.cmd.arg("-pie");
+            }
+            LinkOutputKind::StaticNoPicExe => {
+                // `-static` works for both gcc wrapper and ld.
+                self.cmd.arg("-static");
+                if !self.is_ld {
+                    self.cmd.arg("-no-pie");
+                }
+            }
+            LinkOutputKind::StaticPicExe => {
+                if !self.is_ld {
+                    // Note that combination `-static -pie` doesn't work as expected
+                    // for the gcc wrapper, `-static` in that case suppresses `-pie`.
+                    self.cmd.arg("-static-pie");
+                } else {
+                    // `--no-dynamic-linker` and `-z text` are not strictly necessary for producing
+                    // a static pie, but currently passed because gcc and clang pass them.
+                    // The former suppresses the `INTERP` ELF header specifying dynamic linker,
+                    // which is otherwise implicitly injected by ld (but not lld).
+                    // The latter doesn't change anything, only ensures that everything is pic.
+                    self.cmd.args(&["-static", "-pie", "--no-dynamic-linker", "-z", "text"]);
+                }
+            }
+            LinkOutputKind::DynamicDylib => self.build_dylib(out_filename),
+            LinkOutputKind::StaticDylib => {
+                self.cmd.arg("-static");
+                self.build_dylib(out_filename);
+            }
+        }
+    }
+
     fn link_dylib(&mut self, lib: Symbol) {
         self.hint_dynamic();
         self.cmd.arg(format!("-l{}", lib));
@@ -262,14 +341,6 @@ impl<'a> Linker for GccLinker<'a> {
     fn add_object(&mut self, path: &Path) {
         self.cmd.arg(path);
     }
-    fn position_independent_executable(&mut self) {
-        self.cmd.arg("-pie");
-    }
-    fn no_position_independent_executable(&mut self) {
-        if !self.is_ld {
-            self.cmd.arg("-no-pie");
-        }
-    }
     fn full_relro(&mut self) {
         self.linker_arg("-zrelro");
         self.linker_arg("-znow");
@@ -280,9 +351,6 @@ impl<'a> Linker for GccLinker<'a> {
     fn no_relro(&mut self) {
         self.linker_arg("-znorelro");
     }
-    fn build_static_executable(&mut self) {
-        self.cmd.arg("-static");
-    }
 
     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
         self.hint_dynamic();
@@ -418,47 +486,6 @@ impl<'a> Linker for GccLinker<'a> {
         }
     }
 
-    fn build_dylib(&mut self, out_filename: &Path) {
-        // On mac we need to tell the linker to let this library be rpathed
-        if self.sess.target.target.options.is_like_osx {
-            self.cmd.arg("-dynamiclib");
-            self.linker_arg("-dylib");
-
-            // Note that the `osx_rpath_install_name` option here is a hack
-            // purely to support rustbuild right now, we should get a more
-            // principled solution at some point to force the compiler to pass
-            // the right `-Wl,-install_name` with an `@rpath` in it.
-            if self.sess.opts.cg.rpath || self.sess.opts.debugging_opts.osx_rpath_install_name {
-                self.linker_arg("-install_name");
-                let mut v = OsString::from("@rpath/");
-                v.push(out_filename.file_name().unwrap());
-                self.linker_arg(&v);
-            }
-        } else {
-            self.cmd.arg("-shared");
-            if self.sess.target.target.options.is_like_windows {
-                // The output filename already contains `dll_suffix` so
-                // the resulting import library will have a name in the
-                // form of libfoo.dll.a
-                let implib_name =
-                    out_filename.file_name().and_then(|file| file.to_str()).map(|file| {
-                        format!(
-                            "{}{}{}",
-                            self.sess.target.target.options.staticlib_prefix,
-                            file,
-                            self.sess.target.target.options.staticlib_suffix
-                        )
-                    });
-                if let Some(implib_name) = implib_name {
-                    let implib = out_filename.parent().map(|dir| dir.join(&implib_name));
-                    if let Some(implib) = implib {
-                        self.linker_arg(&format!("--out-implib,{}", (*implib).to_str().unwrap()));
-                    }
-                }
-            }
-        }
-    }
-
     fn export_symbols(&mut self, tmpdir: &Path, crate_type: CrateType) {
         // Symbol visibility in object files typically takes care of this.
         if crate_type == CrateType::Executable
@@ -582,6 +609,22 @@ impl<'a> Linker for MsvcLinker<'a> {
     fn cmd(&mut self) -> &mut Command {
         &mut self.cmd
     }
+
+    fn set_output_kind(&mut self, output_kind: LinkOutputKind, out_filename: &Path) {
+        match output_kind {
+            LinkOutputKind::DynamicNoPicExe
+            | LinkOutputKind::DynamicPicExe
+            | LinkOutputKind::StaticNoPicExe
+            | LinkOutputKind::StaticPicExe => {}
+            LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
+                self.cmd.arg("/DLL");
+                let mut arg: OsString = "/IMPLIB:".into();
+                arg.push(out_filename.with_extension("dll.lib"));
+                self.cmd.arg(arg);
+            }
+        }
+    }
+
     fn link_rlib(&mut self, lib: &Path) {
         self.cmd.arg(lib);
     }
@@ -589,17 +632,6 @@ impl<'a> Linker for MsvcLinker<'a> {
         self.cmd.arg(path);
     }
 
-    fn build_dylib(&mut self, out_filename: &Path) {
-        self.cmd.arg("/DLL");
-        let mut arg: OsString = "/IMPLIB:".into();
-        arg.push(out_filename.with_extension("dll.lib"));
-        self.cmd.arg(arg);
-    }
-
-    fn build_static_executable(&mut self) {
-        // noop
-    }
-
     fn gc_sections(&mut self, _keep_metadata: bool) {
         // MSVC's ICF (Identical COMDAT Folding) link optimization is
         // slow for Rust and thus we disable it by default when not in
@@ -632,14 +664,6 @@ impl<'a> Linker for MsvcLinker<'a> {
         self.cmd.arg(&format!("{}.lib", lib));
     }
 
-    fn position_independent_executable(&mut self) {
-        // noop
-    }
-
-    fn no_position_independent_executable(&mut self) {
-        // noop
-    }
-
     fn full_relro(&mut self) {
         // noop
     }
@@ -817,6 +841,9 @@ impl<'a> Linker for EmLinker<'a> {
     fn cmd(&mut self) -> &mut Command {
         &mut self.cmd
     }
+
+    fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
+
     fn include_path(&mut self, path: &Path) {
         self.cmd.arg("-L").arg(path);
     }
@@ -856,14 +883,6 @@ impl<'a> Linker for EmLinker<'a> {
         self.add_object(lib);
     }
 
-    fn position_independent_executable(&mut self) {
-        // noop
-    }
-
-    fn no_position_independent_executable(&mut self) {
-        // noop
-    }
-
     fn full_relro(&mut self) {
         // noop
     }
@@ -925,14 +944,6 @@ impl<'a> Linker for EmLinker<'a> {
         self.cmd.args(&["-s", "DEFAULT_LIBRARY_FUNCS_TO_INCLUDE=[]"]);
     }
 
-    fn build_dylib(&mut self, _out_filename: &Path) {
-        bug!("building dynamic library is unsupported on Emscripten")
-    }
-
-    fn build_static_executable(&mut self) {
-        // noop
-    }
-
     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
         let symbols = &self.info.exports[&crate_type];
 
@@ -1031,6 +1042,18 @@ impl<'a> Linker for WasmLd<'a> {
         &mut self.cmd
     }
 
+    fn set_output_kind(&mut self, output_kind: LinkOutputKind, _out_filename: &Path) {
+        match output_kind {
+            LinkOutputKind::DynamicNoPicExe
+            | LinkOutputKind::DynamicPicExe
+            | LinkOutputKind::StaticNoPicExe
+            | LinkOutputKind::StaticPicExe => {}
+            LinkOutputKind::DynamicDylib | LinkOutputKind::StaticDylib => {
+                self.cmd.arg("--no-entry");
+            }
+        }
+    }
+
     fn link_dylib(&mut self, lib: Symbol) {
         self.cmd.arg("-l").sym_arg(lib);
     }
@@ -1059,16 +1082,12 @@ impl<'a> Linker for WasmLd<'a> {
         self.cmd.arg(path);
     }
 
-    fn position_independent_executable(&mut self) {}
-
     fn full_relro(&mut self) {}
 
     fn partial_relro(&mut self) {}
 
     fn no_relro(&mut self) {}
 
-    fn build_static_executable(&mut self) {}
-
     fn link_rust_dylib(&mut self, lib: Symbol, _path: &Path) {
         self.cmd.arg("-l").sym_arg(lib);
     }
@@ -1124,10 +1143,6 @@ impl<'a> Linker for WasmLd<'a> {
 
     fn no_default_libraries(&mut self) {}
 
-    fn build_dylib(&mut self, _out_filename: &Path) {
-        self.cmd.arg("--no-entry");
-    }
-
     fn export_symbols(&mut self, _tmpdir: &Path, crate_type: CrateType) {
         for sym in self.info.exports[&crate_type].iter() {
             self.cmd.arg("--export").arg(&sym);
@@ -1143,8 +1158,6 @@ impl<'a> Linker for WasmLd<'a> {
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
-    fn no_position_independent_executable(&mut self) {}
-
     fn finalize(&mut self) {}
 
     // Not needed for now with LLD
@@ -1207,6 +1220,8 @@ impl<'a> Linker for PtxLinker<'a> {
         &mut self.cmd
     }
 
+    fn set_output_kind(&mut self, _output_kind: LinkOutputKind, _out_filename: &Path) {}
+
     fn link_rlib(&mut self, path: &Path) {
         self.cmd.arg("--rlib").arg(path);
     }
@@ -1273,16 +1288,12 @@ impl<'a> Linker for PtxLinker<'a> {
         panic!("frameworks not supported")
     }
 
-    fn position_independent_executable(&mut self) {}
-
     fn full_relro(&mut self) {}
 
     fn partial_relro(&mut self) {}
 
     fn no_relro(&mut self) {}
 
-    fn build_static_executable(&mut self) {}
-
     fn gc_sections(&mut self, _keep_metadata: bool) {}
 
     fn pgo_gen(&mut self) {}
@@ -1295,14 +1306,10 @@ impl<'a> Linker for PtxLinker<'a> {
         self.sess.warn("Windows Control Flow Guard is not supported by this linker.");
     }
 
-    fn build_dylib(&mut self, _out_filename: &Path) {}
-
     fn export_symbols(&mut self, _tmpdir: &Path, _crate_type: CrateType) {}
 
     fn subsystem(&mut self, _subsystem: &str) {}
 
-    fn no_position_independent_executable(&mut self) {}
-
     fn group_start(&mut self) {}
 
     fn group_end(&mut self) {}
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index e0c6fb451fc..6c18e753d79 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -909,13 +909,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 mir::InlineAsmOperand::SymFn { ref value } => {
                     let literal = self.monomorphize(&value.literal);
                     if let ty::FnDef(def_id, substs) = literal.ty.kind {
-                        let instance = ty::Instance::resolve(
+                        let instance = ty::Instance::resolve_for_fn_ptr(
                             bx.tcx(),
                             ty::ParamEnv::reveal_all(),
                             def_id,
                             substs,
                         )
-                        .unwrap()
                         .unwrap();
                         InlineAsmOperandRef::SymFn { instance }
                     } else {
diff --git a/src/librustc_data_structures/lib.rs b/src/librustc_data_structures/lib.rs
index 7ee60176dbe..0b2e7cda1b4 100644
--- a/src/librustc_data_structures/lib.rs
+++ b/src/librustc_data_structures/lib.rs
@@ -22,6 +22,7 @@
 #![feature(test)]
 #![feature(associated_type_bounds)]
 #![feature(thread_id_value)]
+#![feature(extend_one)]
 #![allow(rustc::default_hash_types)]
 
 #[macro_use]
diff --git a/src/librustc_data_structures/thin_vec.rs b/src/librustc_data_structures/thin_vec.rs
index 2befc0aa504..43002178eb9 100644
--- a/src/librustc_data_structures/thin_vec.rs
+++ b/src/librustc_data_structures/thin_vec.rs
@@ -53,6 +53,20 @@ impl<T> Extend<T> for ThinVec<T> {
             ThinVec(None) => *self = iter.into_iter().collect::<Vec<_>>().into(),
         }
     }
+
+    fn extend_one(&mut self, item: T) {
+        match *self {
+            ThinVec(Some(ref mut vec)) => vec.push(item),
+            ThinVec(None) => *self = vec![item].into(),
+        }
+    }
+
+    fn extend_reserve(&mut self, additional: usize) {
+        match *self {
+            ThinVec(Some(ref mut vec)) => vec.reserve(additional),
+            ThinVec(None) => *self = Vec::with_capacity(additional).into(),
+        }
+    }
 }
 
 impl<T: HashStable<CTX>, CTX> HashStable<CTX> for ThinVec<T> {
diff --git a/src/librustc_error_codes/error_codes/E0055.md b/src/librustc_error_codes/error_codes/E0055.md
index d5b863081a6..223ba400029 100644
--- a/src/librustc_error_codes/error_codes/E0055.md
+++ b/src/librustc_error_codes/error_codes/E0055.md
@@ -6,7 +6,7 @@ recursion limit (which can be set via the `recursion_limit` attribute).
 For a somewhat artificial example:
 
 ```compile_fail,E0055
-#![recursion_limit="5"]
+#![recursion_limit="4"]
 
 struct Foo;
 
diff --git a/src/librustc_error_codes/error_codes/E0619.md b/src/librustc_error_codes/error_codes/E0619.md
index 8727692c0a5..f516de43095 100644
--- a/src/librustc_error_codes/error_codes/E0619.md
+++ b/src/librustc_error_codes/error_codes/E0619.md
@@ -1,4 +1,5 @@
 #### Note: this error code is no longer emitted by the compiler.
+
 The type-checker needed to know the type of an expression, but that type had not
 yet been inferred.
 
diff --git a/src/librustc_errors/diagnostic.rs b/src/librustc_errors/diagnostic.rs
index 1cc5daafed1..cff83c3d5cd 100644
--- a/src/librustc_errors/diagnostic.rs
+++ b/src/librustc_errors/diagnostic.rs
@@ -193,9 +193,18 @@ impl Diagnostic {
         expected_extra: &dyn fmt::Display,
         found_extra: &dyn fmt::Display,
     ) -> &mut Self {
-        let expected_label = format!("expected {}", expected_label);
-
-        let found_label = format!("found {}", found_label);
+        let expected_label = expected_label.to_string();
+        let expected_label = if expected_label.is_empty() {
+            "expected".to_string()
+        } else {
+            format!("expected {}", expected_label)
+        };
+        let found_label = found_label.to_string();
+        let found_label = if found_label.is_empty() {
+            "found".to_string()
+        } else {
+            format!("found {}", found_label)
+        };
         let (found_padding, expected_padding) = if expected_label.len() > found_label.len() {
             (expected_label.len() - found_label.len(), 0)
         } else {
diff --git a/src/librustc_expand/base.rs b/src/librustc_expand/base.rs
index 649aac488fc..eeb30e2ced9 100644
--- a/src/librustc_expand/base.rs
+++ b/src/librustc_expand/base.rs
@@ -12,7 +12,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::{self, Lrc};
 use rustc_errors::{DiagnosticBuilder, ErrorReported};
 use rustc_parse::{self, parser, MACRO_ARGUMENTS};
-use rustc_session::parse::ParseSess;
+use rustc_session::{parse::ParseSess, Limit};
 use rustc_span::def_id::DefId;
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::{AstPass, ExpnData, ExpnId, ExpnKind};
@@ -941,7 +941,7 @@ pub struct ExpansionData {
 pub struct ExtCtxt<'a> {
     pub parse_sess: &'a ParseSess,
     pub ecfg: expand::ExpansionConfig<'a>,
-    pub reduced_recursion_limit: Option<usize>,
+    pub reduced_recursion_limit: Option<Limit>,
     pub root_path: PathBuf,
     pub resolver: &'a mut dyn Resolver,
     pub current_expansion: ExpansionData,
diff --git a/src/librustc_expand/expand.rs b/src/librustc_expand/expand.rs
index b505302f625..09ba64204c5 100644
--- a/src/librustc_expand/expand.rs
+++ b/src/librustc_expand/expand.rs
@@ -24,6 +24,7 @@ use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::UNUSED_DOC_COMMENTS;
 use rustc_session::lint::BuiltinLintDiagnostics;
 use rustc_session::parse::{feature_err, ParseSess};
+use rustc_session::Limit;
 use rustc_span::source_map::respan;
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::{FileName, Span, DUMMY_SP};
@@ -664,7 +665,7 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
     ) -> ExpandResult<AstFragment, Invocation> {
         let recursion_limit =
             self.cx.reduced_recursion_limit.unwrap_or(self.cx.ecfg.recursion_limit);
-        if self.cx.current_expansion.depth > recursion_limit {
+        if !recursion_limit.value_within_limit(self.cx.current_expansion.depth) {
             if self.cx.reduced_recursion_limit.is_none() {
                 self.error_recursion_limit_reached();
             }
@@ -1784,7 +1785,7 @@ impl<'a, 'b> MutVisitor for InvocationCollector<'a, 'b> {
 pub struct ExpansionConfig<'feat> {
     pub crate_name: String,
     pub features: Option<&'feat Features>,
-    pub recursion_limit: usize,
+    pub recursion_limit: Limit,
     pub trace_mac: bool,
     pub should_test: bool, // If false, strip `#[test]` nodes
     pub keep_macs: bool,
@@ -1795,7 +1796,7 @@ impl<'feat> ExpansionConfig<'feat> {
         ExpansionConfig {
             crate_name,
             features: None,
-            recursion_limit: 1024,
+            recursion_limit: Limit::new(1024),
             trace_mac: false,
             should_test: false,
             keep_macs: false,
diff --git a/src/librustc_feature/active.rs b/src/librustc_feature/active.rs
index 90b2380d864..fd35cb6c3f7 100644
--- a/src/librustc_feature/active.rs
+++ b/src/librustc_feature/active.rs
@@ -571,6 +571,9 @@ declare_features! (
     /// Allows the use of `#[ffi_const]` on foreign functions.
     (active, ffi_const, "1.45.0", Some(58328), None),
 
+    /// No longer treat an unsafe function as an unsafe block.
+    (active, unsafe_block_in_unsafe_fn, "1.45.0", Some(71668), None),
+
     // -------------------------------------------------------------------------
     // feature-group-end: actual feature gates
     // -------------------------------------------------------------------------
diff --git a/src/librustc_hir/definitions.rs b/src/librustc_hir/definitions.rs
index c7a0822d27d..c8971c2f9ad 100644
--- a/src/librustc_hir/definitions.rs
+++ b/src/librustc_hir/definitions.rs
@@ -333,17 +333,6 @@ impl Definitions {
     }
 
     #[inline]
-    pub fn as_local_node_id(&self, def_id: DefId) -> Option<ast::NodeId> {
-        if let Some(def_id) = def_id.as_local() {
-            let node_id = self.def_id_to_node_id[def_id];
-            if node_id != ast::DUMMY_NODE_ID {
-                return Some(node_id);
-            }
-        }
-        None
-    }
-
-    #[inline]
     pub fn as_local_hir_id(&self, def_id: LocalDefId) -> hir::HirId {
         self.local_def_id_to_hir_id(def_id)
     }
diff --git a/src/librustc_index/lib.rs b/src/librustc_index/lib.rs
index e8aa1a209e9..3effc416450 100644
--- a/src/librustc_index/lib.rs
+++ b/src/librustc_index/lib.rs
@@ -2,6 +2,7 @@
 #![feature(const_if_match)]
 #![feature(const_fn)]
 #![feature(const_panic)]
+#![feature(extend_one)]
 #![feature(unboxed_closures)]
 #![feature(test)]
 #![feature(fn_traits)]
diff --git a/src/librustc_index/vec.rs b/src/librustc_index/vec.rs
index 67dcea58cf8..4dde33283f5 100644
--- a/src/librustc_index/vec.rs
+++ b/src/librustc_index/vec.rs
@@ -736,6 +736,16 @@ impl<I: Idx, T> Extend<T> for IndexVec<I, T> {
     fn extend<J: IntoIterator<Item = T>>(&mut self, iter: J) {
         self.raw.extend(iter);
     }
+
+    #[inline]
+    fn extend_one(&mut self, item: T) {
+        self.raw.push(item);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.raw.reserve(additional);
+    }
 }
 
 impl<I: Idx, T> FromIterator<T> for IndexVec<I, T> {
diff --git a/src/librustc_infer/infer/error_reporting/mod.rs b/src/librustc_infer/infer/error_reporting/mod.rs
index cc479aa17ce..a59a91e3005 100644
--- a/src/librustc_infer/infer/error_reporting/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/mod.rs
@@ -60,7 +60,7 @@ use rustc_errors::{pluralize, struct_span_err};
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticStyledString};
 use rustc_hir as hir;
 use rustc_hir::def_id::DefId;
-use rustc_hir::Node;
+use rustc_hir::{Item, ItemKind, Node};
 use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::{
     self,
@@ -987,12 +987,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
 
         fn push_ty_ref<'tcx>(
-            r: &ty::Region<'tcx>,
+            region: &ty::Region<'tcx>,
             ty: Ty<'tcx>,
             mutbl: hir::Mutability,
             s: &mut DiagnosticStyledString,
         ) {
-            let mut r = r.to_string();
+            let mut r = region.to_string();
             if r == "'_" {
                 r.clear();
             } else {
@@ -1682,49 +1682,92 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         bound_kind: GenericKind<'tcx>,
         sub: Region<'tcx>,
     ) -> DiagnosticBuilder<'a> {
+        let hir = &self.tcx.hir();
         // Attempt to obtain the span of the parameter so we can
         // suggest adding an explicit lifetime bound to it.
-        let type_param_span = match (self.in_progress_tables, bound_kind) {
-            (Some(ref table), GenericKind::Param(ref param)) => {
-                let table_owner = table.borrow().hir_owner;
-                table_owner.and_then(|table_owner| {
-                    let generics = self.tcx.generics_of(table_owner.to_def_id());
-                    // Account for the case where `param` corresponds to `Self`,
-                    // which doesn't have the expected type argument.
-                    if !(generics.has_self && param.index == 0) {
-                        let type_param = generics.type_param(param, self.tcx);
-                        let hir = &self.tcx.hir();
-                        type_param.def_id.as_local().map(|def_id| {
-                            // Get the `hir::Param` to verify whether it already has any bounds.
-                            // We do this to avoid suggesting code that ends up as `T: 'a'b`,
-                            // instead we suggest `T: 'a + 'b` in that case.
-                            let id = hir.as_local_hir_id(def_id);
-                            let mut has_bounds = false;
-                            if let Node::GenericParam(param) = hir.get(id) {
-                                has_bounds = !param.bounds.is_empty();
-                            }
-                            let sp = hir.span(id);
-                            // `sp` only covers `T`, change it so that it covers
-                            // `T:` when appropriate
-                            let is_impl_trait = bound_kind.to_string().starts_with("impl ");
-                            let sp = if has_bounds && !is_impl_trait {
-                                sp.to(self
-                                    .tcx
-                                    .sess
-                                    .source_map()
-                                    .next_point(self.tcx.sess.source_map().next_point(sp)))
-                            } else {
-                                sp
-                            };
-                            (sp, has_bounds, is_impl_trait)
-                        })
+        let generics =
+            self.in_progress_tables.and_then(|table| table.borrow().hir_owner).map(|table_owner| {
+                let hir_id = hir.as_local_hir_id(table_owner);
+                let parent_id = hir.get_parent_item(hir_id);
+                (
+                    // Parent item could be a `mod`, so we check the HIR before calling:
+                    if let Some(Node::Item(Item {
+                        kind: ItemKind::Trait(..) | ItemKind::Impl { .. },
+                        ..
+                    })) = hir.find(parent_id)
+                    {
+                        Some(self.tcx.generics_of(hir.local_def_id(parent_id).to_def_id()))
                     } else {
                         None
-                    }
-                })
+                    },
+                    self.tcx.generics_of(table_owner.to_def_id()),
+                )
+            });
+        let type_param_span = match (generics, bound_kind) {
+            (Some((_, ref generics)), GenericKind::Param(ref param)) => {
+                // Account for the case where `param` corresponds to `Self`,
+                // which doesn't have the expected type argument.
+                if !(generics.has_self && param.index == 0) {
+                    let type_param = generics.type_param(param, self.tcx);
+                    type_param.def_id.as_local().map(|def_id| {
+                        // Get the `hir::Param` to verify whether it already has any bounds.
+                        // We do this to avoid suggesting code that ends up as `T: 'a'b`,
+                        // instead we suggest `T: 'a + 'b` in that case.
+                        let id = hir.as_local_hir_id(def_id);
+                        let mut has_bounds = false;
+                        if let Node::GenericParam(param) = hir.get(id) {
+                            has_bounds = !param.bounds.is_empty();
+                        }
+                        let sp = hir.span(id);
+                        // `sp` only covers `T`, change it so that it covers
+                        // `T:` when appropriate
+                        let is_impl_trait = bound_kind.to_string().starts_with("impl ");
+                        let sp = if has_bounds && !is_impl_trait {
+                            sp.to(self
+                                .tcx
+                                .sess
+                                .source_map()
+                                .next_point(self.tcx.sess.source_map().next_point(sp)))
+                        } else {
+                            sp
+                        };
+                        (sp, has_bounds, is_impl_trait)
+                    })
+                } else {
+                    None
+                }
             }
             _ => None,
         };
+        let new_lt = generics
+            .as_ref()
+            .and_then(|(parent_g, g)| {
+                let possible: Vec<_> = (b'a'..=b'z').map(|c| format!("'{}", c as char)).collect();
+                let mut lts_names = g
+                    .params
+                    .iter()
+                    .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
+                    .map(|p| p.name.as_str())
+                    .collect::<Vec<_>>();
+                if let Some(g) = parent_g {
+                    lts_names.extend(
+                        g.params
+                            .iter()
+                            .filter(|p| matches!(p.kind, ty::GenericParamDefKind::Lifetime))
+                            .map(|p| p.name.as_str()),
+                    );
+                }
+                let lts = lts_names.iter().map(|s| -> &str { &*s }).collect::<Vec<_>>();
+                possible.into_iter().find(|candidate| !lts.contains(&candidate.as_str()))
+            })
+            .unwrap_or("'lt".to_string());
+        let add_lt_sugg = generics
+            .as_ref()
+            .and_then(|(_, g)| g.params.first())
+            .and_then(|param| param.def_id.as_local())
+            .map(|def_id| {
+                (hir.span(hir.as_local_hir_id(def_id)).shrink_to_lo(), format!("{}, ", new_lt))
+            });
 
         let labeled_user_string = match bound_kind {
             GenericKind::Param(ref p) => format!("the parameter type `{}`", p),
@@ -1781,6 +1824,29 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             }
         }
 
+        let new_binding_suggestion =
+            |err: &mut DiagnosticBuilder<'tcx>,
+             type_param_span: Option<(Span, bool, bool)>,
+             bound_kind: GenericKind<'tcx>| {
+                let msg = "consider introducing an explicit lifetime bound";
+                if let Some((sp, has_lifetimes, is_impl_trait)) = type_param_span {
+                    let suggestion = if is_impl_trait {
+                        (sp.shrink_to_hi(), format!(" + {}", new_lt))
+                    } else {
+                        let tail = if has_lifetimes { " +" } else { "" };
+                        (sp, format!("{}: {}{}", bound_kind, new_lt, tail))
+                    };
+                    let mut sugg =
+                        vec![suggestion, (span.shrink_to_hi(), format!(" + {}", new_lt))];
+                    if let Some(lt) = add_lt_sugg {
+                        sugg.push(lt);
+                        sugg.rotate_right(1);
+                    }
+                    // `MaybeIncorrect` due to issue #41966.
+                    err.multipart_suggestion(msg, sugg, Applicability::MaybeIncorrect);
+                }
+            };
+
         let mut err = match *sub {
             ty::ReEarlyBound(ty::EarlyBoundRegion { name, .. })
             | ty::ReFree(ty::FreeRegion { bound_region: ty::BrNamed(_, name), .. }) => {
@@ -1822,10 +1888,6 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     "{} may not live long enough",
                     labeled_user_string
                 );
-                err.help(&format!(
-                    "consider adding an explicit lifetime bound for `{}`",
-                    bound_kind
-                ));
                 note_and_explain_region(
                     self.tcx,
                     &mut err,
@@ -1833,6 +1895,21 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     sub,
                     "...",
                 );
+                if let Some(infer::RelateParamBound(_, t)) = origin {
+                    let t = self.resolve_vars_if_possible(&t);
+                    match t.kind {
+                        // We've got:
+                        // fn get_later<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+                        // suggest:
+                        // fn get_later<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+                        ty::Closure(_, _substs) | ty::Opaque(_, _substs) => {
+                            new_binding_suggestion(&mut err, type_param_span, bound_kind);
+                        }
+                        _ => {
+                            binding_suggestion(&mut err, type_param_span, bound_kind, new_lt);
+                        }
+                    }
+                }
                 err
             }
         };
@@ -1861,14 +1938,15 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             "...",
         );
 
+        debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
+        debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
+        debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
+        debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
+        debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
+
         if let (&infer::Subtype(ref sup_trace), &infer::Subtype(ref sub_trace)) =
             (&sup_origin, &sub_origin)
         {
-            debug!("report_sub_sup_conflict: var_origin={:?}", var_origin);
-            debug!("report_sub_sup_conflict: sub_region={:?}", sub_region);
-            debug!("report_sub_sup_conflict: sub_origin={:?}", sub_origin);
-            debug!("report_sub_sup_conflict: sup_region={:?}", sup_region);
-            debug!("report_sub_sup_conflict: sup_origin={:?}", sup_origin);
             debug!("report_sub_sup_conflict: sup_trace={:?}", sup_trace);
             debug!("report_sub_sup_conflict: sub_trace={:?}", sub_trace);
             debug!("report_sub_sup_conflict: sup_trace.values={:?}", sup_trace.values);
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
index d206a30d526..7ab18e54f7e 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/different_lifetimes.rs
@@ -121,16 +121,14 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             (Some(ret_span), _) => (
                 ty_sub.span,
                 ret_span,
-                "this parameter and the return type are declared \
-                 with different lifetimes..."
+                "this parameter and the return type are declared with different lifetimes..."
                     .to_owned(),
                 format!("...but data{} is returned here", span_label_var1),
             ),
             (_, Some(ret_span)) => (
                 ty_sup.span,
                 ret_span,
-                "this parameter and the return type are declared \
-                 with different lifetimes..."
+                "this parameter and the return type are declared with different lifetimes..."
                     .to_owned(),
                 format!("...but data{} is returned here", span_label_var1),
             ),
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
index efe52689550..cc8f1816bc3 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/mod.rs
@@ -55,9 +55,9 @@ impl<'cx, 'tcx> NiceRegionError<'cx, 'tcx> {
                 diag.emit();
                 ErrorReported
             })
+            .or_else(|| self.try_report_impl_not_conforming_to_trait())
             .or_else(|| self.try_report_anon_anon_conflict())
             .or_else(|| self.try_report_static_impl_trait())
-            .or_else(|| self.try_report_impl_not_conforming_to_trait())
     }
 
     pub fn regions(&self) -> Option<(Span, ty::Region<'tcx>, ty::Region<'tcx>)> {
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
index b85a4cae2e4..acaf4746992 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/named_anon_conflict.rs
@@ -21,8 +21,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         // where the anonymous region appears (there must always be one; we
         // only introduced anonymous regions in parameters) as well as a
         // version new_ty of its type where the anonymous region is replaced
-        // with the named one.//scope_def_id
-        let (named, anon, anon_param_info, region_info) = if self.is_named_region(sub)
+        // with the named one.
+        let (named, anon, anon_param_info, region_info) = if sub.has_name()
             && self.tcx().is_suitable_region(sup).is_some()
             && self.find_param_with_region(sup, sub).is_some()
         {
@@ -32,7 +32,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 self.find_param_with_region(sup, sub).unwrap(),
                 self.tcx().is_suitable_region(sup).unwrap(),
             )
-        } else if self.is_named_region(sup)
+        } else if sup.has_name()
             && self.tcx().is_suitable_region(sub).is_some()
             && self.find_param_with_region(sub, sup).is_some()
         {
@@ -74,15 +74,21 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         }
 
         if let Some((_, fndecl)) = self.find_anon_type(anon, &br) {
-            if self.is_return_type_anon(scope_def_id, br, fndecl).is_some()
-                || self.is_self_anon(is_first, scope_def_id)
-            {
+            let is_self_anon = self.is_self_anon(is_first, scope_def_id);
+            if is_self_anon {
                 return None;
             }
+
             if let FnRetTy::Return(ty) = &fndecl.output {
-                if let (TyKind::Def(_, _), ty::ReStatic) = (&ty.kind, sub) {
-                    // This is an impl Trait return that evaluates de need of 'static.
-                    // We handle this case better in `static_impl_trait`.
+                let mut v = ty::TraitObjectVisitor(vec![]);
+                rustc_hir::intravisit::walk_ty(&mut v, ty);
+
+                debug!("try_report_named_anon_conflict: ret ty {:?}", ty);
+                if sub == &ty::ReStatic && (matches!(ty.kind, TyKind::Def(_, _)) || v.0.len() == 1)
+                {
+                    debug!("try_report_named_anon_conflict: impl Trait + 'static");
+                    // This is an `impl Trait` or `dyn Trait` return that evaluates de need of
+                    // `'static`. We handle this case better in `static_impl_trait`.
                     return None;
                 }
             }
@@ -114,17 +120,4 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
 
         Some(diag)
     }
-
-    // This method returns whether the given Region is Named
-    pub(super) fn is_named_region(&self, region: ty::Region<'tcx>) -> bool {
-        match *region {
-            ty::ReStatic => true,
-            ty::ReFree(ref free_region) => match free_region.bound_region {
-                ty::BrNamed(..) => true,
-                _ => false,
-            },
-            ty::ReEarlyBound(ebr) => ebr.has_name(),
-            _ => false,
-        }
-    }
 }
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 7f3ec852e41..f4c86ddae60 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
@@ -4,7 +4,7 @@ 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_middle::ty::{BoundRegion, FreeRegion, RegionKind};
+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.
@@ -20,48 +20,59 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
             ) = error.clone()
             {
                 let anon_reg_sup = self.tcx().is_suitable_region(sup_r)?;
-                let return_ty = self.tcx().return_type_impl_trait(anon_reg_sup.def_id);
-                if sub_r == &RegionKind::ReStatic && return_ty.is_some() {
+                let (fn_return_span, is_dyn) =
+                    self.tcx().return_type_impl_or_dyn_trait(anon_reg_sup.def_id)?;
+                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");
-                    err.span_label(
-                        return_sp,
-                        "this return type evaluates to the `'static` lifetime...",
-                    );
-                    err.span_label(sup_origin.span(), "...but this borrow...");
+                    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, lt_sp_opt) = msg_span_from_free_region(self.tcx(), sup_r);
-                    if let Some(lifetime_sp) = lt_sp_opt {
-                        err.span_note(lifetime_sp, &format!("...can't outlive {}", lifetime));
-                    }
-
-                    let lifetime_name = match sup_r {
-                        RegionKind::ReFree(FreeRegion {
-                            bound_region: BoundRegion::BrNamed(_, ref name),
-                            ..
-                        }) => name.to_string(),
-                        _ => "'_".to_owned(),
-                    };
-                    let fn_return_span = return_ty.unwrap().1;
-                    if let Ok(snippet) =
-                        self.tcx().sess.source_map().span_to_snippet(fn_return_span)
+                    // We try to make the output have fewer overlapping spans if possible.
+                    if (sp == sup_origin.span() || !return_sp.overlaps(sup_origin.span()))
+                        && sup_origin.span() != return_sp
                     {
-                        // only apply this suggestion onto functions with
-                        // explicit non-desugar'able return.
-                        if fn_return_span.desugaring_kind().is_none() {
-                            err.span_suggestion(
-                                fn_return_span,
-                                &format!(
-                                    "you can add a bound to the return type to make it last \
-                                 less than `'static` and match {}",
-                                    lifetime,
-                                ),
-                                format!("{} + {}", snippet, lifetime_name),
-                                Applicability::Unspecified,
-                            );
+                        // FIXME: account for `async fn` like in `async-await/issues/issue-62097.rs`
+
+                        // 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");
+                        } else {
+                            err.span_label(return_sp, "...is required to be `'static` by this...");
+                            err.span_label(sup_origin.span(), "...and is captured here");
                         }
+                    } else {
+                        err.span_label(
+                            return_sp,
+                            "...is captured and required to be `'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,
+                        );
+                        // 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,
+                        );
                     }
                     err.emit();
                     return Some(ErrorReported);
diff --git a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
index 695f3e47fb5..5f14f799fc7 100644
--- a/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
+++ b/src/librustc_infer/infer/error_reporting/nice_region_error/trait_impl_difference.rs
@@ -2,11 +2,16 @@
 
 use crate::infer::error_reporting::nice_region_error::NiceRegionError;
 use crate::infer::lexical_region_resolve::RegionResolutionError;
-use crate::infer::{Subtype, ValuePairs};
+use crate::infer::{Subtype, TyCtxtInferExt, ValuePairs};
 use crate::traits::ObligationCauseCode::CompareImplMethodObligation;
 use rustc_errors::ErrorReported;
-use rustc_middle::ty::Ty;
-use rustc_span::Span;
+use rustc_hir as hir;
+use rustc_hir::def::Res;
+use rustc_hir::def_id::DefId;
+use rustc_hir::intravisit::Visitor;
+use rustc_middle::ty::error::ExpectedFound;
+use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::{MultiSpan, Span};
 
 impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
     /// Print the error message for lifetime errors when the `impl` doesn't conform to the `trait`.
@@ -36,7 +41,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                                 var_origin.span(),
                                 sub_expected_found.expected,
                                 sub_expected_found.found,
-                                self.tcx().def_span(*trait_item_def_id),
+                                *trait_item_def_id,
                             );
                             return Some(ErrorReported);
                         }
@@ -47,14 +52,100 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         None
     }
 
-    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, impl_sp: Span) {
+    fn emit_err(&self, sp: Span, expected: Ty<'tcx>, found: Ty<'tcx>, trait_def_id: DefId) {
+        let tcx = self.tcx();
+        let trait_sp = self.tcx().def_span(trait_def_id);
         let mut err = self
             .tcx()
             .sess
             .struct_span_err(sp, "`impl` item signature doesn't match `trait` item signature");
-        err.note(&format!("expected `{:?}`\n   found `{:?}`", expected, found));
-        err.span_label(sp, &format!("found {:?}", found));
-        err.span_label(impl_sp, &format!("expected {:?}", expected));
+        err.span_label(sp, &format!("found `{:?}`", found));
+        err.span_label(trait_sp, &format!("expected `{:?}`", expected));
+
+        // Get the span of all the used type parameters in the method.
+        let assoc_item = self.tcx().associated_item(trait_def_id);
+        let mut visitor = TypeParamSpanVisitor { tcx: self.tcx(), types: vec![] };
+        match assoc_item.kind {
+            ty::AssocKind::Fn => {
+                let hir = self.tcx().hir();
+                if let Some(hir_id) = assoc_item.def_id.as_local().map(|id| hir.as_local_hir_id(id))
+                {
+                    if let Some(decl) = hir.fn_decl_by_hir_id(hir_id) {
+                        visitor.visit_fn_decl(decl);
+                    }
+                }
+            }
+            _ => {}
+        }
+        let mut type_param_span: MultiSpan =
+            visitor.types.iter().cloned().collect::<Vec<_>>().into();
+        for &span in &visitor.types {
+            type_param_span.push_span_label(
+                span,
+                "consider borrowing this type parameter in the trait".to_string(),
+            );
+        }
+
+        if let Some((expected, found)) = tcx
+            .infer_ctxt()
+            .enter(|infcx| infcx.expected_found_str_ty(&ExpectedFound { expected, found }))
+        {
+            // Highlighted the differences when showing the "expected/found" note.
+            err.note_expected_found(&"", expected, &"", found);
+        } else {
+            // This fallback shouldn't be necessary, but let's keep it in just in case.
+            err.note(&format!("expected `{:?}`\n   found `{:?}`", expected, found));
+        }
+        err.span_help(
+            type_param_span,
+            "the lifetime requirements from the `impl` do not correspond to the requirements in \
+             the `trait`",
+        );
+        if visitor.types.is_empty() {
+            err.help(
+                "verify the lifetime relationships in the `trait` and `impl` between the `self` \
+                 argument, the other inputs and its output",
+            );
+        }
         err.emit();
     }
 }
+
+struct TypeParamSpanVisitor<'tcx> {
+    tcx: TyCtxt<'tcx>,
+    types: Vec<Span>,
+}
+
+impl Visitor<'tcx> for TypeParamSpanVisitor<'tcx> {
+    type Map = rustc_middle::hir::map::Map<'tcx>;
+
+    fn nested_visit_map(&mut self) -> hir::intravisit::NestedVisitorMap<Self::Map> {
+        hir::intravisit::NestedVisitorMap::OnlyBodies(self.tcx.hir())
+    }
+
+    fn visit_ty(&mut self, arg: &'tcx hir::Ty<'tcx>) {
+        match arg.kind {
+            hir::TyKind::Rptr(_, ref mut_ty) => {
+                // We don't want to suggest looking into borrowing `&T` or `&Self`.
+                hir::intravisit::walk_ty(self, mut_ty.ty);
+                return;
+            }
+            hir::TyKind::Path(hir::QPath::Resolved(None, path)) => match &path.segments {
+                [segment]
+                    if segment
+                        .res
+                        .map(|res| match res {
+                            Res::SelfTy(_, _) | Res::Def(hir::def::DefKind::TyParam, _) => true,
+                            _ => false,
+                        })
+                        .unwrap_or(false) =>
+                {
+                    self.types.push(path.span);
+                }
+                _ => {}
+            },
+            _ => {}
+        }
+        hir::intravisit::walk_ty(self, arg);
+    }
+}
diff --git a/src/librustc_infer/infer/error_reporting/note.rs b/src/librustc_infer/infer/error_reporting/note.rs
index 8fbb89da5af..9ac27030ade 100644
--- a/src/librustc_infer/infer/error_reporting/note.rs
+++ b/src/librustc_infer/infer/error_reporting/note.rs
@@ -10,10 +10,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         err: &mut DiagnosticBuilder<'_>,
         origin: &SubregionOrigin<'tcx>,
     ) {
+        let mut label_or_note = |span, msg| {
+            let sub_count = err.children.iter().filter(|d| d.span.is_dummy()).count();
+            let expanded_sub_count = err.children.iter().filter(|d| !d.span.is_dummy()).count();
+            let span_is_primary = err.span.primary_spans().iter().all(|&sp| sp == span);
+            if span_is_primary && sub_count == 0 && expanded_sub_count == 0 {
+                err.span_label(span, msg);
+            } else if span_is_primary && expanded_sub_count == 0 {
+                err.note(msg);
+            } else {
+                err.span_note(span, msg);
+            }
+        };
         match *origin {
             infer::Subtype(ref trace) => {
                 if let Some((expected, found)) = self.values_str(&trace.values) {
-                    err.span_note(
+                    label_or_note(
                         trace.cause.span,
                         &format!("...so that the {}", trace.cause.as_requirement_str()),
                     );
@@ -24,27 +36,27 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     // handling of region checking when type errors are present is
                     // *terrible*.
 
-                    err.span_note(
+                    label_or_note(
                         trace.cause.span,
                         &format!("...so that {}", trace.cause.as_requirement_str()),
                     );
                 }
             }
             infer::Reborrow(span) => {
-                err.span_note(span, "...so that reference does not outlive borrowed content");
+                label_or_note(span, "...so that reference does not outlive borrowed content");
             }
             infer::ReborrowUpvar(span, ref upvar_id) => {
                 let var_name = self.tcx.hir().name(upvar_id.var_path.hir_id);
-                err.span_note(span, &format!("...so that closure can access `{}`", var_name));
+                label_or_note(span, &format!("...so that closure can access `{}`", var_name));
             }
             infer::RelateObjectBound(span) => {
-                err.span_note(span, "...so that it can be closed over into an object");
+                label_or_note(span, "...so that it can be closed over into an object");
             }
             infer::CallReturn(span) => {
-                err.span_note(span, "...so that return value is valid for the call");
+                label_or_note(span, "...so that return value is valid for the call");
             }
             infer::DataBorrowed(ty, span) => {
-                err.span_note(
+                label_or_note(
                     span,
                     &format!(
                         "...so that the type `{}` is not borrowed for too long",
@@ -53,36 +65,33 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 );
             }
             infer::ReferenceOutlivesReferent(ty, span) => {
-                err.span_note(
+                label_or_note(
                     span,
                     &format!(
-                        "...so that the reference type `{}` does not outlive the \
-                                        data it points at",
+                        "...so that the reference type `{}` does not outlive the data it points at",
                         self.ty_to_string(ty)
                     ),
                 );
             }
             infer::RelateParamBound(span, t) => {
-                err.span_note(
+                label_or_note(
                     span,
                     &format!(
-                        "...so that the type `{}` will meet its required \
-                                        lifetime bounds",
+                        "...so that the type `{}` will meet its required lifetime bounds",
                         self.ty_to_string(t)
                     ),
                 );
             }
             infer::RelateRegionParamBound(span) => {
-                err.span_note(
+                label_or_note(
                     span,
                     "...so that the declared lifetime parameter bounds are satisfied",
                 );
             }
             infer::CompareImplMethodObligation { span, .. } => {
-                err.span_note(
+                label_or_note(
                     span,
-                    "...so that the definition in impl matches the definition from the \
-                               trait",
+                    "...so that the definition in impl matches the definition from the trait",
                 );
             }
         }
@@ -113,8 +122,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     span,
                     E0312,
-                    "lifetime of reference outlives lifetime of \
-                                                borrowed content..."
+                    "lifetime of reference outlives lifetime of borrowed content..."
                 );
                 note_and_explain_region(
                     self.tcx,
@@ -138,8 +146,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     span,
                     E0313,
-                    "lifetime of borrowed pointer outlives lifetime \
-                                                of captured variable `{}`...",
+                    "lifetime of borrowed pointer outlives lifetime of captured variable `{}`...",
                     var_name
                 );
                 note_and_explain_region(
@@ -163,8 +170,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     span,
                     E0476,
-                    "lifetime of the source pointer does not outlive \
-                                                lifetime bound of the object type"
+                    "lifetime of the source pointer does not outlive lifetime bound of the \
+                     object type"
                 );
                 note_and_explain_region(self.tcx, &mut err, "object type is valid for ", sub, "");
                 note_and_explain_region(
@@ -181,8 +188,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     span,
                     E0477,
-                    "the type `{}` does not fulfill the required \
-                                                lifetime",
+                    "the type `{}` does not fulfill the required lifetime",
                     self.ty_to_string(ty)
                 );
                 match *sub {
@@ -217,8 +223,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                     self.tcx.sess,
                     span,
                     E0482,
-                    "lifetime of return value does not outlive the \
-                                                function call"
+                    "lifetime of return value does not outlive the function call"
                 );
                 note_and_explain_region(
                     self.tcx,
diff --git a/src/librustc_infer/lib.rs b/src/librustc_infer/lib.rs
index 28d42cea6d3..ed04ee02b72 100644
--- a/src/librustc_infer/lib.rs
+++ b/src/librustc_infer/lib.rs
@@ -16,6 +16,7 @@
 #![feature(bool_to_option)]
 #![feature(box_patterns)]
 #![feature(box_syntax)]
+#![feature(extend_one)]
 #![feature(never_type)]
 #![feature(or_patterns)]
 #![feature(range_is_empty)]
diff --git a/src/librustc_infer/traits/util.rs b/src/librustc_infer/traits/util.rs
index 17b7b4e680f..8081cac0067 100644
--- a/src/librustc_infer/traits/util.rs
+++ b/src/librustc_infer/traits/util.rs
@@ -81,6 +81,14 @@ impl Extend<ty::Predicate<'tcx>> for PredicateSet<'tcx> {
             self.insert(pred);
         }
     }
+
+    fn extend_one(&mut self, pred: ty::Predicate<'tcx>) {
+        self.insert(pred);
+    }
+
+    fn extend_reserve(&mut self, additional: usize) {
+        Extend::<ty::Predicate<'tcx>>::extend_reserve(&mut self.set, additional);
+    }
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/src/librustc_interface/passes.rs b/src/librustc_interface/passes.rs
index 214701db724..c06fd91133b 100644
--- a/src/librustc_interface/passes.rs
+++ b/src/librustc_interface/passes.rs
@@ -838,7 +838,7 @@ fn analysis(tcx: TyCtxt<'_>, cnum: CrateNum) -> Result<()> {
 
     sess.time("MIR_effect_checking", || {
         for def_id in tcx.body_owners() {
-            mir::transform::check_unsafety::check_unsafety(tcx, def_id.to_def_id())
+            mir::transform::check_unsafety::check_unsafety(tcx, def_id)
         }
     });
 
diff --git a/src/librustc_lint/levels.rs b/src/librustc_lint/levels.rs
index 274e57ae64c..3d2ddf12a0a 100644
--- a/src/librustc_lint/levels.rs
+++ b/src/librustc_lint/levels.rs
@@ -14,11 +14,11 @@ use rustc_middle::lint::LintDiagnosticBuilder;
 use rustc_middle::lint::{struct_lint_level, LintLevelMap, LintLevelSets, LintSet, LintSource};
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::lint::{builtin, Level, Lint};
+use rustc_session::lint::{builtin, Level, Lint, LintId};
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
-use rustc_span::source_map::MultiSpan;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{source_map::MultiSpan, Span, DUMMY_SP};
 
 use std::cmp;
 
@@ -80,11 +80,13 @@ impl<'s> LintLevelsBuilder<'s> {
             let level = cmp::min(level, self.sets.lint_cap);
 
             let lint_flag_val = Symbol::intern(lint_name);
+
             let ids = match store.find_lints(&lint_name) {
                 Ok(ids) => ids,
                 Err(_) => continue, // errors handled in check_lint_name_cmdline above
             };
             for id in ids {
+                self.check_gated_lint(id, DUMMY_SP);
                 let src = LintSource::CommandLine(lint_flag_val);
                 specs.insert(id, (level, src));
             }
@@ -213,6 +215,7 @@ impl<'s> LintLevelsBuilder<'s> {
                     CheckLintNameResult::Ok(ids) => {
                         let src = LintSource::Node(name, li.span(), reason);
                         for id in ids {
+                            self.check_gated_lint(*id, attr.span);
                             specs.insert(*id, (level, src));
                         }
                     }
@@ -383,6 +386,20 @@ impl<'s> LintLevelsBuilder<'s> {
         BuilderPush { prev, changed: prev != self.cur }
     }
 
+    fn check_gated_lint(&self, id: LintId, span: Span) {
+        if id == LintId::of(builtin::UNSAFE_OP_IN_UNSAFE_FN)
+            && !self.sess.features_untracked().unsafe_block_in_unsafe_fn
+        {
+            feature_err(
+                &self.sess.parse_sess,
+                sym::unsafe_block_in_unsafe_fn,
+                span,
+                "the `unsafe_op_in_unsafe_fn` lint is unstable",
+            )
+            .emit();
+        }
+    }
+
     /// Called after `push` when the scope of a set of attributes are exited.
     pub fn pop(&mut self, push: BuilderPush) {
         self.cur = push.prev;
diff --git a/src/librustc_middle/middle/limits.rs b/src/librustc_middle/middle/limits.rs
index 19c056925cf..85198482bd3 100644
--- a/src/librustc_middle/middle/limits.rs
+++ b/src/librustc_middle/middle/limits.rs
@@ -8,7 +8,7 @@
 use crate::bug;
 use rustc_ast::ast;
 use rustc_data_structures::sync::OnceCell;
-use rustc_session::Session;
+use rustc_session::{Limit, Session};
 use rustc_span::symbol::{sym, Symbol};
 
 use std::num::IntErrorKind;
@@ -22,7 +22,7 @@ pub fn update_limits(sess: &Session, krate: &ast::Crate) {
 fn update_limit(
     sess: &Session,
     krate: &ast::Crate,
-    limit: &OnceCell<usize>,
+    limit: &OnceCell<Limit>,
     name: Symbol,
     default: usize,
 ) {
@@ -34,7 +34,7 @@ fn update_limit(
         if let Some(s) = attr.value_str() {
             match s.as_str().parse() {
                 Ok(n) => {
-                    limit.set(n).unwrap();
+                    limit.set(Limit::new(n)).unwrap();
                     return;
                 }
                 Err(e) => {
@@ -62,5 +62,5 @@ fn update_limit(
             }
         }
     }
-    limit.set(default).unwrap();
+    limit.set(Limit::new(default)).unwrap();
 }
diff --git a/src/librustc_middle/mir/interpret/error.rs b/src/librustc_middle/mir/interpret/error.rs
index d32a1473449..fc588e049d7 100644
--- a/src/librustc_middle/mir/interpret/error.rs
+++ b/src/librustc_middle/mir/interpret/error.rs
@@ -1,4 +1,4 @@
-use super::{AllocId, Pointer, RawConst, ScalarMaybeUninit};
+use super::{AllocId, Pointer, RawConst, Scalar};
 
 use crate::mir::interpret::ConstValue;
 use crate::ty::layout::LayoutError;
@@ -391,7 +391,7 @@ pub enum UndefinedBehaviorInfo<'tcx> {
     /// Using a non-character `u32` as character.
     InvalidChar(u32),
     /// An enum discriminant was set to a value which was outside the range of valid values.
-    InvalidDiscriminant(ScalarMaybeUninit),
+    InvalidDiscriminant(Scalar),
     /// Using a pointer-not-to-a-function as function pointer.
     InvalidFunctionPointer(Pointer),
     /// Using a string that is not valid UTF-8,
diff --git a/src/librustc_middle/mir/interpret/mod.rs b/src/librustc_middle/mir/interpret/mod.rs
index d9e52af8900..061bc9750e1 100644
--- a/src/librustc_middle/mir/interpret/mod.rs
+++ b/src/librustc_middle/mir/interpret/mod.rs
@@ -598,3 +598,12 @@ pub fn truncate(value: u128, size: Size) -> u128 {
     // Truncate (shift left to drop out leftover values, shift right to fill with zeroes).
     (value << shift) >> shift
 }
+
+/// Computes the unsigned absolute value without wrapping or panicking.
+#[inline]
+pub fn uabs(value: i64) -> u64 {
+    // The only tricky part here is if value == i64::MIN. In that case,
+    // wrapping_abs() returns i64::MIN == -2^63. Casting this value to a u64
+    // gives 2^63, the correct value.
+    value.wrapping_abs() as u64
+}
diff --git a/src/librustc_middle/mir/interpret/pointer.rs b/src/librustc_middle/mir/interpret/pointer.rs
index 70cc546199b..ccad4f0a135 100644
--- a/src/librustc_middle/mir/interpret/pointer.rs
+++ b/src/librustc_middle/mir/interpret/pointer.rs
@@ -1,4 +1,4 @@
-use super::{AllocId, InterpResult};
+use super::{uabs, AllocId, InterpResult};
 
 use rustc_macros::HashStable;
 use rustc_target::abi::{HasDataLayout, Size};
@@ -25,6 +25,12 @@ pub trait PointerArithmetic: HasDataLayout {
     }
 
     #[inline]
+    fn machine_isize_min(&self) -> i64 {
+        let max_isize_plus_1 = 1i128 << (self.pointer_size().bits() - 1);
+        i64::try_from(-max_isize_plus_1).unwrap()
+    }
+
+    #[inline]
     fn machine_isize_max(&self) -> i64 {
         let max_isize_plus_1 = 1u128 << (self.pointer_size().bits() - 1);
         i64::try_from(max_isize_plus_1 - 1).unwrap()
@@ -42,21 +48,23 @@ pub trait PointerArithmetic: HasDataLayout {
 
     #[inline]
     fn overflowing_offset(&self, val: u64, i: u64) -> (u64, bool) {
+        // We do not need to check if i fits in a machine usize. If it doesn't,
+        // either the wrapping_add will wrap or res will not fit in a pointer.
         let res = val.overflowing_add(i);
         self.truncate_to_ptr(res)
     }
 
     #[inline]
     fn overflowing_signed_offset(&self, val: u64, i: i64) -> (u64, bool) {
-        if i < 0 {
-            // Trickery to ensure that `i64::MIN` works fine: compute `n = -i`.
-            // This formula only works for true negative values; it overflows for zero!
-            let n = u64::MAX - (i as u64) + 1;
-            let res = val.overflowing_sub(n);
-            self.truncate_to_ptr(res)
+        // We need to make sure that i fits in a machine isize.
+        let n = uabs(i);
+        if i >= 0 {
+            let (val, over) = self.overflowing_offset(val, n);
+            (val, over || i > self.machine_isize_max())
         } else {
-            // `i >= 0`, so the cast is safe.
-            self.overflowing_offset(val, i as u64)
+            let res = val.overflowing_sub(n);
+            let (val, over) = self.truncate_to_ptr(res);
+            (val, over || i < self.machine_isize_min())
         }
     }
 
diff --git a/src/librustc_middle/mir/mod.rs b/src/librustc_middle/mir/mod.rs
index f6a236d38ec..b54b09918ab 100644
--- a/src/librustc_middle/mir/mod.rs
+++ b/src/librustc_middle/mir/mod.rs
@@ -408,7 +408,7 @@ impl<'tcx> Body<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, RustcEncodable, RustcDecodable, HashStable)]
+#[derive(Copy, Clone, PartialEq, Eq, Debug, RustcEncodable, RustcDecodable, HashStable)]
 pub enum Safety {
     Safe,
     /// Unsafe because of a PushUnsafeBlock
@@ -1072,7 +1072,8 @@ pub enum TerminatorKind<'tcx> {
     Abort,
 
     /// Indicates a normal return. The return place should have
-    /// been filled in by now. This should occur at most once.
+    /// been filled in before this executes. This can occur multiple times
+    /// in different basic blocks.
     Return,
 
     /// Indicates a terminator that can never be reached.
diff --git a/src/librustc_middle/mir/query.rs b/src/librustc_middle/mir/query.rs
index 63b8d8c8da7..99bfb74c243 100644
--- a/src/librustc_middle/mir/query.rs
+++ b/src/librustc_middle/mir/query.rs
@@ -15,15 +15,27 @@ use super::{Field, SourceInfo};
 
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
 pub enum UnsafetyViolationKind {
+    /// Only permitted in regular `fn`s, prohibitted in `const fn`s.
     General,
     /// Permitted both in `const fn`s and regular `fn`s.
     GeneralAndConstFn,
-    BorrowPacked(hir::HirId),
+    /// Borrow of packed field.
+    /// Has to be handled as a lint for backwards compatibility.
+    BorrowPacked,
+    /// Unsafe operation in an `unsafe fn` but outside an `unsafe` block.
+    /// Has to be handled as a lint for backwards compatibility.
+    /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
+    UnsafeFn,
+    /// Borrow of packed field in an `unsafe fn` but outside an `unsafe` block.
+    /// Has to be handled as a lint for backwards compatibility.
+    /// Should stay gated under `#![feature(unsafe_block_in_unsafe_fn)]`.
+    UnsafeFnBorrowPacked,
 }
 
 #[derive(Copy, Clone, PartialEq, RustcEncodable, RustcDecodable, HashStable)]
 pub struct UnsafetyViolation {
     pub source_info: SourceInfo,
+    pub lint_root: hir::HirId,
     pub description: Symbol,
     pub details: Symbol,
     pub kind: UnsafetyViolationKind,
diff --git a/src/librustc_middle/mir/tcx.rs b/src/librustc_middle/mir/tcx.rs
index 4747aec2d5c..4059bfedc6d 100644
--- a/src/librustc_middle/mir/tcx.rs
+++ b/src/librustc_middle/mir/tcx.rs
@@ -5,7 +5,6 @@
 
 use crate::mir::*;
 use crate::ty::subst::Subst;
-use crate::ty::util::IntTypeExt;
 use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
 use rustc_target::abi::VariantIdx;
@@ -174,17 +173,7 @@ impl<'tcx> Rvalue<'tcx> {
                 tcx.intern_tup(&[ty, tcx.types.bool])
             }
             Rvalue::UnaryOp(UnOp::Not | UnOp::Neg, ref operand) => operand.ty(local_decls, tcx),
-            Rvalue::Discriminant(ref place) => {
-                let ty = place.ty(local_decls, tcx).ty;
-                match ty.kind {
-                    ty::Adt(adt_def, _) => adt_def.repr.discr_type().to_ty(tcx),
-                    ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
-                    _ => {
-                        // This can only be `0`, for now, so `u8` will suffice.
-                        tcx.types.u8
-                    }
-                }
-            }
+            Rvalue::Discriminant(ref place) => place.ty(local_decls, tcx).ty.discriminant_ty(tcx),
             Rvalue::NullaryOp(NullOp::Box, t) => tcx.mk_box(t),
             Rvalue::NullaryOp(NullOp::SizeOf, _) => tcx.types.usize,
             Rvalue::Aggregate(ref ak, ref ops) => match **ak {
diff --git a/src/librustc_middle/query/mod.rs b/src/librustc_middle/query/mod.rs
index 85451bf6538..59b6f5e529b 100644
--- a/src/librustc_middle/query/mod.rs
+++ b/src/librustc_middle/query/mod.rs
@@ -386,8 +386,14 @@ rustc_queries! {
             storage(ArenaCacheSelector<'tcx>)
         }
 
-        /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error
-        query unsafe_derive_on_repr_packed(_: DefId) -> () {}
+        /// HACK: when evaluated, this reports a "unsafe derive on repr(packed)" error.
+        ///
+        /// Unsafety checking is executed for each method separately, but we only want
+        /// to emit this error once per derive. As there are some impls with multiple
+        /// methods, we use a query for deduplication.
+        query unsafe_derive_on_repr_packed(key: LocalDefId) -> () {
+            desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
+        }
 
         /// The signature of functions and closures.
         query fn_sig(_: DefId) -> ty::PolyFnSig<'tcx> {}
diff --git a/src/librustc_middle/ty/context.rs b/src/librustc_middle/ty/context.rs
index 7a200144841..c9d240a5da9 100644
--- a/src/librustc_middle/ty/context.rs
+++ b/src/librustc_middle/ty/context.rs
@@ -1,38 +1,27 @@
 //! Type context book-keeping.
 
 use crate::arena::Arena;
-use crate::dep_graph::DepGraph;
-use crate::dep_graph::{self, DepConstructor};
+use crate::dep_graph::{self, DepConstructor, DepGraph};
 use crate::hir::exports::Export;
 use crate::ich::{NodeIdHashingMode, StableHashingContext};
 use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
-use crate::lint::LintDiagnosticBuilder;
-use crate::lint::{struct_lint_level, LintSource};
+use crate::lint::{struct_lint_level, LintDiagnosticBuilder, LintSource};
 use crate::middle;
-use crate::middle::cstore::CrateStoreDyn;
-use crate::middle::cstore::EncodedMetadata;
+use crate::middle::cstore::{CrateStoreDyn, EncodedMetadata};
 use crate::middle::resolve_lifetime::{self, ObjectLifetimeDefault};
 use crate::middle::stability;
-use crate::mir::interpret::{Allocation, ConstValue, Scalar};
-use crate::mir::{interpret, Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
+use crate::mir::interpret::{self, Allocation, ConstValue, Scalar};
+use crate::mir::{Body, Field, Local, Place, PlaceElem, ProjectionKind, Promoted};
 use crate::traits;
-use crate::ty::query;
 use crate::ty::steal::Steal;
-use crate::ty::subst::{GenericArg, InternalSubsts, Subst, SubstsRef};
-use crate::ty::subst::{GenericArgKind, UserSubsts};
-use crate::ty::CanonicalPolyFnSig;
-use crate::ty::GenericParamDefKind;
-use crate::ty::RegionKind;
-use crate::ty::ReprOptions;
+use crate::ty::subst::{GenericArg, GenericArgKind, InternalSubsts, Subst, SubstsRef, UserSubsts};
 use crate::ty::TyKind::*;
-use crate::ty::{self, DefIdTree, Ty, TypeAndMut};
-use crate::ty::{AdtDef, AdtKind, Const, Region};
-use crate::ty::{BindingMode, BoundVar};
-use crate::ty::{ConstVid, FloatVar, FloatVid, IntVar, IntVid, TyVar, TyVid};
-use crate::ty::{ExistentialPredicate, Predicate, PredicateKind};
-use crate::ty::{InferConst, ParamConst};
-use crate::ty::{InferTy, ParamTy, PolyFnSig, ProjectionTy};
-use crate::ty::{List, TyKind, TyS};
+use crate::ty::{
+    self, query, AdtDef, AdtKind, BindingMode, BoundVar, CanonicalPolyFnSig, Const, ConstVid,
+    DefIdTree, ExistentialPredicate, FloatVar, FloatVid, GenericParamDefKind, InferConst, InferTy,
+    IntVar, IntVid, List, ParamConst, ParamTy, PolyFnSig, Predicate, PredicateKind, ProjectionTy,
+    Region, RegionKind, ReprOptions, TraitObjectVisitor, Ty, TyKind, TyS, TyVar, TyVid, TypeAndMut,
+};
 use rustc_ast::ast;
 use rustc_ast::expand::allocator::AllocatorKind;
 use rustc_attr as attr;
@@ -48,10 +37,8 @@ use rustc_hir as hir;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, LocalDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefPathHash, Definitions};
-use rustc_hir::lang_items;
-use rustc_hir::lang_items::PanicLocationLangItem;
-use rustc_hir::{HirId, Node, TraitCandidate};
-use rustc_hir::{ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet};
+use rustc_hir::lang_items::{self, PanicLocationLangItem};
+use rustc_hir::{HirId, ItemKind, ItemLocalId, ItemLocalMap, ItemLocalSet, Node, TraitCandidate};
 use rustc_index::vec::{Idx, IndexVec};
 use rustc_macros::HashStable;
 use rustc_session::config::{BorrowckMode, CrateType, OutputFilenames};
@@ -419,7 +406,7 @@ pub struct TypeckTables<'tcx> {
     /// The upvarID contains the HIR node ID and it also contains the full path
     /// leading to the member of the struct or tuple that is used instead of the
     /// entire variable.
-    pub upvar_list: ty::UpvarListMap,
+    pub closure_captures: ty::UpvarListMap,
 
     /// Stores the type, expression, span and optional scope span of all types
     /// that are live across the yield of this generator (if a generator).
@@ -447,7 +434,7 @@ impl<'tcx> TypeckTables<'tcx> {
             used_trait_imports: Lrc::new(Default::default()),
             tainted_by_errors: None,
             concrete_opaque_types: Default::default(),
-            upvar_list: Default::default(),
+            closure_captures: Default::default(),
             generator_interior_types: Default::default(),
         }
     }
@@ -688,7 +675,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             ref used_trait_imports,
             tainted_by_errors,
             ref concrete_opaque_types,
-            ref upvar_list,
+            ref closure_captures,
             ref generator_interior_types,
         } = *self;
 
@@ -721,7 +708,7 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for TypeckTables<'tcx> {
             used_trait_imports.hash_stable(hcx, hasher);
             tainted_by_errors.hash_stable(hcx, hasher);
             concrete_opaque_types.hash_stable(hcx, hasher);
-            upvar_list.hash_stable(hcx, hasher);
+            closure_captures.hash_stable(hcx, hasher);
             generator_interior_types.hash_stable(hcx, hasher);
         })
     }
@@ -1396,6 +1383,66 @@ impl<'tcx> TyCtxt<'tcx> {
         })
     }
 
+    pub fn return_type_impl_or_dyn_trait(&self, scope_def_id: DefId) -> Option<(Span, bool)> {
+        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 {
+                kind:
+                    ItemKind::Fn(
+                        hir::FnSig {
+                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
+                            ..
+                        },
+                        ..,
+                    ),
+                ..
+            })
+            | Node::ImplItem(hir::ImplItem {
+                kind:
+                    hir::ImplItemKind::Fn(
+                        hir::FnSig {
+                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
+                            ..
+                        },
+                        _,
+                    ),
+                ..
+            })
+            | Node::TraitItem(hir::TraitItem {
+                kind:
+                    hir::TraitItemKind::Fn(
+                        hir::FnSig {
+                            decl: hir::FnDecl { output: hir::FnRetTy::Return(ty), .. },
+                            ..
+                        },
+                        _,
+                    ),
+                ..
+            }) => ty,
+            _ => return None,
+        };
+
+        let ret_ty = self.type_of(scope_def_id);
+        match ret_ty.kind {
+            ty::FnDef(_, _) => {
+                let sig = ret_ty.fn_sig(*self);
+                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))
+                } 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));
+                    }
+                    None
+                }
+            }
+            _ => None,
+        }
+    }
+
     pub fn return_type_impl_trait(&self, scope_def_id: DefId) -> Option<(Ty<'tcx>, Span)> {
         // HACK: `type_of_def_id()` will fail on these (#55796), so return `None`.
         let hir_id = self.hir().as_local_hir_id(scope_def_id.expect_local());
@@ -2252,11 +2299,6 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     #[inline]
-    pub fn mk_bool(self) -> Ty<'tcx> {
-        self.mk_ty(Bool)
-    }
-
-    #[inline]
     pub fn mk_fn_def(self, def_id: DefId, substs: SubstsRef<'tcx>) -> Ty<'tcx> {
         self.mk_ty(FnDef(def_id, substs))
     }
diff --git a/src/librustc_middle/ty/diagnostics.rs b/src/librustc_middle/ty/diagnostics.rs
index 613d66d59c5..1403efb745b 100644
--- a/src/librustc_middle/ty/diagnostics.rs
+++ b/src/librustc_middle/ty/diagnostics.rs
@@ -249,3 +249,22 @@ pub fn suggest_constraining_type_param(
         true
     }
 }
+
+pub struct TraitObjectVisitor(pub Vec<rustc_span::Span>);
+impl<'v> hir::intravisit::Visitor<'v> for TraitObjectVisitor {
+    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<'_>) {
+        if let hir::TyKind::TraitObject(
+            _,
+            hir::Lifetime { name: hir::LifetimeName::ImplicitObjectLifetimeDefault, .. },
+        ) = ty.kind
+        {
+            self.0.push(ty.span);
+        }
+    }
+}
diff --git a/src/librustc_middle/ty/layout.rs b/src/librustc_middle/ty/layout.rs
index 5566e187c0c..e93abd3390a 100644
--- a/src/librustc_middle/ty/layout.rs
+++ b/src/librustc_middle/ty/layout.rs
@@ -187,10 +187,9 @@ fn layout_raw<'tcx>(
     query: ty::ParamEnvAnd<'tcx, Ty<'tcx>>,
 ) -> Result<&'tcx Layout, LayoutError<'tcx>> {
     ty::tls::with_related_context(tcx, move |icx| {
-        let rec_limit = tcx.sess.recursion_limit.get().copied().unwrap();
         let (param_env, ty) = query.into_parts();
 
-        if icx.layout_depth > rec_limit {
+        if !tcx.sess.recursion_limit().value_within_limit(icx.layout_depth) {
             tcx.sess.fatal(&format!("overflow representing the type `{}`", ty));
         }
 
diff --git a/src/librustc_middle/ty/mod.rs b/src/librustc_middle/ty/mod.rs
index 01517ab25a2..4cd3be932de 100644
--- a/src/librustc_middle/ty/mod.rs
+++ b/src/librustc_middle/ty/mod.rs
@@ -2037,6 +2037,8 @@ impl ReprOptions {
         self.flags.contains(ReprFlags::HIDE_NICHE)
     }
 
+    /// Returns the discriminant type, given these `repr` options.
+    /// This must only be called on enums!
     pub fn discr_type(&self) -> attr::IntType {
         self.int.unwrap_or(attr::SignedInt(ast::IntTy::Isize))
     }
@@ -2269,6 +2271,7 @@ impl<'tcx> AdtDef {
 
     #[inline]
     pub fn eval_explicit_discr(&self, tcx: TyCtxt<'tcx>, expr_did: DefId) -> Option<Discr<'tcx>> {
+        assert!(self.is_enum());
         let param_env = tcx.param_env(expr_did);
         let repr_type = self.repr.discr_type();
         match tcx.const_eval_poly(expr_did) {
@@ -2305,6 +2308,7 @@ impl<'tcx> AdtDef {
         &'tcx self,
         tcx: TyCtxt<'tcx>,
     ) -> impl Iterator<Item = (VariantIdx, Discr<'tcx>)> + Captures<'tcx> {
+        assert!(self.is_enum());
         let repr_type = self.repr.discr_type();
         let initial = repr_type.initial_discriminant(tcx);
         let mut prev_discr = None::<Discr<'tcx>>;
@@ -2337,6 +2341,7 @@ impl<'tcx> AdtDef {
         tcx: TyCtxt<'tcx>,
         variant_index: VariantIdx,
     ) -> Discr<'tcx> {
+        assert!(self.is_enum());
         let (val, offset) = self.discriminant_def_for_variant(variant_index);
         let explicit_value = val
             .and_then(|expr_did| self.eval_explicit_discr(tcx, expr_did))
diff --git a/src/librustc_middle/ty/sty.rs b/src/librustc_middle/ty/sty.rs
index ef77d1b5b3f..f4962ced6c0 100644
--- a/src/librustc_middle/ty/sty.rs
+++ b/src/librustc_middle/ty/sty.rs
@@ -29,6 +29,7 @@ use std::borrow::Cow;
 use std::cmp::Ordering;
 use std::marker::PhantomData;
 use std::ops::Range;
+use ty::util::IntTypeExt;
 
 #[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, RustcEncodable, RustcDecodable)]
 #[derive(HashStable, TypeFoldable, Lift)]
@@ -2096,7 +2097,9 @@ impl<'tcx> TyS<'tcx> {
         variant_index: VariantIdx,
     ) -> Option<Discr<'tcx>> {
         match self.kind {
-            TyKind::Adt(adt, _) => Some(adt.discriminant_for_variant(tcx, variant_index)),
+            TyKind::Adt(adt, _) if adt.is_enum() => {
+                Some(adt.discriminant_for_variant(tcx, variant_index))
+            }
             TyKind::Generator(def_id, substs, _) => {
                 Some(substs.as_generator().discriminant_for_variant(def_id, tcx, variant_index))
             }
@@ -2104,6 +2107,18 @@ impl<'tcx> TyS<'tcx> {
         }
     }
 
+    /// Returns the type of the discriminant of this type.
+    pub fn discriminant_ty(&self, tcx: TyCtxt<'tcx>) -> Ty<'tcx> {
+        match self.kind {
+            ty::Adt(adt, _) if adt.is_enum() => adt.repr.discr_type().to_ty(tcx),
+            ty::Generator(_, substs, _) => substs.as_generator().discr_ty(tcx),
+            _ => {
+                // This can only be `0`, for now, so `u8` will suffice.
+                tcx.types.u8
+            }
+        }
+    }
+
     /// When we create a closure, we record its kind (i.e., what trait
     /// it implements) into its `ClosureSubsts` using a type
     /// parameter. This is kind of a phantom type, except that the
diff --git a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
index 5f1c0911da2..d0050f801fc 100644
--- a/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/conflict_errors.rs
@@ -214,7 +214,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                     let generics = tcx.generics_of(self.mir_def_id);
                     let param = generics.type_param(&param_ty, tcx);
                     if let Some(generics) =
-                        tcx.hir().get_generics(tcx.closure_base_def_id(self.mir_def_id))
+                        tcx.hir().get_generics(tcx.closure_base_def_id(self.mir_def_id.to_def_id()))
                     {
                         suggest_constraining_type_param(
                             tcx,
@@ -865,49 +865,42 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                 format!("`{}` would have to be valid for `{}`...", name, region_name),
             );
 
-            if let Some(def_id) = self.mir_def_id.as_local() {
-                let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(def_id);
-                err.span_label(
-                    drop_span,
-                    format!(
-                        "...but `{}` will be dropped here, when the {} returns",
-                        name,
-                        self.infcx
-                            .tcx
-                            .hir()
-                            .opt_name(fn_hir_id)
-                            .map(|name| format!("function `{}`", name))
-                            .unwrap_or_else(|| {
-                                match &self
-                                    .infcx
-                                    .tcx
-                                    .typeck_tables_of(def_id)
-                                    .node_type(fn_hir_id)
-                                    .kind
-                                {
-                                    ty::Closure(..) => "enclosing closure",
-                                    ty::Generator(..) => "enclosing generator",
-                                    kind => bug!("expected closure or generator, found {:?}", kind),
-                                }
-                                .to_string()
-                            })
-                    ),
-                );
+            let fn_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
+            err.span_label(
+                drop_span,
+                format!(
+                    "...but `{}` will be dropped here, when the {} returns",
+                    name,
+                    self.infcx
+                        .tcx
+                        .hir()
+                        .opt_name(fn_hir_id)
+                        .map(|name| format!("function `{}`", name))
+                        .unwrap_or_else(|| {
+                            match &self
+                                .infcx
+                                .tcx
+                                .typeck_tables_of(self.mir_def_id)
+                                .node_type(fn_hir_id)
+                                .kind
+                            {
+                                ty::Closure(..) => "enclosing closure",
+                                ty::Generator(..) => "enclosing generator",
+                                kind => bug!("expected closure or generator, found {:?}", kind),
+                            }
+                            .to_string()
+                        })
+                ),
+            );
 
-                err.note(
-                    "functions cannot return a borrow to data owned within the function's scope, \
-                     functions can only return borrows to data passed as arguments",
-                );
-                err.note(
-                    "to learn more, visit <https://doc.rust-lang.org/book/ch04-02-\
-                     references-and-borrowing.html#dangling-references>",
-                );
-            } else {
-                err.span_label(
-                    drop_span,
-                    format!("...but `{}` dropped here while still borrowed", name),
-                );
-            }
+            err.note(
+                "functions cannot return a borrow to data owned within the function's scope, \
+                    functions can only return borrows to data passed as arguments",
+            );
+            err.note(
+                "to learn more, visit <https://doc.rust-lang.org/book/ch04-02-\
+                    references-and-borrowing.html#dangling-references>",
+            );
 
             if let BorrowExplanation::MustBeValidFor { .. } = explanation {
             } else {
@@ -1237,7 +1230,7 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> DiagnosticBuilder<'cx> {
         let tcx = self.infcx.tcx;
 
-        let (_, escapes_from) = tcx.article_and_description(self.mir_def_id);
+        let (_, escapes_from) = tcx.article_and_description(self.mir_def_id.to_def_id());
 
         let mut err =
             borrowck_errors::borrowed_data_escapes_closure(tcx, escape_span, escapes_from);
@@ -1572,14 +1565,16 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
     ) -> Option<AnnotatedBorrowFnSignature<'tcx>> {
         // Define a fallback for when we can't match a closure.
         let fallback = || {
-            let is_closure = self.infcx.tcx.is_closure(self.mir_def_id);
+            let is_closure = self.infcx.tcx.is_closure(self.mir_def_id.to_def_id());
             if is_closure {
                 None
             } else {
                 let ty = self.infcx.tcx.type_of(self.mir_def_id);
                 match ty.kind {
-                    ty::FnDef(_, _) | ty::FnPtr(_) => self
-                        .annotate_fn_sig(self.mir_def_id, self.infcx.tcx.fn_sig(self.mir_def_id)),
+                    ty::FnDef(_, _) | ty::FnPtr(_) => self.annotate_fn_sig(
+                        self.mir_def_id.to_def_id(),
+                        self.infcx.tcx.fn_sig(self.mir_def_id),
+                    ),
                     _ => None,
                 }
             }
diff --git a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
index 67254811ec5..b49e4187fb8 100644
--- a/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/move_errors.rs
@@ -331,7 +331,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
                 self.cannot_move_out_of_interior_noncopy(span, ty, None)
             }
             ty::Closure(def_id, closure_substs)
-                if def_id == self.mir_def_id && upvar_field.is_some() =>
+                if def_id.as_local() == Some(self.mir_def_id) && upvar_field.is_some() =>
             {
                 let closure_kind_ty = closure_substs.as_closure().kind_ty();
                 let closure_kind = closure_kind_ty.to_opt_closure_kind();
diff --git a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
index 402eac47c46..e04ed8b83de 100644
--- a/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/mutability_errors.rs
@@ -492,7 +492,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         err.span_label(sp, format!("cannot {}", act));
 
         let hir = self.infcx.tcx.hir();
-        let closure_id = hir.as_local_hir_id(self.mir_def_id.expect_local());
+        let closure_id = hir.as_local_hir_id(self.mir_def_id);
         let fn_call_id = hir.get_parent_node(closure_id);
         let node = hir.get(fn_call_id);
         let item_id = hir.get_parent_item(fn_call_id);
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
index e19fab89eab..727c4d0605e 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_errors.rs
@@ -498,7 +498,7 @@ impl<'a, 'tcx> MirBorrowckCtxt<'a, 'tcx> {
         let mut diag =
             self.infcx.tcx.sess.struct_span_err(*span, "lifetime may not live long enough");
 
-        let (_, mir_def_name) = self.infcx.tcx.article_and_description(self.mir_def_id);
+        let (_, mir_def_name) = self.infcx.tcx.article_and_description(self.mir_def_id.to_def_id());
 
         let fr_name = self.give_region_a_name(*fr).unwrap();
         fr_name.highlight_region_name(&mut diag);
diff --git a/src/librustc_mir/borrow_check/diagnostics/region_name.rs b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
index e912ef7b202..2240eb81e1f 100644
--- a/src/librustc_mir/borrow_check/diagnostics/region_name.rs
+++ b/src/librustc_mir/borrow_check/diagnostics/region_name.rs
@@ -237,8 +237,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
                 }
 
                 ty::BoundRegion::BrEnv => {
-                    let mir_hir_id =
-                        self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id.expect_local());
+                    let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
                     let def_ty = self.regioncx.universal_regions().defining_ty;
 
                     if let DefiningTy::Closure(_, substs) = def_ty {
@@ -323,7 +322,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         argument_ty: Ty<'tcx>,
         argument_index: usize,
     ) -> Option<RegionName> {
-        let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id.as_local()?);
+        let mir_hir_id = self.infcx.tcx.hir().as_local_hir_id(self.mir_def_id);
         let fn_decl = self.infcx.tcx.hir().fn_decl_by_hir_id(mir_hir_id)?;
         let argument_hir_ty: &hir::Ty<'_> = fn_decl.inputs.get(argument_index)?;
         match argument_hir_ty.kind {
@@ -634,7 +633,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
         let type_name = self.infcx.extract_type_name(&return_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id.expect_local());
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
 
         let (return_span, mir_description) = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
@@ -686,7 +685,7 @@ impl<'tcx> MirBorrowckCtxt<'_, 'tcx> {
         highlight.highlighting_region_vid(fr, *self.next_region_name.try_borrow().unwrap());
         let type_name = self.infcx.extract_type_name(&yield_ty, Some(highlight)).0;
 
-        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id.expect_local());
+        let mir_hir_id = tcx.hir().as_local_hir_id(self.mir_def_id);
 
         let yield_span = match tcx.hir().get(mir_hir_id) {
             hir::Node::Expr(hir::Expr {
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index 525c054a766..268fbfcf395 100644
--- a/src/librustc_mir/borrow_check/mod.rs
+++ b/src/librustc_mir/borrow_check/mod.rs
@@ -4,10 +4,8 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::graph::dominators::Dominators;
 use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorReported};
 use rustc_hir as hir;
-use rustc_hir::{
-    def_id::{DefId, LocalDefId},
-    HirId, Node,
-};
+use rustc_hir::def_id::LocalDefId;
+use rustc_hir::{HirId, Node};
 use rustc_index::bit_set::BitSet;
 use rustc_index::vec::IndexVec;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
@@ -142,7 +140,7 @@ fn do_mir_borrowck<'a, 'tcx>(
         infcx.set_tainted_by_errors();
     }
     let upvars: Vec<_> = tables
-        .upvar_list
+        .closure_captures
         .get(&def_id.to_def_id())
         .into_iter()
         .flat_map(|v| v.values())
@@ -174,7 +172,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     let mut body = input_body.clone();
     let mut promoted = input_promoted.clone();
     let free_regions =
-        nll::replace_regions_in_mir(infcx, def_id.to_def_id(), param_env, &mut body, &mut promoted);
+        nll::replace_regions_in_mir(infcx, def_id, param_env, &mut body, &mut promoted);
     let body = &body; // no further changes
 
     let location_table = &LocationTable::new(&body);
@@ -275,7 +273,7 @@ fn do_mir_borrowck<'a, 'tcx>(
             let mut promoted_mbcx = MirBorrowckCtxt {
                 infcx,
                 body: promoted_body,
-                mir_def_id: def_id.to_def_id(),
+                mir_def_id: def_id,
                 move_data: &move_data,
                 location_table: &LocationTable::new(promoted_body),
                 movable_generator,
@@ -307,7 +305,7 @@ fn do_mir_borrowck<'a, 'tcx>(
     let mut mbcx = MirBorrowckCtxt {
         infcx,
         body,
-        mir_def_id: def_id.to_def_id(),
+        mir_def_id: def_id,
         move_data: &mdpe.move_data,
         location_table,
         movable_generator,
@@ -459,7 +457,7 @@ fn do_mir_borrowck<'a, 'tcx>(
 crate struct MirBorrowckCtxt<'cx, 'tcx> {
     crate infcx: &'cx InferCtxt<'cx, 'tcx>,
     body: &'cx Body<'tcx>,
-    mir_def_id: DefId,
+    mir_def_id: LocalDefId,
     move_data: &'cx MoveData<'tcx>,
 
     /// Map from MIR `Location` to `LocationIndex`; created
diff --git a/src/librustc_mir/borrow_check/nll.rs b/src/librustc_mir/borrow_check/nll.rs
index b820b79c47f..1d373337147 100644
--- a/src/librustc_mir/borrow_check/nll.rs
+++ b/src/librustc_mir/borrow_check/nll.rs
@@ -58,7 +58,7 @@ crate struct NllOutput<'tcx> {
 /// `compute_regions`.
 pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
     infcx: &InferCtxt<'cx, 'tcx>,
-    def_id: DefId,
+    def_id: LocalDefId,
     param_env: ty::ParamEnv<'tcx>,
     body: &mut Body<'tcx>,
     promoted: &mut IndexVec<Promoted, Body<'tcx>>,
@@ -66,12 +66,12 @@ pub(in crate::borrow_check) fn replace_regions_in_mir<'cx, 'tcx>(
     debug!("replace_regions_in_mir(def_id={:?})", def_id);
 
     // Compute named region information. This also renumbers the inputs/outputs.
-    let universal_regions = UniversalRegions::new(infcx, def_id.expect_local(), param_env);
+    let universal_regions = UniversalRegions::new(infcx, def_id, param_env);
 
     // Replace all remaining regions with fresh inference variables.
     renumber::renumber_mir(infcx, body, promoted);
 
-    let source = MirSource::item(def_id);
+    let source = MirSource::item(def_id.to_def_id());
     mir_util::dump_mir(infcx.tcx, None, "renumber", &0, source, body, |_, _| Ok(()));
 
     universal_regions
diff --git a/src/librustc_mir/const_eval/machine.rs b/src/librustc_mir/const_eval/machine.rs
index 7c1ab261eb9..dc13126df0e 100644
--- a/src/librustc_mir/const_eval/machine.rs
+++ b/src/librustc_mir/const_eval/machine.rs
@@ -10,6 +10,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_ast::ast::Mutability;
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::AssertMessage;
+use rustc_session::Limit;
 use rustc_span::symbol::Symbol;
 
 use crate::interpret::{
@@ -109,8 +110,8 @@ pub struct MemoryExtra {
 }
 
 impl<'mir, 'tcx> CompileTimeInterpreter<'mir, 'tcx> {
-    pub(super) fn new(const_eval_limit: usize) -> Self {
-        CompileTimeInterpreter { steps_remaining: const_eval_limit, stack: Vec::new() }
+    pub(super) fn new(const_eval_limit: Limit) -> Self {
+        CompileTimeInterpreter { steps_remaining: const_eval_limit.0, stack: Vec::new() }
     }
 }
 
diff --git a/src/librustc_mir/interpret/eval_context.rs b/src/librustc_mir/interpret/eval_context.rs
index 4f91257e2ef..6497e211de3 100644
--- a/src/librustc_mir/interpret/eval_context.rs
+++ b/src/librustc_mir/interpret/eval_context.rs
@@ -651,7 +651,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         M::after_stack_push(self)?;
         info!("ENTERING({}) {}", self.frame_idx(), self.frame().instance);
 
-        if self.stack().len() > self.tcx.sess.recursion_limit() {
+        if !self.tcx.sess.recursion_limit().value_within_limit(self.stack().len()) {
             throw_exhaust!(StackFrameLimitReached)
         } else {
             Ok(())
diff --git a/src/librustc_mir/interpret/intrinsics.rs b/src/librustc_mir/interpret/intrinsics.rs
index fc4be82ad90..115a472cabe 100644
--- a/src/librustc_mir/interpret/intrinsics.rs
+++ b/src/librustc_mir/interpret/intrinsics.rs
@@ -2,19 +2,21 @@
 //! looking at their MIR. Intrinsics/functions supported here are shared by CTFE
 //! and miri.
 
+use std::convert::TryFrom;
+
 use rustc_hir::def_id::DefId;
 use rustc_middle::mir::{
     self,
-    interpret::{ConstValue, GlobalId, InterpResult, Scalar},
+    interpret::{uabs, ConstValue, GlobalId, InterpResult, Scalar},
     BinOp,
 };
 use rustc_middle::ty;
 use rustc_middle::ty::subst::SubstsRef;
-use rustc_middle::ty::TyCtxt;
+use rustc_middle::ty::{Ty, TyCtxt};
 use rustc_span::symbol::{sym, Symbol};
 use rustc_target::abi::{Abi, LayoutOf as _, Primitive, Size};
 
-use super::{ImmTy, InterpCx, Machine, OpTy, PlaceTy};
+use super::{CheckInAllocMsg, ImmTy, InterpCx, Machine, OpTy, PlaceTy};
 
 mod caller_location;
 mod type_name;
@@ -218,15 +220,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             sym::discriminant_value => {
                 let place = self.deref_operand(args[0])?;
                 let discr_val = self.read_discriminant(place.into())?.0;
-                let scalar = match dest.layout.ty.kind {
-                    ty::Int(_) => Scalar::from_int(
-                        self.sign_extend(discr_val, dest.layout) as i128,
-                        dest.layout.size,
-                    ),
-                    ty::Uint(_) => Scalar::from_uint(discr_val, dest.layout.size),
-                    _ => bug!("invalid `discriminant_value` return layout: {:?}", dest.layout),
-                };
-                self.write_scalar(scalar, dest)?;
+                self.write_scalar(discr_val, dest)?;
             }
             sym::unchecked_shl
             | sym::unchecked_shr
@@ -279,7 +273,24 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let result = Scalar::from_uint(truncated_bits, layout.size);
                 self.write_scalar(result, dest)?;
             }
+            sym::offset => {
+                let ptr = self.read_scalar(args[0])?.not_undef()?;
+                let offset_count = self.read_scalar(args[1])?.to_machine_isize(self)?;
+                let pointee_ty = substs.type_at(0);
+
+                let offset_ptr = self.ptr_offset_inbounds(ptr, pointee_ty, offset_count)?;
+                self.write_scalar(offset_ptr, dest)?;
+            }
+            sym::arith_offset => {
+                let ptr = self.read_scalar(args[0])?.not_undef()?;
+                let offset_count = self.read_scalar(args[1])?.to_machine_isize(self)?;
+                let pointee_ty = substs.type_at(0);
 
+                let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
+                let offset_bytes = offset_count.wrapping_mul(pointee_size);
+                let offset_ptr = ptr.ptr_wrapping_signed_offset(offset_bytes, self);
+                self.write_scalar(offset_ptr, dest)?;
+            }
             sym::ptr_offset_from => {
                 let a = self.read_immediate(args[0])?.to_scalar()?;
                 let b = self.read_immediate(args[1])?.to_scalar()?;
@@ -409,4 +420,36 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // `Rem` says this is all right, so we can let `Div` do its job.
         self.binop_ignore_overflow(BinOp::Div, a, b, dest)
     }
+
+    /// Offsets a pointer by some multiple of its type, returning an error if the pointer leaves its
+    /// allocation. For integer pointers, we consider each of them their own tiny allocation of size
+    /// 0, so offset-by-0 (and only 0) is okay -- except that NULL cannot be offset by _any_ value.
+    pub fn ptr_offset_inbounds(
+        &self,
+        ptr: Scalar<M::PointerTag>,
+        pointee_ty: Ty<'tcx>,
+        offset_count: i64,
+    ) -> InterpResult<'tcx, Scalar<M::PointerTag>> {
+        // We cannot overflow i64 as a type's size must be <= isize::MAX.
+        let pointee_size = i64::try_from(self.layout_of(pointee_ty)?.size.bytes()).unwrap();
+        // The computed offset, in bytes, cannot overflow an isize.
+        let offset_bytes =
+            offset_count.checked_mul(pointee_size).ok_or(err_ub!(PointerArithOverflow))?;
+        // The offset being in bounds cannot rely on "wrapping around" the address space.
+        // So, first rule out overflows in the pointer arithmetic.
+        let offset_ptr = ptr.ptr_signed_offset(offset_bytes, self)?;
+        // ptr and offset_ptr must be in bounds of the same allocated object. This means all of the
+        // memory between these pointers must be accessible. Note that we do not require the
+        // pointers to be properly aligned (unlike a read/write operation).
+        let min_ptr = if offset_bytes >= 0 { ptr } else { offset_ptr };
+        let size: u64 = uabs(offset_bytes);
+        // This call handles checking for integer/NULL pointers.
+        self.memory.check_ptr_access_align(
+            min_ptr,
+            Size::from_bytes(size),
+            None,
+            CheckInAllocMsg::InboundsTest,
+        )?;
+        Ok(offset_ptr)
+    }
 }
diff --git a/src/librustc_mir/interpret/operand.rs b/src/librustc_mir/interpret/operand.rs
index 95bc9810dab..db4473154c4 100644
--- a/src/librustc_mir/interpret/operand.rs
+++ b/src/librustc_mir/interpret/operand.rs
@@ -7,15 +7,15 @@ use std::fmt::Write;
 use rustc_errors::ErrorReported;
 use rustc_hir::def::Namespace;
 use rustc_macros::HashStable;
-use rustc_middle::ty::layout::{IntegerExt, PrimitiveExt, TyAndLayout};
+use rustc_middle::ty::layout::{PrimitiveExt, TyAndLayout};
 use rustc_middle::ty::print::{FmtPrinter, PrettyPrinter, Printer};
 use rustc_middle::ty::Ty;
 use rustc_middle::{mir, ty};
-use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, Integer, LayoutOf, Size};
+use rustc_target::abi::{Abi, DiscriminantKind, HasDataLayout, LayoutOf, Size};
 use rustc_target::abi::{VariantIdx, Variants};
 
 use super::{
-    from_known_layout, sign_extend, truncate, ConstValue, GlobalId, InterpCx, InterpResult,
+    from_known_layout, mir_assign_valid_types, ConstValue, GlobalId, InterpCx, InterpResult,
     MPlaceTy, Machine, MemPlace, Place, PlaceTy, Pointer, Scalar, ScalarMaybeUninit,
 };
 
@@ -469,6 +469,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             .try_fold(base_op, |op, elem| self.operand_projection(op, elem))?;
 
         trace!("eval_place_to_op: got {:?}", *op);
+        // Sanity-check the type we ended up with.
+        debug_assert!(mir_assign_valid_types(
+            *self.tcx,
+            self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
+                place.ty(&self.frame().body.local_decls, *self.tcx).ty
+            ))?,
+            op.layout,
+        ));
         Ok(op)
     }
 
@@ -576,98 +584,113 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     /// Read discriminant, return the runtime value as well as the variant index.
     pub fn read_discriminant(
         &self,
-        rval: OpTy<'tcx, M::PointerTag>,
-    ) -> InterpResult<'tcx, (u128, VariantIdx)> {
-        trace!("read_discriminant_value {:#?}", rval.layout);
-
-        let (discr_layout, discr_kind, discr_index) = match rval.layout.variants {
+        op: OpTy<'tcx, M::PointerTag>,
+    ) -> InterpResult<'tcx, (Scalar<M::PointerTag>, VariantIdx)> {
+        trace!("read_discriminant_value {:#?}", op.layout);
+
+        // Get type and layout of the discriminant.
+        let discr_layout = self.layout_of(op.layout.ty.discriminant_ty(*self.tcx))?;
+        trace!("discriminant type: {:?}", discr_layout.ty);
+
+        // We use "discriminant" to refer to the value associated with a particular enum variant.
+        // This is not to be confused with its "variant index", which is just determining its position in the
+        // declared list of variants -- they can differ with explicitly assigned discriminants.
+        // We use "tag" to refer to how the discriminant is encoded in memory, which can be either
+        // straight-forward (`DiscriminantKind::Tag`) or with a niche (`DiscriminantKind::Niche`).
+        // Unfortunately, the rest of the compiler calls the latter "discriminant", too, which makes things
+        // rather confusing.
+        let (tag_scalar_layout, tag_kind, tag_index) = match op.layout.variants {
             Variants::Single { index } => {
-                let discr_val = rval
-                    .layout
-                    .ty
-                    .discriminant_for_variant(*self.tcx, index)
-                    .map_or(u128::from(index.as_u32()), |discr| discr.val);
-                return Ok((discr_val, index));
+                let discr = match op.layout.ty.discriminant_for_variant(*self.tcx, index) {
+                    Some(discr) => {
+                        // This type actually has discriminants.
+                        assert_eq!(discr.ty, discr_layout.ty);
+                        Scalar::from_uint(discr.val, discr_layout.size)
+                    }
+                    None => {
+                        // On a type without actual discriminants, variant is 0.
+                        assert_eq!(index.as_u32(), 0);
+                        Scalar::from_uint(index.as_u32(), discr_layout.size)
+                    }
+                };
+                return Ok((discr, index));
             }
-            Variants::Multiple { discr: ref discr_layout, ref discr_kind, discr_index, .. } => {
-                (discr_layout, discr_kind, discr_index)
+            Variants::Multiple { ref discr, ref discr_kind, discr_index, .. } => {
+                (discr, discr_kind, discr_index)
             }
         };
 
-        // read raw discriminant value
-        let discr_op = self.operand_field(rval, discr_index)?;
-        let discr_val = self.read_immediate(discr_op)?;
-        let raw_discr = discr_val.to_scalar_or_undef();
-        trace!("discr value: {:?}", raw_discr);
-        // post-process
-        Ok(match *discr_kind {
+        // There are *three* layouts that come into play here:
+        // - The discriminant has a type for typechecking. This is `discr_layout`, and is used for
+        //   the `Scalar` we return.
+        // - The tag (encoded discriminant) has layout `tag_layout`. This is always an integer type,
+        //   and used to interpret the value we read from the tag field.
+        //   For the return value, a cast to `discr_layout` is performed.
+        // - The field storing the tag has a layout, which is very similar to `tag_layout` but
+        //   may be a pointer. This is `tag_val.layout`; we just use it for sanity checks.
+
+        // Get layout for tag.
+        let tag_layout = self.layout_of(tag_scalar_layout.value.to_int_ty(*self.tcx))?;
+
+        // Read tag and sanity-check `tag_layout`.
+        let tag_val = self.read_immediate(self.operand_field(op, tag_index)?)?;
+        assert_eq!(tag_layout.size, tag_val.layout.size);
+        assert_eq!(tag_layout.abi.is_signed(), tag_val.layout.abi.is_signed());
+        let tag_val = tag_val.to_scalar()?;
+        trace!("tag value: {:?}", tag_val);
+
+        // Figure out which discriminant and variant this corresponds to.
+        Ok(match *tag_kind {
             DiscriminantKind::Tag => {
-                let bits_discr = raw_discr
-                    .not_undef()
-                    .and_then(|raw_discr| self.force_bits(raw_discr, discr_val.layout.size))
-                    .map_err(|_| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?;
-                let real_discr = if discr_val.layout.abi.is_signed() {
-                    // going from layout tag type to typeck discriminant type
-                    // requires first sign extending with the discriminant layout
-                    let sexted = sign_extend(bits_discr, discr_val.layout.size);
-                    // and then zeroing with the typeck discriminant type
-                    let discr_ty = rval
-                        .layout
-                        .ty
-                        .ty_adt_def()
-                        .expect("tagged layout corresponds to adt")
-                        .repr
-                        .discr_type();
-                    let size = Integer::from_attr(self, discr_ty).size();
-                    truncate(sexted, size)
-                } else {
-                    bits_discr
-                };
-                // Make sure we catch invalid discriminants
-                let index = match rval.layout.ty.kind {
+                let tag_bits = self
+                    .force_bits(tag_val, tag_layout.size)
+                    .map_err(|_| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
+                // Cast bits from tag layout to discriminant layout.
+                let discr_val_cast = self.cast_from_scalar(tag_bits, tag_layout, discr_layout.ty);
+                let discr_bits = discr_val_cast.assert_bits(discr_layout.size);
+                // Convert discriminant to variant index, and catch invalid discriminants.
+                let index = match op.layout.ty.kind {
                     ty::Adt(adt, _) => {
-                        adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == real_discr)
+                        adt.discriminants(self.tcx.tcx).find(|(_, var)| var.val == discr_bits)
                     }
                     ty::Generator(def_id, substs, _) => {
                         let substs = substs.as_generator();
                         substs
                             .discriminants(def_id, self.tcx.tcx)
-                            .find(|(_, var)| var.val == real_discr)
+                            .find(|(_, var)| var.val == discr_bits)
                     }
                     _ => bug!("tagged layout for non-adt non-generator"),
                 }
-                .ok_or_else(|| err_ub!(InvalidDiscriminant(raw_discr.erase_tag())))?;
-                (real_discr, index.0)
+                .ok_or_else(|| err_ub!(InvalidDiscriminant(tag_val.erase_tag())))?;
+                // Return the cast value, and the index.
+                (discr_val_cast, index.0)
             }
             DiscriminantKind::Niche { dataful_variant, ref niche_variants, niche_start } => {
+                // Compute the variant this niche value/"tag" corresponds to. With niche layout,
+                // discriminant (encoded in niche/tag) and variant index are the same.
                 let variants_start = niche_variants.start().as_u32();
                 let variants_end = niche_variants.end().as_u32();
-                let raw_discr = raw_discr
-                    .not_undef()
-                    .map_err(|_| err_ub!(InvalidDiscriminant(ScalarMaybeUninit::Uninit)))?;
-                match raw_discr.to_bits_or_ptr(discr_val.layout.size, self) {
+                let variant = match tag_val.to_bits_or_ptr(tag_layout.size, self) {
                     Err(ptr) => {
                         // The niche must be just 0 (which an inbounds pointer value never is)
                         let ptr_valid = niche_start == 0
                             && variants_start == variants_end
                             && !self.memory.ptr_may_be_null(ptr);
                         if !ptr_valid {
-                            throw_ub!(InvalidDiscriminant(raw_discr.erase_tag().into()))
+                            throw_ub!(InvalidDiscriminant(tag_val.erase_tag()))
                         }
-                        (u128::from(dataful_variant.as_u32()), dataful_variant)
+                        dataful_variant
                     }
-                    Ok(raw_discr) => {
+                    Ok(tag_bits) => {
                         // We need to use machine arithmetic to get the relative variant idx:
-                        // variant_index_relative = discr_val - niche_start_val
-                        let discr_layout =
-                            self.layout_of(discr_layout.value.to_int_ty(*self.tcx))?;
-                        let discr_val = ImmTy::from_uint(raw_discr, discr_layout);
-                        let niche_start_val = ImmTy::from_uint(niche_start, discr_layout);
+                        // variant_index_relative = tag_val - niche_start_val
+                        let tag_val = ImmTy::from_uint(tag_bits, tag_layout);
+                        let niche_start_val = ImmTy::from_uint(niche_start, tag_layout);
                         let variant_index_relative_val =
-                            self.binary_op(mir::BinOp::Sub, discr_val, niche_start_val)?;
+                            self.binary_op(mir::BinOp::Sub, tag_val, niche_start_val)?;
                         let variant_index_relative = variant_index_relative_val
                             .to_scalar()?
-                            .assert_bits(discr_val.layout.size);
+                            .assert_bits(tag_val.layout.size);
                         // Check if this is in the range that indicates an actual discriminant.
                         if variant_index_relative <= u128::from(variants_end - variants_start) {
                             let variant_index_relative = u32::try_from(variant_index_relative)
@@ -676,7 +699,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             let variant_index = variants_start
                                 .checked_add(variant_index_relative)
                                 .expect("overflow computing absolute variant idx");
-                            let variants_len = rval
+                            let variants_len = op
                                 .layout
                                 .ty
                                 .ty_adt_def()
@@ -684,12 +707,16 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                                 .variants
                                 .len();
                             assert!(usize::try_from(variant_index).unwrap() < variants_len);
-                            (u128::from(variant_index), VariantIdx::from_u32(variant_index))
+                            VariantIdx::from_u32(variant_index)
                         } else {
-                            (u128::from(dataful_variant.as_u32()), dataful_variant)
+                            dataful_variant
                         }
                     }
-                }
+                };
+                // Compute the size of the scalar we need to return.
+                // No need to cast, because the variant index directly serves as discriminant and is
+                // encoded in the tag.
+                (Scalar::from_uint(variant.as_u32(), discr_layout.size), variant)
             }
         })
     }
diff --git a/src/librustc_mir/interpret/place.rs b/src/librustc_mir/interpret/place.rs
index dc6967c2c49..3f0800b12b5 100644
--- a/src/librustc_mir/interpret/place.rs
+++ b/src/librustc_mir/interpret/place.rs
@@ -638,6 +638,14 @@ where
         }
 
         self.dump_place(place_ty.place);
+        // Sanity-check the type we ended up with.
+        debug_assert!(mir_assign_valid_types(
+            *self.tcx,
+            self.layout_of(self.subst_from_current_frame_and_normalize_erasing_regions(
+                place.ty(&self.frame().body.local_decls, *self.tcx).ty
+            ))?,
+            place_ty.layout,
+        ));
         Ok(place_ty)
     }
 
diff --git a/src/librustc_mir/interpret/step.rs b/src/librustc_mir/interpret/step.rs
index fd9815975c1..bd4df788057 100644
--- a/src/librustc_mir/interpret/step.rs
+++ b/src/librustc_mir/interpret/step.rs
@@ -262,8 +262,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             Discriminant(place) => {
                 let op = self.eval_place_to_op(place, None)?;
                 let discr_val = self.read_discriminant(op)?.0;
-                let size = dest.layout.size;
-                self.write_scalar(Scalar::from_uint(discr_val, size), dest)?;
+                self.write_scalar(discr_val, dest)?;
             }
         }
 
diff --git a/src/librustc_mir/interpret/validity.rs b/src/librustc_mir/interpret/validity.rs
index c83555d65fa..e962dfb2b3e 100644
--- a/src/librustc_mir/interpret/validity.rs
+++ b/src/librustc_mir/interpret/validity.rs
@@ -227,7 +227,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 let mut name = None;
                 if let Some(def_id) = def_id.as_local() {
                     let tables = self.ecx.tcx.typeck_tables_of(def_id);
-                    if let Some(upvars) = tables.upvar_list.get(&def_id.to_def_id()) {
+                    if let Some(upvars) = tables.closure_captures.get(&def_id.to_def_id()) {
                         // Sometimes the index is beyond the number of upvars (seen
                         // for a generator).
                         if let Some((&var_hir_id, _)) = upvars.get_index(field) {
diff --git a/src/librustc_mir/monomorphize/collector.rs b/src/librustc_mir/monomorphize/collector.rs
index c75e8414e8c..6c96b9a66ad 100644
--- a/src/librustc_mir/monomorphize/collector.rs
+++ b/src/librustc_mir/monomorphize/collector.rs
@@ -430,7 +430,7 @@ fn check_recursion_limit<'tcx>(
     // Code that needs to instantiate the same function recursively
     // more than the recursion limit is assumed to be causing an
     // infinite expansion.
-    if adjusted_recursion_depth > tcx.sess.recursion_limit() {
+    if !tcx.sess.recursion_limit().value_within_limit(adjusted_recursion_depth) {
         let error = format!("reached the recursion limit while instantiating `{}`", instance);
         if let Some(def_id) = def_id.as_local() {
             let hir_id = tcx.hir().as_local_hir_id(def_id);
@@ -463,7 +463,7 @@ fn check_type_length_limit<'tcx>(tcx: TyCtxt<'tcx>, instance: Instance<'tcx>) {
     // which means that rustc basically hangs.
     //
     // Bail out in these cases to avoid that bad user experience.
-    if type_length > tcx.sess.type_length_limit() {
+    if !tcx.sess.type_length_limit().value_within_limit(type_length) {
         // The instance name is already known to be too long for rustc.
         // Show only the first and last 32 characters to avoid blasting
         // the user's terminal with thousands of lines of type-name.
@@ -632,14 +632,21 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
                 let ty = self.monomorphize(ty);
                 visit_drop_use(self.tcx, ty, true, self.output);
             }
+            mir::TerminatorKind::InlineAsm { ref operands, .. } => {
+                for op in operands {
+                    if let mir::InlineAsmOperand::SymFn { value } = op {
+                        let fn_ty = self.monomorphize(value.literal.ty);
+                        visit_fn_use(self.tcx, fn_ty, false, &mut self.output);
+                    }
+                }
+            }
             mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::SwitchInt { .. }
             | mir::TerminatorKind::Resume
             | mir::TerminatorKind::Abort
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::Unreachable
-            | mir::TerminatorKind::Assert { .. }
-            | mir::TerminatorKind::InlineAsm { .. } => {}
+            | mir::TerminatorKind::Assert { .. } => {}
             mir::TerminatorKind::GeneratorDrop
             | mir::TerminatorKind::Yield { .. }
             | mir::TerminatorKind::FalseEdges { .. }
diff --git a/src/librustc_mir/transform/check_unsafety.rs b/src/librustc_mir/transform/check_unsafety.rs
index a335fa2de41..e32bccc85ee 100644
--- a/src/librustc_mir/transform/check_unsafety.rs
+++ b/src/librustc_mir/transform/check_unsafety.rs
@@ -2,6 +2,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def_id::{DefId, LocalDefId};
+use rustc_hir::hir_id::HirId;
 use rustc_hir::intravisit;
 use rustc_hir::Node;
 use rustc_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
@@ -9,7 +10,8 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::cast::CastTy;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNUSED_UNSAFE};
+use rustc_session::lint::builtin::{SAFE_PACKED_BORROWS, UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
+use rustc_session::lint::Level;
 use rustc_span::symbol::{sym, Symbol};
 
 use std::ops::Bound;
@@ -202,25 +204,30 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
 
         if context.is_borrow() {
             if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
-                let source_info = self.source_info;
-                let lint_root = self.body.source_scopes[source_info.scope]
-                    .local_data
-                    .as_ref()
-                    .assert_crate_local()
-                    .lint_root;
                 self.require_unsafe(
                     "borrow of packed field",
                     "fields of packed structs might be misaligned: dereferencing a \
                     misaligned pointer or even just creating a misaligned reference \
                     is undefined behavior",
-                    UnsafetyViolationKind::BorrowPacked(lint_root),
+                    UnsafetyViolationKind::BorrowPacked,
                 );
             }
         }
 
         for (i, elem) in place.projection.iter().enumerate() {
             let proj_base = &place.projection[..i];
-            let old_source_info = self.source_info;
+            if context.is_borrow() {
+                if util::is_disaligned(self.tcx, self.body, self.param_env, *place) {
+                    self.require_unsafe(
+                        "borrow of packed field",
+                        "fields of packed structs might be misaligned: dereferencing a \
+                        misaligned pointer or even just creating a misaligned reference \
+                        is undefined behavior",
+                        UnsafetyViolationKind::BorrowPacked,
+                    );
+                }
+            }
+            let source_info = self.source_info;
             if let [] = proj_base {
                 let decl = &self.body.local_decls[place.local];
                 if decl.internal {
@@ -301,7 +308,7 @@ impl<'a, 'tcx> Visitor<'tcx> for UnsafetyChecker<'a, 'tcx> {
                 }
                 _ => {}
             }
-            self.source_info = old_source_info;
+            self.source_info = source_info;
         }
     }
 }
@@ -314,9 +321,15 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
         kind: UnsafetyViolationKind,
     ) {
         let source_info = self.source_info;
+        let lint_root = self.body.source_scopes[self.source_info.scope]
+            .local_data
+            .as_ref()
+            .assert_crate_local()
+            .lint_root;
         self.register_violations(
             &[UnsafetyViolation {
                 source_info,
+                lint_root,
                 description: Symbol::intern(description),
                 details: Symbol::intern(details),
                 kind,
@@ -343,7 +356,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                     match violation.kind {
                         UnsafetyViolationKind::GeneralAndConstFn
                         | UnsafetyViolationKind::General => {}
-                        UnsafetyViolationKind::BorrowPacked(_) => {
+                        UnsafetyViolationKind::BorrowPacked => {
                             if self.min_const_fn {
                                 // const fns don't need to be backwards compatible and can
                                 // emit these violations as a hard error instead of a backwards
@@ -351,6 +364,26 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                                 violation.kind = UnsafetyViolationKind::General;
                             }
                         }
+                        UnsafetyViolationKind::UnsafeFn
+                        | UnsafetyViolationKind::UnsafeFnBorrowPacked => {
+                            bug!("`UnsafetyViolationKind::UnsafeFn` in an `Safe` context")
+                        }
+                    }
+                    if !self.violations.contains(&violation) {
+                        self.violations.push(violation)
+                    }
+                }
+                false
+            }
+            // With the RFC 2585, no longer allow `unsafe` operations in `unsafe fn`s
+            Safety::FnUnsafe if self.tcx.features().unsafe_block_in_unsafe_fn => {
+                for violation in violations {
+                    let mut violation = *violation;
+
+                    if violation.kind == UnsafetyViolationKind::BorrowPacked {
+                        violation.kind = UnsafetyViolationKind::UnsafeFnBorrowPacked;
+                    } else {
+                        violation.kind = UnsafetyViolationKind::UnsafeFn;
                     }
                     if !self.violations.contains(&violation) {
                         self.violations.push(violation)
@@ -358,7 +391,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                 }
                 false
             }
-            // `unsafe` function bodies allow unsafe without additional unsafe blocks
+            // `unsafe` function bodies allow unsafe without additional unsafe blocks (before RFC 2585)
             Safety::BuiltinUnsafe | Safety::FnUnsafe => true,
             Safety::ExplicitUnsafe(hir_id) => {
                 // mark unsafe block as used if there are any unsafe operations inside
@@ -373,7 +406,7 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                             UnsafetyViolationKind::GeneralAndConstFn => {}
                             // these things are forbidden in const fns
                             UnsafetyViolationKind::General
-                            | UnsafetyViolationKind::BorrowPacked(_) => {
+                            | UnsafetyViolationKind::BorrowPacked => {
                                 let mut violation = *violation;
                                 // const fns don't need to be backwards compatible and can
                                 // emit these violations as a hard error instead of a backwards
@@ -383,6 +416,10 @@ impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
                                     self.violations.push(violation)
                                 }
                             }
+                            UnsafetyViolationKind::UnsafeFn
+                            | UnsafetyViolationKind::UnsafeFnBorrowPacked => bug!(
+                                "`UnsafetyViolationKind::UnsafeFn` in an `ExplicitUnsafe` context"
+                            ),
                         }
                     }
                 }
@@ -542,8 +579,8 @@ fn unsafety_check_result(tcx: TyCtxt<'_>, def_id: LocalDefId) -> UnsafetyCheckRe
     }
 }
 
-fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: DefId) {
-    let lint_hir_id = tcx.hir().as_local_hir_id(def_id.expect_local());
+fn unsafe_derive_on_repr_packed(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    let lint_hir_id = tcx.hir().as_local_hir_id(def_id);
 
     tcx.struct_span_lint_hir(SAFE_PACKED_BORROWS, lint_hir_id, tcx.def_span(def_id), |lint| {
         // FIXME: when we make this a hard error, this should have its
@@ -575,9 +612,12 @@ fn is_enclosed(
             kind: hir::ItemKind::Fn(ref sig, _, _), ..
         })) = tcx.hir().find(parent_id)
         {
-            match sig.header.unsafety {
-                hir::Unsafety::Unsafe => Some(("fn".to_string(), parent_id)),
-                hir::Unsafety::Normal => None,
+            if sig.header.unsafety == hir::Unsafety::Unsafe
+                && !tcx.features().unsafe_block_in_unsafe_fn
+            {
+                Some(("fn".to_string(), parent_id))
+            } else {
+                None
             }
         } else {
             is_enclosed(tcx, used_unsafe, parent_id)
@@ -619,44 +659,52 @@ fn builtin_derive_def_id(tcx: TyCtxt<'_>, def_id: DefId) -> Option<DefId> {
     }
 }
 
-pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
+pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: LocalDefId) {
     debug!("check_unsafety({:?})", def_id);
 
     // closures are handled by their parent fn.
-    if tcx.is_closure(def_id) {
+    if tcx.is_closure(def_id.to_def_id()) {
         return;
     }
 
-    let UnsafetyCheckResult { violations, unsafe_blocks } =
-        tcx.unsafety_check_result(def_id.expect_local());
+    let UnsafetyCheckResult { violations, unsafe_blocks } = tcx.unsafety_check_result(def_id);
 
-    for &UnsafetyViolation { source_info, description, details, kind } in violations.iter() {
+    for &UnsafetyViolation { source_info, lint_root, description, details, kind } in
+        violations.iter()
+    {
         // Report an error.
+        let unsafe_fn_msg =
+            if unsafe_op_in_unsafe_fn_allowed(tcx, lint_root) { " function or" } else { "" };
+
         match kind {
             UnsafetyViolationKind::GeneralAndConstFn | UnsafetyViolationKind::General => {
+                // once
                 struct_span_err!(
                     tcx.sess,
                     source_info.span,
                     E0133,
-                    "{} is unsafe and requires unsafe function or block",
-                    description
+                    "{} is unsafe and requires unsafe{} block",
+                    description,
+                    unsafe_fn_msg,
                 )
                 .span_label(source_info.span, &*description.as_str())
                 .note(&details.as_str())
                 .emit();
             }
-            UnsafetyViolationKind::BorrowPacked(lint_hir_id) => {
-                if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id) {
-                    tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id);
+            UnsafetyViolationKind::BorrowPacked => {
+                if let Some(impl_def_id) = builtin_derive_def_id(tcx, def_id.to_def_id()) {
+                    // If a method is defined in the local crate,
+                    // the impl containing that method should also be.
+                    tcx.ensure().unsafe_derive_on_repr_packed(impl_def_id.expect_local());
                 } else {
                     tcx.struct_span_lint_hir(
                         SAFE_PACKED_BORROWS,
-                        lint_hir_id,
+                        lint_root,
                         source_info.span,
                         |lint| {
                             lint.build(&format!(
-                                "{} is unsafe and requires unsafe function or block (error E0133)",
-                                description
+                                "{} is unsafe and requires unsafe{} block (error E0133)",
+                                description, unsafe_fn_msg,
                             ))
                             .note(&details.as_str())
                             .emit()
@@ -664,6 +712,49 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
                     )
                 }
             }
+            UnsafetyViolationKind::UnsafeFn => tcx.struct_span_lint_hir(
+                UNSAFE_OP_IN_UNSAFE_FN,
+                lint_root,
+                source_info.span,
+                |lint| {
+                    lint.build(&format!(
+                        "{} is unsafe and requires unsafe block (error E0133)",
+                        description,
+                    ))
+                    .span_label(source_info.span, &*description.as_str())
+                    .note(&details.as_str())
+                    .emit();
+                },
+            ),
+            UnsafetyViolationKind::UnsafeFnBorrowPacked => {
+                // When `unsafe_op_in_unsafe_fn` is disallowed, the behavior of safe and unsafe functions
+                // should be the same in terms of warnings and errors. Therefore, with `#[warn(safe_packed_borrows)]`,
+                // a safe packed borrow should emit a warning *but not an error* in an unsafe function,
+                // just like in a safe function, even if `unsafe_op_in_unsafe_fn` is `deny`.
+                //
+                // Also, `#[warn(unsafe_op_in_unsafe_fn)]` can't cause any new errors. Therefore, with
+                // `#[deny(safe_packed_borrows)]` and `#[warn(unsafe_op_in_unsafe_fn)]`, a packed borrow
+                // should only issue a warning for the sake of backwards compatibility.
+                //
+                // The solution those 2 expectations is to always take the minimum of both lints.
+                // This prevent any new errors (unless both lints are explicitely set to `deny`).
+                let lint = if tcx.lint_level_at_node(SAFE_PACKED_BORROWS, lint_root).0
+                    <= tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, lint_root).0
+                {
+                    SAFE_PACKED_BORROWS
+                } else {
+                    UNSAFE_OP_IN_UNSAFE_FN
+                };
+                tcx.struct_span_lint_hir(&lint, lint_root, source_info.span, |lint| {
+                    lint.build(&format!(
+                        "{} is unsafe and requires unsafe block (error E0133)",
+                        description,
+                    ))
+                    .span_label(source_info.span, &*description.as_str())
+                    .note(&details.as_str())
+                    .emit();
+                })
+            }
         }
     }
 
@@ -683,3 +774,7 @@ pub fn check_unsafety(tcx: TyCtxt<'_>, def_id: DefId) {
         report_unused_unsafe(tcx, &unsafe_used, block_id);
     }
 }
+
+fn unsafe_op_in_unsafe_fn_allowed(tcx: TyCtxt<'_>, id: HirId) -> bool {
+    tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, id).0 == Level::Allow
+}
diff --git a/src/librustc_mir_build/build/block.rs b/src/librustc_mir_build/build/block.rs
index fa783ddcf40..4e4f0dc74cb 100644
--- a/src/librustc_mir_build/build/block.rs
+++ b/src/librustc_mir_build/build/block.rs
@@ -4,6 +4,8 @@ use crate::build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
 use crate::hair::*;
 use rustc_hir as hir;
 use rustc_middle::mir::*;
+use rustc_session::lint::builtin::UNSAFE_OP_IN_UNSAFE_FN;
+use rustc_session::lint::Level;
 use rustc_span::Span;
 
 impl<'a, 'tcx> Builder<'a, 'tcx> {
@@ -217,6 +219,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 assert_eq!(self.push_unsafe_count, 0);
                 match self.unpushed_unsafe {
                     Safety::Safe => {}
+                    // no longer treat `unsafe fn`s as `unsafe` contexts (see RFC #2585)
+                    Safety::FnUnsafe
+                        if self.hir.tcx().lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, hir_id).0
+                            != Level::Allow => {}
                     _ => return,
                 }
                 self.unpushed_unsafe = Safety::ExplicitUnsafe(hir_id);
@@ -231,7 +237,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     .push_unsafe_count
                     .checked_sub(1)
                     .unwrap_or_else(|| span_bug!(span, "unsafe count underflow"));
-                if self.push_unsafe_count == 0 { Some(self.unpushed_unsafe) } else { None }
+                if self.push_unsafe_count == 0 {
+                    Some(self.unpushed_unsafe)
+                } else {
+                    None
+                }
             }
         };
 
diff --git a/src/librustc_mir_build/build/mod.rs b/src/librustc_mir_build/build/mod.rs
index b30b57ea921..3d821aa55a1 100644
--- a/src/librustc_mir_build/build/mod.rs
+++ b/src/librustc_mir_build/build/mod.rs
@@ -790,11 +790,11 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         let hir_tables = self.hir.tables();
 
         // In analyze_closure() in upvar.rs we gathered a list of upvars used by a
-        // closure and we stored in a map called upvar_list in TypeckTables indexed
+        // indexed closure and we stored in a map called closure_captures in TypeckTables
         // with the closure's DefId. Here, we run through that vec of UpvarIds for
         // the given closure and use the necessary information to create upvar
         // debuginfo and to fill `self.upvar_mutbls`.
-        if let Some(upvars) = hir_tables.upvar_list.get(&fn_def_id) {
+        if let Some(upvars) = hir_tables.closure_captures.get(&fn_def_id) {
             let closure_env_arg = Local::new(1);
             let mut closure_env_projs = vec![];
             let mut closure_ty = self.local_decls[closure_env_arg].ty;
diff --git a/src/librustc_mir_build/hair/cx/expr.rs b/src/librustc_mir_build/hair/cx/expr.rs
index 056cb9d98ce..969bb4f7259 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -885,7 +885,7 @@ fn convert_var<'tcx>(
 ) -> ExprKind<'tcx> {
     let upvar_index = cx
         .tables()
-        .upvar_list
+        .closure_captures
         .get(&cx.body_owner)
         .and_then(|upvars| upvars.get_full(&var_hir_id).map(|(i, _, _)| i));
 
diff --git a/src/librustc_parse/Cargo.toml b/src/librustc_parse/Cargo.toml
index 0d31a8c7bc1..7164c678808 100644
--- a/src/librustc_parse/Cargo.toml
+++ b/src/librustc_parse/Cargo.toml
@@ -12,7 +12,6 @@ doctest = false
 [dependencies]
 bitflags = "1.0"
 log = "0.4"
-smallvec = { version = "1.0", features = ["union", "may_dangle"] }
 rustc_ast_pretty = { path = "../librustc_ast_pretty" }
 rustc_data_structures = { path = "../librustc_data_structures" }
 rustc_feature = { path = "../librustc_feature" }
diff --git a/src/librustc_parse/lib.rs b/src/librustc_parse/lib.rs
index 8ca3f6c5768..be86b4b7c77 100644
--- a/src/librustc_parse/lib.rs
+++ b/src/librustc_parse/lib.rs
@@ -7,18 +7,14 @@
 #![feature(or_patterns)]
 
 use rustc_ast::ast;
-use rustc_ast::token::{self, DelimToken, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{self, IsJoint, TokenStream, TokenTree};
+use rustc_ast::token::{self, Nonterminal};
+use rustc_ast::tokenstream::{self, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Diagnostic, FatalError, Level, PResult};
 use rustc_session::parse::ParseSess;
-use rustc_span::symbol::kw;
-use rustc_span::{FileName, SourceFile, Span, DUMMY_SP};
+use rustc_span::{FileName, SourceFile, Span};
 
-use smallvec::SmallVec;
-
-use std::mem;
 use std::path::Path;
 use std::str;
 
@@ -310,7 +306,7 @@ pub fn nt_to_tokenstream(nt: &Nonterminal, sess: &ParseSess, span: Span) -> Toke
     // modifications, including adding/removing typically non-semantic
     // tokens such as extra braces and commas, don't happen.
     if let Some(tokens) = tokens {
-        if tokenstream_probably_equal_for_proc_macro(&tokens, &tokens_for_real, sess) {
+        if tokens.probably_equal_for_proc_macro(&tokens_for_real) {
             return tokens;
         }
         info!(
@@ -385,203 +381,3 @@ fn prepend_attrs(
     builder.push(tokens.clone());
     Some(builder.build())
 }
-
-// See comments in `Nonterminal::to_tokenstream` for why we care about
-// *probably* equal here rather than actual equality
-//
-// This is otherwise the same as `eq_unspanned`, only recursing with a
-// different method.
-pub fn tokenstream_probably_equal_for_proc_macro(
-    first: &TokenStream,
-    other: &TokenStream,
-    sess: &ParseSess,
-) -> bool {
-    // When checking for `probably_eq`, we ignore certain tokens that aren't
-    // preserved in the AST. Because they are not preserved, the pretty
-    // printer arbitrarily adds or removes them when printing as token
-    // streams, making a comparison between a token stream generated from an
-    // AST and a token stream which was parsed into an AST more reliable.
-    fn semantic_tree(tree: &TokenTree) -> bool {
-        if let TokenTree::Token(token) = tree {
-            if let
-                // The pretty printer tends to add trailing commas to
-                // everything, and in particular, after struct fields.
-                | token::Comma
-                // The pretty printer emits `NoDelim` as whitespace.
-                | token::OpenDelim(DelimToken::NoDelim)
-                | token::CloseDelim(DelimToken::NoDelim)
-                // The pretty printer collapses many semicolons into one.
-                | token::Semi
-                // The pretty printer collapses whitespace arbitrarily and can
-                // introduce whitespace from `NoDelim`.
-                | token::Whitespace
-                // The pretty printer can turn `$crate` into `::crate_name`
-                | token::ModSep = token.kind {
-                return false;
-            }
-        }
-        true
-    }
-
-    // When comparing two `TokenStream`s, we ignore the `IsJoint` information.
-    //
-    // However, `rustc_parse::lexer::tokentrees::TokenStreamBuilder` will
-    // use `Token.glue` on adjacent tokens with the proper `IsJoint`.
-    // Since we are ignoreing `IsJoint`, a 'glued' token (e.g. `BinOp(Shr)`)
-    // and its 'split'/'unglued' compoenents (e.g. `Gt, Gt`) are equivalent
-    // when determining if two `TokenStream`s are 'probably equal'.
-    //
-    // Therefore, we use `break_two_token_op` to convert all tokens
-    // to the 'unglued' form (if it exists). This ensures that two
-    // `TokenStream`s which differ only in how their tokens are glued
-    // will be considered 'probably equal', which allows us to keep spans.
-    //
-    // This is important when the original `TokenStream` contained
-    // extra spaces (e.g. `f :: < Vec < _ > > ( ) ;'). These extra spaces
-    // will be omitted when we pretty-print, which can cause the original
-    // and reparsed `TokenStream`s to differ in the assignment of `IsJoint`,
-    // leading to some tokens being 'glued' together in one stream but not
-    // the other. See #68489 for more details.
-    fn break_tokens(tree: TokenTree) -> impl Iterator<Item = TokenTree> {
-        // In almost all cases, we should have either zero or one levels
-        // of 'unglueing'. However, in some unusual cases, we may need
-        // to iterate breaking tokens mutliple times. For example:
-        // '[BinOpEq(Shr)] => [Gt, Ge] -> [Gt, Gt, Eq]'
-        let mut token_trees: SmallVec<[_; 2]>;
-        if let TokenTree::Token(token) = &tree {
-            let mut out = SmallVec::<[_; 2]>::new();
-            out.push(token.clone());
-            // Iterate to fixpoint:
-            // * We start off with 'out' containing our initial token, and `temp` empty
-            // * If we are able to break any tokens in `out`, then `out` will have
-            //   at least one more element than 'temp', so we will try to break tokens
-            //   again.
-            // * If we cannot break any tokens in 'out', we are done
-            loop {
-                let mut temp = SmallVec::<[_; 2]>::new();
-                let mut changed = false;
-
-                for token in out.into_iter() {
-                    if let Some((first, second)) = token.kind.break_two_token_op() {
-                        temp.push(Token::new(first, DUMMY_SP));
-                        temp.push(Token::new(second, DUMMY_SP));
-                        changed = true;
-                    } else {
-                        temp.push(token);
-                    }
-                }
-                out = temp;
-                if !changed {
-                    break;
-                }
-            }
-            token_trees = out.into_iter().map(|t| TokenTree::Token(t)).collect();
-            if token_trees.len() != 1 {
-                debug!("break_tokens: broke {:?} to {:?}", tree, token_trees);
-            }
-        } else {
-            token_trees = SmallVec::new();
-            token_trees.push(tree);
-        }
-        token_trees.into_iter()
-    }
-
-    let expand_nt = |tree: TokenTree| {
-        if let TokenTree::Token(Token { kind: TokenKind::Interpolated(nt), span }) = &tree {
-            nt_to_tokenstream(nt, sess, *span).into_trees()
-        } else {
-            TokenStream::new(vec![(tree, IsJoint::NonJoint)]).into_trees()
-        }
-    };
-
-    // Break tokens after we expand any nonterminals, so that we break tokens
-    // that are produced as a result of nonterminal expansion.
-    let mut t1 = first.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
-    let mut t2 = other.trees().filter(semantic_tree).flat_map(expand_nt).flat_map(break_tokens);
-    for (t1, t2) in t1.by_ref().zip(t2.by_ref()) {
-        if !tokentree_probably_equal_for_proc_macro(&t1, &t2, sess) {
-            return false;
-        }
-    }
-    t1.next().is_none() && t2.next().is_none()
-}
-
-// See comments in `Nonterminal::to_tokenstream` for why we care about
-// *probably* equal here rather than actual equality
-crate fn token_probably_equal_for_proc_macro(first: &Token, other: &Token) -> bool {
-    use TokenKind::*;
-
-    if mem::discriminant(&first.kind) != mem::discriminant(&other.kind) {
-        return false;
-    }
-    match (&first.kind, &other.kind) {
-        (&Eq, &Eq)
-        | (&Lt, &Lt)
-        | (&Le, &Le)
-        | (&EqEq, &EqEq)
-        | (&Ne, &Ne)
-        | (&Ge, &Ge)
-        | (&Gt, &Gt)
-        | (&AndAnd, &AndAnd)
-        | (&OrOr, &OrOr)
-        | (&Not, &Not)
-        | (&Tilde, &Tilde)
-        | (&At, &At)
-        | (&Dot, &Dot)
-        | (&DotDot, &DotDot)
-        | (&DotDotDot, &DotDotDot)
-        | (&DotDotEq, &DotDotEq)
-        | (&Comma, &Comma)
-        | (&Semi, &Semi)
-        | (&Colon, &Colon)
-        | (&ModSep, &ModSep)
-        | (&RArrow, &RArrow)
-        | (&LArrow, &LArrow)
-        | (&FatArrow, &FatArrow)
-        | (&Pound, &Pound)
-        | (&Dollar, &Dollar)
-        | (&Question, &Question)
-        | (&Whitespace, &Whitespace)
-        | (&Comment, &Comment)
-        | (&Eof, &Eof) => true,
-
-        (&BinOp(a), &BinOp(b)) | (&BinOpEq(a), &BinOpEq(b)) => a == b,
-
-        (&OpenDelim(a), &OpenDelim(b)) | (&CloseDelim(a), &CloseDelim(b)) => a == b,
-
-        (&DocComment(a), &DocComment(b)) | (&Shebang(a), &Shebang(b)) => a == b,
-
-        (&Literal(a), &Literal(b)) => a == b,
-
-        (&Lifetime(a), &Lifetime(b)) => a == b,
-        (&Ident(a, b), &Ident(c, d)) => {
-            b == d && (a == c || a == kw::DollarCrate || c == kw::DollarCrate)
-        }
-
-        // Expanded by `tokenstream_probably_equal_for_proc_macro`
-        (&Interpolated(_), &Interpolated(_)) => unreachable!(),
-
-        _ => panic!("forgot to add a token?"),
-    }
-}
-
-// See comments in `Nonterminal::to_tokenstream` for why we care about
-// *probably* equal here rather than actual equality
-//
-// This is otherwise the same as `eq_unspanned`, only recursing with a
-// different method.
-pub fn tokentree_probably_equal_for_proc_macro(
-    first: &TokenTree,
-    other: &TokenTree,
-    sess: &ParseSess,
-) -> bool {
-    match (first, other) {
-        (TokenTree::Token(token), TokenTree::Token(token2)) => {
-            token_probably_equal_for_proc_macro(token, token2)
-        }
-        (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
-            delim == delim2 && tokenstream_probably_equal_for_proc_macro(&tts, &tts2, sess)
-        }
-        _ => false,
-    }
-}
diff --git a/src/librustc_parse/parser/item.rs b/src/librustc_parse/parser/item.rs
index 4fe0453e9c8..6f13d7994d1 100644
--- a/src/librustc_parse/parser/item.rs
+++ b/src/librustc_parse/parser/item.rs
@@ -106,11 +106,20 @@ impl<'a> Parser<'a> {
         });
 
         let mut unclosed_delims = vec![];
-        let (mut item, tokens) = self.collect_tokens(|this| {
+        let has_attrs = !attrs.is_empty();
+        let parse_item = |this: &mut Self| {
             let item = this.parse_item_common_(attrs, mac_allowed, attrs_allowed, req_name);
             unclosed_delims.append(&mut this.unclosed_delims);
             item
-        })?;
+        };
+
+        let (mut item, tokens) = if has_attrs {
+            let (item, tokens) = self.collect_tokens(parse_item)?;
+            (item, Some(tokens))
+        } else {
+            (parse_item(self)?, None)
+        };
+
         self.unclosed_delims.append(&mut unclosed_delims);
 
         // Once we've parsed an item and recorded the tokens we got while
@@ -127,9 +136,11 @@ impl<'a> Parser<'a> {
         // it (bad!). To work around this case for now we just avoid recording
         // `tokens` if we detect any inner attributes. This should help keep
         // expansion correct, but we should fix this bug one day!
-        if let Some(item) = &mut item {
-            if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
-                item.tokens = Some(tokens);
+        if let Some(tokens) = tokens {
+            if let Some(item) = &mut item {
+                if !item.attrs.iter().any(|attr| attr.style == AttrStyle::Inner) {
+                    item.tokens = Some(tokens);
+                }
             }
         }
         Ok(item)
diff --git a/src/librustc_passes/liveness.rs b/src/librustc_passes/liveness.rs
index ece78d02512..55978afc594 100644
--- a/src/librustc_passes/liveness.rs
+++ b/src/librustc_passes/liveness.rs
@@ -76,22 +76,10 @@
 //!   is not just used to generate a new value. For example, `x += 1` is
 //!   a read but not a use. This is used to generate better warnings.
 //!
-//! ## Special Variables
+//! ## Special nodes and variables
 //!
-//! We generate various special variables for various, well, special purposes.
-//! These are described in the `specials` struct:
-//!
-//! - `exit_ln`: a live node that is generated to represent every 'exit' from
-//!   the function, whether it be by explicit return, panic, or other means.
-//!
-//! - `fallthrough_ln`: a live node that represents a fallthrough
-//!
-//! - `clean_exit_var`: a synthetic variable that is only 'read' from the
-//!   fallthrough node. It is only live if the function could converge
-//!   via means other than an explicit `return` expression. That is, it is
-//!   only dead if the end of the function's block can never be reached.
-//!   It is the responsibility of typeck to ensure that there are no
-//!   `return` expressions in a function declared as diverging.
+//! We generate various special nodes for various, well, special purposes.
+//! These are described in the `Specials` struct.
 
 use self::LiveNodeKind::*;
 use self::VarKind::*;
@@ -140,6 +128,7 @@ enum LiveNodeKind {
     UpvarNode(Span),
     ExprNode(Span),
     VarDefNode(Span),
+    ClosureNode,
     ExitNode,
 }
 
@@ -149,6 +138,7 @@ fn live_node_kind_to_string(lnk: LiveNodeKind, tcx: TyCtxt<'_>) -> String {
         UpvarNode(s) => format!("Upvar node [{}]", sm.span_to_string(s)),
         ExprNode(s) => format!("Expr node [{}]", sm.span_to_string(s)),
         VarDefNode(s) => format!("Var def node [{}]", sm.span_to_string(s)),
+        ClosureNode => "Closure node".to_owned(),
         ExitNode => "Exit node".to_owned(),
     }
 }
@@ -253,7 +243,7 @@ struct LocalInfo {
 enum VarKind {
     Param(HirId, Symbol),
     Local(LocalInfo),
-    CleanExit,
+    Upvar(HirId, Symbol),
 }
 
 struct IrMaps<'tcx> {
@@ -306,10 +296,9 @@ impl IrMaps<'tcx> {
         self.num_vars += 1;
 
         match vk {
-            Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) => {
+            Local(LocalInfo { id: node_id, .. }) | Param(node_id, _) | Upvar(node_id, _) => {
                 self.variable_map.insert(node_id, v);
             }
-            CleanExit => {}
         }
 
         debug!("{:?} is {:?}", v, vk);
@@ -328,15 +317,14 @@ impl IrMaps<'tcx> {
 
     fn variable_name(&self, var: Variable) -> String {
         match self.var_kinds[var.get()] {
-            Local(LocalInfo { name, .. }) | Param(_, name) => name.to_string(),
-            CleanExit => "<clean-exit>".to_owned(),
+            Local(LocalInfo { name, .. }) | Param(_, name) | Upvar(_, name) => name.to_string(),
         }
     }
 
     fn variable_is_shorthand(&self, var: Variable) -> bool {
         match self.var_kinds[var.get()] {
             Local(LocalInfo { is_shorthand, .. }) => is_shorthand,
-            Param(..) | CleanExit => false,
+            Param(..) | Upvar(..) => false,
         }
     }
 
@@ -357,7 +345,7 @@ fn visit_fn<'tcx>(
     sp: Span,
     id: hir::HirId,
 ) {
-    debug!("visit_fn");
+    debug!("visit_fn {:?}", id);
 
     // swap in a new set of IR maps for this function body:
     let def_id = ir.tcx.hir().local_def_id(id);
@@ -377,6 +365,14 @@ fn visit_fn<'tcx>(
 
     let body = ir.tcx.hir().body(body_id);
 
+    if let Some(upvars) = ir.tcx.upvars_mentioned(def_id) {
+        for (&var_hir_id, _upvar) in upvars {
+            debug!("adding upvar {:?}", var_hir_id);
+            let var_name = ir.tcx.hir().name(var_hir_id);
+            fn_maps.add_variable(Upvar(var_hir_id, var_name));
+        }
+    }
+
     for param in body.params {
         let is_shorthand = match param.pat.kind {
             rustc_hir::PatKind::Struct(..) => true,
@@ -399,10 +395,12 @@ fn visit_fn<'tcx>(
 
     // compute liveness
     let mut lsets = Liveness::new(&mut fn_maps, def_id);
-    let entry_ln = lsets.compute(&body.value);
+    let entry_ln = lsets.compute(fk, &body, sp, id);
+    lsets.log_liveness(entry_ln, id);
 
     // check for various error conditions
     lsets.visit_body(body);
+    lsets.warn_about_unused_upvars(entry_ln);
     lsets.warn_about_unused_args(body, entry_ln);
 }
 
@@ -462,11 +460,8 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
         // live nodes required for uses or definitions of variables:
         hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
             debug!("expr {}: path that leads to {:?}", expr.hir_id, path.res);
-            if let Res::Local(var_hir_id) = path.res {
-                let upvars = ir.tcx.upvars_mentioned(ir.body_owner);
-                if !upvars.map_or(false, |upvars| upvars.contains_key(&var_hir_id)) {
-                    ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
-                }
+            if let Res::Local(_var_hir_id) = path.res {
+                ir.add_live_node_for_node(expr.hir_id, ExprNode(expr.span));
             }
             intravisit::walk_expr(ir, expr);
         }
@@ -482,16 +477,9 @@ fn visit_expr<'tcx>(ir: &mut IrMaps<'tcx>, expr: &'tcx Expr<'tcx>) {
             let mut call_caps = Vec::new();
             let closure_def_id = ir.tcx.hir().local_def_id(expr.hir_id);
             if let Some(upvars) = ir.tcx.upvars_mentioned(closure_def_id) {
-                let parent_upvars = ir.tcx.upvars_mentioned(ir.body_owner);
-                call_caps.extend(upvars.iter().filter_map(|(&var_id, upvar)| {
-                    let has_parent =
-                        parent_upvars.map_or(false, |upvars| upvars.contains_key(&var_id));
-                    if !has_parent {
-                        let upvar_ln = ir.add_live_node(UpvarNode(upvar.span));
-                        Some(CaptureInfo { ln: upvar_ln, var_hid: var_id })
-                    } else {
-                        None
-                    }
+                call_caps.extend(upvars.iter().map(|(&var_id, upvar)| {
+                    let upvar_ln = ir.add_live_node(UpvarNode(upvar.span));
+                    CaptureInfo { ln: upvar_ln, var_hid: var_id }
                 }));
             }
             ir.set_captures(expr.hir_id, call_caps);
@@ -647,9 +635,13 @@ impl RWUTable {
 
 #[derive(Copy, Clone)]
 struct Specials {
+    /// A live node representing a point of execution before closure entry &
+    /// after closure exit. Used to calculate liveness of captured variables
+    /// through calls to the same closure. Used for Fn & FnMut closures only.
+    closure_ln: LiveNode,
+    /// A live node representing every 'exit' from the function, whether it be
+    /// by explicit return, panic, or other means.
     exit_ln: LiveNode,
-    fallthrough_ln: LiveNode,
-    clean_exit_var: Variable,
 }
 
 const ACC_READ: u32 = 1;
@@ -673,14 +665,9 @@ struct Liveness<'a, 'tcx> {
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn new(ir: &'a mut IrMaps<'tcx>, def_id: LocalDefId) -> Liveness<'a, 'tcx> {
-        // Special nodes and variables:
-        // - exit_ln represents the end of the fn, either by return or panic
-        // - implicit_ret_var is a pseudo-variable that represents
-        //   an implicit return
         let specials = Specials {
+            closure_ln: ir.add_live_node(ClosureNode),
             exit_ln: ir.add_live_node(ExitNode),
-            fallthrough_ln: ir.add_live_node(ExitNode),
-            clean_exit_var: ir.add_variable(CleanExit),
         };
 
         let tables = ir.tcx.typeck_tables_of(def_id);
@@ -777,12 +764,12 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
 
     fn write_vars<F>(&self, wr: &mut dyn Write, ln: LiveNode, mut test: F) -> io::Result<()>
     where
-        F: FnMut(usize) -> LiveNode,
+        F: FnMut(usize) -> bool,
     {
         let node_base_idx = self.idx(ln, Variable(0));
         for var_idx in 0..self.ir.num_vars {
             let idx = node_base_idx + var_idx;
-            if test(idx).is_valid() {
+            if test(idx) {
                 write!(wr, " {:?}", Variable(var_idx as u32))?;
             }
         }
@@ -795,14 +782,31 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         {
             let wr = &mut wr as &mut dyn Write;
             write!(wr, "[ln({:?}) of kind {:?} reads", ln.get(), self.ir.lnk(ln));
-            self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx));
+            self.write_vars(wr, ln, |idx| self.rwu_table.get_reader(idx).is_valid());
             write!(wr, "  writes");
-            self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx));
+            self.write_vars(wr, ln, |idx| self.rwu_table.get_writer(idx).is_valid());
+            write!(wr, "  uses");
+            self.write_vars(wr, ln, |idx| self.rwu_table.get_used(idx));
+
             write!(wr, "  precedes {:?}]", self.successors[ln.get()]);
         }
         String::from_utf8(wr).unwrap()
     }
 
+    fn log_liveness(&self, entry_ln: LiveNode, hir_id: hir::HirId) {
+        // hack to skip the loop unless debug! is enabled:
+        debug!(
+            "^^ liveness computation results for body {} (entry={:?})",
+            {
+                for ln_idx in 0..self.ir.num_live_nodes {
+                    debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32)));
+                }
+                hir_id
+            },
+            entry_ln
+        );
+    }
+
     fn init_empty(&mut self, ln: LiveNode, succ_ln: LiveNode) {
         self.successors[ln.get()] = succ_ln;
 
@@ -903,30 +907,87 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         self.rwu_table.assign_unpacked(idx, rwu);
     }
 
-    fn compute(&mut self, body: &hir::Expr<'_>) -> LiveNode {
-        debug!("compute: using id for body, {:?}", body);
+    fn compute(
+        &mut self,
+        fk: FnKind<'_>,
+        body: &hir::Body<'_>,
+        span: Span,
+        id: hir::HirId,
+    ) -> LiveNode {
+        debug!("compute: using id for body, {:?}", body.value);
+
+        // # Liveness of captured variables
+        //
+        // When computing the liveness for captured variables we take into
+        // account how variable is captured (ByRef vs ByValue) and what is the
+        // closure kind (Generator / FnOnce vs Fn / FnMut).
+        //
+        // Variables captured by reference are assumed to be used on the exit
+        // from the closure.
+        //
+        // In FnOnce closures, variables captured by value are known to be dead
+        // on exit since it is impossible to call the closure again.
+        //
+        // In Fn / FnMut closures, variables captured by value are live on exit
+        // if they are live on the entry to the closure, since only the closure
+        // itself can access them on subsequent calls.
+
+        if let Some(upvars) = self.ir.tcx.upvars_mentioned(self.ir.body_owner) {
+            // Mark upvars captured by reference as used after closure exits.
+            for (&var_hir_id, upvar) in upvars.iter().rev() {
+                let upvar_id = ty::UpvarId {
+                    var_path: ty::UpvarPath { hir_id: var_hir_id },
+                    closure_expr_id: self.ir.body_owner.expect_local(),
+                };
+                match self.tables.upvar_capture(upvar_id) {
+                    ty::UpvarCapture::ByRef(_) => {
+                        let var = self.variable(var_hir_id, upvar.span);
+                        self.acc(self.s.exit_ln, var, ACC_READ | ACC_USE);
+                    }
+                    ty::UpvarCapture::ByValue => {}
+                }
+            }
+        }
 
-        // the fallthrough exit is only for those cases where we do not
-        // explicitly return:
-        let s = self.s;
-        self.init_from_succ(s.fallthrough_ln, s.exit_ln);
-        self.acc(s.fallthrough_ln, s.clean_exit_var, ACC_READ);
+        let succ = self.propagate_through_expr(&body.value, self.s.exit_ln);
 
-        let entry_ln = self.propagate_through_expr(body, s.fallthrough_ln);
+        match fk {
+            FnKind::Method(..) | FnKind::ItemFn(..) => return succ,
+            FnKind::Closure(..) => {}
+        }
 
-        // hack to skip the loop unless debug! is enabled:
-        debug!(
-            "^^ liveness computation results for body {} (entry={:?})",
-            {
-                for ln_idx in 0..self.ir.num_live_nodes {
-                    debug!("{:?}", self.ln_str(LiveNode(ln_idx as u32)));
-                }
-                body.hir_id
+        let ty = self.tables.node_type(id);
+        match ty.kind {
+            ty::Closure(_def_id, substs) => match substs.as_closure().kind() {
+                ty::ClosureKind::Fn => {}
+                ty::ClosureKind::FnMut => {}
+                ty::ClosureKind::FnOnce => return succ,
             },
-            entry_ln
-        );
+            ty::Generator(..) => return succ,
+            _ => {
+                span_bug!(span, "type of closure expr {:?} is not a closure {:?}", id, ty,);
+            }
+        };
+
+        // Propagate through calls to the closure.
+        let mut first_merge = true;
+        loop {
+            self.init_from_succ(self.s.closure_ln, succ);
+            for param in body.params {
+                param.pat.each_binding(|_bm, hir_id, _x, ident| {
+                    let var = self.variable(hir_id, ident.span);
+                    self.define(self.s.closure_ln, var);
+                })
+            }
+
+            if !self.merge_from_succ(self.s.exit_ln, self.s.closure_ln, first_merge) {
+                break;
+            }
+            first_merge = false;
+            assert_eq!(succ, self.propagate_through_expr(&body.value, self.s.exit_ln));
+        }
 
-        entry_ln
+        succ
     }
 
     fn propagate_through_block(&mut self, blk: &hir::Block<'_>, succ: LiveNode) -> LiveNode {
@@ -1363,14 +1424,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
         acc: u32,
     ) -> LiveNode {
         match path.res {
-            Res::Local(hid) => {
-                let upvars = self.ir.tcx.upvars_mentioned(self.ir.body_owner);
-                if !upvars.map_or(false, |upvars| upvars.contains_key(&hid)) {
-                    self.access_var(hir_id, hid, succ, acc, path.span)
-                } else {
-                    succ
-                }
-            }
+            Res::Local(hid) => self.access_var(hir_id, hid, succ, acc, path.span),
             _ => succ,
         }
     }
@@ -1529,16 +1583,13 @@ impl<'tcx> Liveness<'_, 'tcx> {
         match expr.kind {
             hir::ExprKind::Path(hir::QPath::Resolved(_, ref path)) => {
                 if let Res::Local(var_hid) = path.res {
-                    let upvars = self.ir.tcx.upvars_mentioned(self.ir.body_owner);
-                    if !upvars.map_or(false, |upvars| upvars.contains_key(&var_hid)) {
-                        // Assignment to an immutable variable or argument: only legal
-                        // if there is no later assignment. If this local is actually
-                        // mutable, then check for a reassignment to flag the mutability
-                        // as being used.
-                        let ln = self.live_node(expr.hir_id, expr.span);
-                        let var = self.variable(var_hid, expr.span);
-                        self.warn_about_dead_assign(vec![expr.span], expr.hir_id, ln, var);
-                    }
+                    // Assignment to an immutable variable or argument: only legal
+                    // if there is no later assignment. If this local is actually
+                    // mutable, then check for a reassignment to flag the mutability
+                    // as being used.
+                    let ln = self.live_node(expr.hir_id, expr.span);
+                    let var = self.variable(var_hid, expr.span);
+                    self.warn_about_dead_assign(vec![expr.span], expr.hir_id, ln, var);
                 }
             }
             _ => {
@@ -1554,11 +1605,60 @@ impl<'tcx> Liveness<'_, 'tcx> {
         if name.is_empty() || name.as_bytes()[0] == b'_' { None } else { Some(name) }
     }
 
+    fn warn_about_unused_upvars(&self, entry_ln: LiveNode) {
+        let upvars = match self.ir.tcx.upvars_mentioned(self.ir.body_owner) {
+            None => return,
+            Some(upvars) => upvars,
+        };
+        for (&var_hir_id, upvar) in upvars.iter() {
+            let var = self.variable(var_hir_id, upvar.span);
+            let upvar_id = ty::UpvarId {
+                var_path: ty::UpvarPath { hir_id: var_hir_id },
+                closure_expr_id: self.ir.body_owner.expect_local(),
+            };
+            match self.tables.upvar_capture(upvar_id) {
+                ty::UpvarCapture::ByValue => {}
+                ty::UpvarCapture::ByRef(..) => continue,
+            };
+            if self.used_on_entry(entry_ln, var) {
+                if self.live_on_entry(entry_ln, var).is_none() {
+                    if let Some(name) = self.should_warn(var) {
+                        self.ir.tcx.struct_span_lint_hir(
+                            lint::builtin::UNUSED_ASSIGNMENTS,
+                            var_hir_id,
+                            vec![upvar.span],
+                            |lint| {
+                                lint.build(&format!("value captured by `{}` is never read", name))
+                                    .help("did you mean to capture by reference instead?")
+                                    .emit();
+                            },
+                        );
+                    }
+                }
+            } else {
+                if let Some(name) = self.should_warn(var) {
+                    self.ir.tcx.struct_span_lint_hir(
+                        lint::builtin::UNUSED_VARIABLES,
+                        var_hir_id,
+                        vec![upvar.span],
+                        |lint| {
+                            lint.build(&format!("unused variable: `{}`", name))
+                                .help("did you mean to capture by reference instead?")
+                                .emit();
+                        },
+                    );
+                }
+            }
+        }
+    }
+
     fn warn_about_unused_args(&self, body: &hir::Body<'_>, entry_ln: LiveNode) {
         for p in body.params {
             self.check_unused_vars_in_pat(&p.pat, Some(entry_ln), |spans, hir_id, ln, var| {
                 if self.live_on_entry(ln, var).is_none() {
-                    self.report_dead_assign(hir_id, spans, var, true);
+                    self.report_unsed_assign(hir_id, spans, var, |name| {
+                        format!("value passed to `{}` is never read", name)
+                    });
                 }
             });
         }
@@ -1672,35 +1772,30 @@ impl<'tcx> Liveness<'_, 'tcx> {
 
     fn warn_about_dead_assign(&self, spans: Vec<Span>, hir_id: HirId, ln: LiveNode, var: Variable) {
         if self.live_on_exit(ln, var).is_none() {
-            self.report_dead_assign(hir_id, spans, var, false);
+            self.report_unsed_assign(hir_id, spans, var, |name| {
+                format!("value assigned to `{}` is never read", name)
+            });
         }
     }
 
-    fn report_dead_assign(&self, hir_id: HirId, spans: Vec<Span>, var: Variable, is_param: bool) {
+    fn report_unsed_assign(
+        &self,
+        hir_id: HirId,
+        spans: Vec<Span>,
+        var: Variable,
+        message: impl Fn(&str) -> String,
+    ) {
         if let Some(name) = self.should_warn(var) {
-            if is_param {
-                self.ir.tcx.struct_span_lint_hir(
-                    lint::builtin::UNUSED_ASSIGNMENTS,
-                    hir_id,
-                    spans,
-                    |lint| {
-                        lint.build(&format!("value passed to `{}` is never read", name))
-                            .help("maybe it is overwritten before being read?")
-                            .emit();
-                    },
-                )
-            } else {
-                self.ir.tcx.struct_span_lint_hir(
-                    lint::builtin::UNUSED_ASSIGNMENTS,
-                    hir_id,
-                    spans,
-                    |lint| {
-                        lint.build(&format!("value assigned to `{}` is never read", name))
-                            .help("maybe it is overwritten before being read?")
-                            .emit();
-                    },
-                )
-            }
+            self.ir.tcx.struct_span_lint_hir(
+                lint::builtin::UNUSED_ASSIGNMENTS,
+                hir_id,
+                spans,
+                |lint| {
+                    lint.build(&message(&name))
+                        .help("maybe it is overwritten before being read?")
+                        .emit();
+                },
+            )
         }
     }
 }
diff --git a/src/librustc_resolve/build_reduced_graph.rs b/src/librustc_resolve/build_reduced_graph.rs
index 92ea119d9a4..9ee3d989bf3 100644
--- a/src/librustc_resolve/build_reduced_graph.rs
+++ b/src/librustc_resolve/build_reduced_graph.rs
@@ -25,7 +25,7 @@ use rustc_errors::{struct_span_err, Applicability};
 use rustc_expand::base::SyntaxExtension;
 use rustc_expand::expand::AstFragment;
 use rustc_hir::def::{self, *};
-use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
+use rustc_hir::def_id::{DefId, LocalDefId, CRATE_DEF_INDEX};
 use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::bug;
 use rustc_middle::hir::exports::Export;
@@ -1150,15 +1150,22 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
     // Mark the given macro as unused unless its name starts with `_`.
     // Macro uses will remove items from this set, and the remaining
     // items will be reported as `unused_macros`.
-    fn insert_unused_macro(&mut self, ident: Ident, node_id: NodeId, span: Span) {
+    fn insert_unused_macro(
+        &mut self,
+        ident: Ident,
+        def_id: LocalDefId,
+        node_id: NodeId,
+        span: Span,
+    ) {
         if !ident.as_str().starts_with('_') {
-            self.r.unused_macros.insert(node_id, span);
+            self.r.unused_macros.insert(def_id, (node_id, span));
         }
     }
 
     fn define_macro(&mut self, item: &ast::Item) -> MacroRulesScope<'a> {
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
+        let def_id = self.r.definitions.local_def_id(item.id);
         let (ext, ident, span, macro_rules) = match &item.kind {
             ItemKind::MacroDef(def) => {
                 let ext = Lrc::new(self.r.compile_macro(item, self.r.session.edition()));
@@ -1166,7 +1173,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             }
             ItemKind::Fn(..) => match Self::proc_macro_stub(item) {
                 Some((macro_kind, ident, span)) => {
-                    self.r.proc_macro_stubs.insert(item.id);
+                    self.r.proc_macro_stubs.insert(def_id);
                     (self.r.dummy_ext(macro_kind), ident, span, false)
                 }
                 None => return parent_scope.macro_rules,
@@ -1174,7 +1181,6 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
             _ => unreachable!(),
         };
 
-        let def_id = self.r.definitions.local_def_id(item.id);
         let res = Res::Def(DefKind::Macro(ext.macro_kind()), def_id.to_def_id());
         self.r.macro_map.insert(def_id.to_def_id(), ext);
         self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
@@ -1196,7 +1202,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 self.r.define(module, ident, MacroNS, (res, vis, span, expansion, IsMacroExport));
             } else {
                 self.r.check_reserved_macro_name(ident, res);
-                self.insert_unused_macro(ident, item.id, span);
+                self.insert_unused_macro(ident, def_id, item.id, span);
             }
             MacroRulesScope::Binding(self.r.arenas.alloc_macro_rules_binding(MacroRulesBinding {
                 parent_macro_rules_scope: parent_scope.macro_rules,
@@ -1214,7 +1220,7 @@ impl<'a, 'b> BuildReducedGraphVisitor<'a, 'b> {
                 _ => self.resolve_visibility(&item.vis),
             };
             if vis != ty::Visibility::Public {
-                self.insert_unused_macro(ident, item.id, span);
+                self.insert_unused_macro(ident, def_id, item.id, span);
             }
             self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
             self.parent_scope.macro_rules
diff --git a/src/librustc_resolve/late.rs b/src/librustc_resolve/late.rs
index f04813cf3bc..3b49b3b6ff7 100644
--- a/src/librustc_resolve/late.rs
+++ b/src/librustc_resolve/late.rs
@@ -1621,11 +1621,10 @@ impl<'a, 'b, 'ast> LateResolutionVisitor<'a, 'b, 'ast> {
         let report_errors = |this: &mut Self, res: Option<Res>| {
             let (err, candidates) = this.smart_resolve_report_errors(path, span, source, res);
             let def_id = this.parent_scope.module.normal_ancestor_id;
-            let node_id = this.r.definitions.as_local_node_id(def_id).unwrap();
             let better = res.is_some();
             let suggestion =
                 if res.is_none() { this.report_missing_type_error(path) } else { None };
-            this.r.use_injections.push(UseError { err, candidates, node_id, better, suggestion });
+            this.r.use_injections.push(UseError { err, candidates, def_id, better, suggestion });
             PartialRes::new(Res::Err)
         };
 
diff --git a/src/librustc_resolve/lib.rs b/src/librustc_resolve/lib.rs
index 015f1b6315c..b50f9fe8e90 100644
--- a/src/librustc_resolve/lib.rs
+++ b/src/librustc_resolve/lib.rs
@@ -23,7 +23,7 @@ use rustc_ast::ast::{self, FloatTy, IntTy, NodeId, UintTy};
 use rustc_ast::ast::{Crate, CRATE_NODE_ID};
 use rustc_ast::ast::{ItemKind, Path};
 use rustc_ast::attr;
-use rustc_ast::node_id::{NodeMap, NodeSet};
+use rustc_ast::node_id::NodeMap;
 use rustc_ast::unwrap_or;
 use rustc_ast::visit::{self, Visitor};
 use rustc_ast_pretty::pprust;
@@ -253,21 +253,31 @@ impl<'a> From<&'a ast::PathSegment> for Segment {
     }
 }
 
-struct UsePlacementFinder {
-    target_module: NodeId,
+struct UsePlacementFinder<'d> {
+    definitions: &'d Definitions,
+    target_module: LocalDefId,
     span: Option<Span>,
     found_use: bool,
 }
 
-impl UsePlacementFinder {
-    fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, bool) {
-        let mut finder = UsePlacementFinder { target_module, span: None, found_use: false };
-        visit::walk_crate(&mut finder, krate);
-        (finder.span, finder.found_use)
+impl<'d> UsePlacementFinder<'d> {
+    fn check(
+        definitions: &'d Definitions,
+        krate: &Crate,
+        target_module: DefId,
+    ) -> (Option<Span>, bool) {
+        if let Some(target_module) = target_module.as_local() {
+            let mut finder =
+                UsePlacementFinder { definitions, target_module, span: None, found_use: false };
+            visit::walk_crate(&mut finder, krate);
+            (finder.span, finder.found_use)
+        } else {
+            (None, false)
+        }
     }
 }
 
-impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
+impl<'tcx, 'd> Visitor<'tcx> for UsePlacementFinder<'d> {
     fn visit_mod(
         &mut self,
         module: &'tcx ast::Mod,
@@ -278,7 +288,7 @@ impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
         if self.span.is_some() {
             return;
         }
-        if node_id != self.target_module {
+        if self.definitions.local_def_id(node_id) != self.target_module {
             visit::walk_mod(self, module);
             return;
         }
@@ -611,7 +621,7 @@ struct UseError<'a> {
     /// Attach `use` statements for these candidates.
     candidates: Vec<ImportSuggestion>,
     /// The `NodeId` of the module to place the use-statements in.
-    node_id: NodeId,
+    def_id: DefId,
     /// Whether the diagnostic should state that it's "better".
     better: bool,
     /// Extra free form suggestion. Currently used to suggest new type parameter.
@@ -926,8 +936,8 @@ pub struct Resolver<'a> {
     non_macro_attrs: [Lrc<SyntaxExtension>; 2],
     local_macro_def_scopes: FxHashMap<LocalDefId, Module<'a>>,
     ast_transform_scopes: FxHashMap<ExpnId, Module<'a>>,
-    unused_macros: NodeMap<Span>,
-    proc_macro_stubs: NodeSet,
+    unused_macros: FxHashMap<LocalDefId, (NodeId, Span)>,
+    proc_macro_stubs: FxHashSet<LocalDefId>,
     /// Traces collected during macro resolution and validated when it's complete.
     single_segment_macro_resolutions:
         Vec<(Ident, MacroKind, ParentScope<'a>, Option<&'a NameBinding<'a>>)>,
@@ -2567,10 +2577,10 @@ impl<'a> Resolver<'a> {
     }
 
     fn report_with_use_injections(&mut self, krate: &Crate) {
-        for UseError { mut err, candidates, node_id, better, suggestion } in
+        for UseError { mut err, candidates, def_id, better, suggestion } in
             self.use_injections.drain(..)
         {
-            let (span, found_use) = UsePlacementFinder::check(krate, node_id);
+            let (span, found_use) = UsePlacementFinder::check(&self.definitions, krate, def_id);
             if !candidates.is_empty() {
                 diagnostics::show_candidates(&mut err, span, &candidates, better, found_use);
             } else if let Some((span, msg, sugg, appl)) = suggestion {
diff --git a/src/librustc_resolve/macros.rs b/src/librustc_resolve/macros.rs
index 7027c826267..394d8dc4e11 100644
--- a/src/librustc_resolve/macros.rs
+++ b/src/librustc_resolve/macros.rs
@@ -333,7 +333,7 @@ impl<'a> base::Resolver for Resolver<'a> {
     }
 
     fn check_unused_macros(&mut self) {
-        for (&node_id, &span) in self.unused_macros.iter() {
+        for (_, &(node_id, span)) in self.unused_macros.iter() {
             self.lint_buffer.buffer_lint(UNUSED_MACROS, node_id, span, "unused macro definition");
         }
     }
@@ -416,9 +416,9 @@ impl<'a> Resolver<'a> {
 
         match res {
             Res::Def(DefKind::Macro(_), def_id) => {
-                if let Some(node_id) = self.definitions.as_local_node_id(def_id) {
-                    self.unused_macros.remove(&node_id);
-                    if self.proc_macro_stubs.contains(&node_id) {
+                if let Some(def_id) = def_id.as_local() {
+                    self.unused_macros.remove(&def_id);
+                    if self.proc_macro_stubs.contains(&def_id) {
                         self.session.span_err(
                             path.span,
                             "can't use a procedural macro from the same crate that defines it",
diff --git a/src/librustc_session/lint/builtin.rs b/src/librustc_session/lint/builtin.rs
index e55ddc26a94..7112ac35b08 100644
--- a/src/librustc_session/lint/builtin.rs
+++ b/src/librustc_session/lint/builtin.rs
@@ -526,6 +526,12 @@ declare_lint! {
     "using only a subset of a register for inline asm inputs",
 }
 
+declare_lint! {
+    pub UNSAFE_OP_IN_UNSAFE_FN,
+    Allow,
+    "unsafe operations in unsafe functions without an explicit unsafe block are deprecated",
+}
+
 declare_lint_pass! {
     /// Does nothing as a lint pass, but registers some `Lint`s
     /// that are used by other parts of the compiler.
@@ -597,6 +603,7 @@ declare_lint_pass! {
         SOFT_UNSTABLE,
         INLINE_NO_SANITIZE,
         ASM_SUB_REGISTER,
+        UNSAFE_OP_IN_UNSAFE_FN,
     ]
 }
 
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index f2f02cb6494..a943cf3b674 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -29,8 +29,10 @@ use rustc_target::spec::{Target, TargetTriple, TlsModel};
 
 use std::cell::{self, RefCell};
 use std::env;
+use std::fmt;
 use std::io::Write;
 use std::num::NonZeroU32;
+use std::ops::{Div, Mul};
 use std::path::PathBuf;
 use std::str::FromStr;
 use std::sync::Arc;
@@ -55,6 +57,46 @@ pub enum CtfeBacktrace {
     Immediate,
 }
 
+/// New-type wrapper around `usize` for representing limits. Ensures that comparisons against
+/// limits are consistent throughout the compiler.
+#[derive(Clone, Copy, Debug)]
+pub struct Limit(pub usize);
+
+impl Limit {
+    /// Create a new limit from a `usize`.
+    pub fn new(value: usize) -> Self {
+        Limit(value)
+    }
+
+    /// Check that `value` is within the limit. Ensures that the same comparisons are used
+    /// throughout the compiler, as mismatches can cause ICEs, see #72540.
+    pub fn value_within_limit(&self, value: usize) -> bool {
+        value <= self.0
+    }
+}
+
+impl fmt::Display for Limit {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{}", self.0)
+    }
+}
+
+impl Div<usize> for Limit {
+    type Output = Limit;
+
+    fn div(self, rhs: usize) -> Self::Output {
+        Limit::new(self.0 / rhs)
+    }
+}
+
+impl Mul<usize> for Limit {
+    type Output = Limit;
+
+    fn mul(self, rhs: usize) -> Self::Output {
+        Limit::new(self.0 * rhs)
+    }
+}
+
 /// Represents the data associated with a compilation
 /// session for a single crate.
 pub struct Session {
@@ -89,13 +131,13 @@ pub struct Session {
 
     /// The maximum recursion limit for potentially infinitely recursive
     /// operations such as auto-dereference and monomorphization.
-    pub recursion_limit: OnceCell<usize>,
+    pub recursion_limit: OnceCell<Limit>,
 
     /// The maximum length of types during monomorphization.
-    pub type_length_limit: OnceCell<usize>,
+    pub type_length_limit: OnceCell<Limit>,
 
     /// The maximum blocks a const expression can evaluate.
-    pub const_eval_limit: OnceCell<usize>,
+    pub const_eval_limit: OnceCell<Limit>,
 
     incr_comp_session: OneThread<RefCell<IncrCompSession>>,
     /// Used for incremental compilation tests. Will only be populated if
@@ -255,15 +297,15 @@ impl Session {
         self.crate_types.set(crate_types).expect("`crate_types` was initialized twice")
     }
 
-    pub fn recursion_limit(&self) -> usize {
+    pub fn recursion_limit(&self) -> Limit {
         self.recursion_limit.get().copied().unwrap()
     }
 
-    pub fn type_length_limit(&self) -> usize {
+    pub fn type_length_limit(&self) -> Limit {
         self.type_length_limit.get().copied().unwrap()
     }
 
-    pub fn const_eval_limit(&self) -> usize {
+    pub fn const_eval_limit(&self) -> Limit {
         self.const_eval_limit.get().copied().unwrap()
     }
 
diff --git a/src/librustc_span/symbol.rs b/src/librustc_span/symbol.rs
index 6a6098710e8..0f2d52c2264 100644
--- a/src/librustc_span/symbol.rs
+++ b/src/librustc_span/symbol.rs
@@ -147,6 +147,7 @@ symbols! {
         Arc,
         Arguments,
         ArgumentV1,
+        arith_offset,
         arm_target_feature,
         asm,
         assert,
@@ -516,6 +517,7 @@ symbols! {
         not,
         note,
         object_safe_for_dispatch,
+        offset,
         Ok,
         omit_gdb_pretty_printer_section,
         on,
@@ -806,6 +808,7 @@ symbols! {
         unmarked_api,
         unreachable_code,
         unrestricted_attribute_tokens,
+        unsafe_block_in_unsafe_fn,
         unsafe_no_drop_flag,
         unsized_locals,
         unsized_tuple_coercion,
diff --git a/src/librustc_target/asm/mod.rs b/src/librustc_target/asm/mod.rs
index 774146a679a..a18a4dbd3e2 100644
--- a/src/librustc_target/asm/mod.rs
+++ b/src/librustc_target/asm/mod.rs
@@ -60,6 +60,7 @@ macro_rules! def_regs {
             #error = [$($bad_reg:literal),+] => $error:literal,
         )*
     }) => {
+        #[allow(unreachable_code)]
         #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, Eq, PartialEq, Hash, HashStable_Generic)]
         #[allow(non_camel_case_types)]
         pub enum $arch_reg {
@@ -102,19 +103,20 @@ macro_rules! def_regs {
         pub(super) fn fill_reg_map(
             _arch: super::InlineAsmArch,
             mut _has_feature: impl FnMut(&str) -> bool,
-            map: &mut rustc_data_structures::fx::FxHashMap<
+            _map: &mut rustc_data_structures::fx::FxHashMap<
                 super::InlineAsmRegClass,
                 rustc_data_structures::fx::FxHashSet<super::InlineAsmReg>,
             >,
         ) {
+            #[allow(unused_imports)]
             use super::{InlineAsmReg, InlineAsmRegClass};
             $(
                 if $($filter(_arch, &mut _has_feature, true).is_ok() &&)? true {
-                    if let Some(set) = map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
+                    if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$class)) {
                         set.insert(InlineAsmReg::$arch($arch_reg::$reg));
                     }
                     $(
-                        if let Some(set) = map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) {
+                        if let Some(set) = _map.get_mut(&InlineAsmRegClass::$arch($arch_regclass::$extra_class)) {
                             set.insert(InlineAsmReg::$arch($arch_reg::$reg));
                         }
                     )*
@@ -146,11 +148,13 @@ macro_rules! types {
 
 mod aarch64;
 mod arm;
+mod nvptx;
 mod riscv;
 mod x86;
 
 pub use aarch64::{AArch64InlineAsmReg, AArch64InlineAsmRegClass};
 pub use arm::{ArmInlineAsmReg, ArmInlineAsmRegClass};
+pub use nvptx::{NvptxInlineAsmReg, NvptxInlineAsmRegClass};
 pub use riscv::{RiscVInlineAsmReg, RiscVInlineAsmRegClass};
 pub use x86::{X86InlineAsmReg, X86InlineAsmRegClass};
 
@@ -162,6 +166,7 @@ pub enum InlineAsmArch {
     AArch64,
     RiscV32,
     RiscV64,
+    Nvptx64,
 }
 
 impl FromStr for InlineAsmArch {
@@ -175,6 +180,7 @@ impl FromStr for InlineAsmArch {
             "aarch64" => Ok(Self::AArch64),
             "riscv32" => Ok(Self::RiscV32),
             "riscv64" => Ok(Self::RiscV64),
+            "nvptx64" => Ok(Self::Nvptx64),
             _ => Err(()),
         }
     }
@@ -196,6 +202,7 @@ pub enum InlineAsmReg {
     Arm(ArmInlineAsmReg),
     AArch64(AArch64InlineAsmReg),
     RiscV(RiscVInlineAsmReg),
+    Nvptx(NvptxInlineAsmReg),
 }
 
 impl InlineAsmReg {
@@ -236,6 +243,9 @@ impl InlineAsmReg {
             InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
                 Self::RiscV(RiscVInlineAsmReg::parse(arch, has_feature, &name)?)
             }
+            InlineAsmArch::Nvptx64 => {
+                Self::Nvptx(NvptxInlineAsmReg::parse(arch, has_feature, &name)?)
+            }
         })
     }
 
@@ -281,6 +291,7 @@ pub enum InlineAsmRegClass {
     Arm(ArmInlineAsmRegClass),
     AArch64(AArch64InlineAsmRegClass),
     RiscV(RiscVInlineAsmRegClass),
+    Nvptx(NvptxInlineAsmRegClass),
 }
 
 impl InlineAsmRegClass {
@@ -290,6 +301,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.name(),
             Self::AArch64(r) => r.name(),
             Self::RiscV(r) => r.name(),
+            Self::Nvptx(r) => r.name(),
         }
     }
 
@@ -302,6 +314,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Arm),
             Self::AArch64(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::AArch64),
             Self::RiscV(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::RiscV),
+            Self::Nvptx(r) => r.suggest_class(arch, ty).map(InlineAsmRegClass::Nvptx),
         }
     }
 
@@ -321,6 +334,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.suggest_modifier(arch, ty),
             Self::AArch64(r) => r.suggest_modifier(arch, ty),
             Self::RiscV(r) => r.suggest_modifier(arch, ty),
+            Self::Nvptx(r) => r.suggest_modifier(arch, ty),
         }
     }
 
@@ -336,6 +350,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.default_modifier(arch),
             Self::AArch64(r) => r.default_modifier(arch),
             Self::RiscV(r) => r.default_modifier(arch),
+            Self::Nvptx(r) => r.default_modifier(arch),
         }
     }
 
@@ -350,6 +365,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.supported_types(arch),
             Self::AArch64(r) => r.supported_types(arch),
             Self::RiscV(r) => r.supported_types(arch),
+            Self::Nvptx(r) => r.supported_types(arch),
         }
     }
 
@@ -367,6 +383,7 @@ impl InlineAsmRegClass {
                 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {
                     Self::RiscV(RiscVInlineAsmRegClass::parse(arch, name)?)
                 }
+                InlineAsmArch::Nvptx64 => Self::Nvptx(NvptxInlineAsmRegClass::parse(arch, name)?),
             })
         })
     }
@@ -379,6 +396,7 @@ impl InlineAsmRegClass {
             Self::Arm(r) => r.valid_modifiers(arch),
             Self::AArch64(r) => r.valid_modifiers(arch),
             Self::RiscV(r) => r.valid_modifiers(arch),
+            Self::Nvptx(r) => r.valid_modifiers(arch),
         }
     }
 }
@@ -518,5 +536,10 @@ pub fn allocatable_registers(
             riscv::fill_reg_map(arch, has_feature, &mut map);
             map
         }
+        InlineAsmArch::Nvptx64 => {
+            let mut map = nvptx::regclass_map();
+            nvptx::fill_reg_map(arch, has_feature, &mut map);
+            map
+        }
     }
 }
diff --git a/src/librustc_target/asm/nvptx.rs b/src/librustc_target/asm/nvptx.rs
new file mode 100644
index 00000000000..43d16ae0f5d
--- /dev/null
+++ b/src/librustc_target/asm/nvptx.rs
@@ -0,0 +1,49 @@
+use super::{InlineAsmArch, InlineAsmType};
+use rustc_macros::HashStable_Generic;
+
+def_reg_class! {
+    Nvptx NvptxInlineAsmRegClass {
+        reg16,
+        reg32,
+        reg64,
+    }
+}
+
+impl NvptxInlineAsmRegClass {
+    pub fn valid_modifiers(self, _arch: InlineAsmArch) -> &'static [char] {
+        &[]
+    }
+
+    pub fn suggest_class(self, _arch: InlineAsmArch, _ty: InlineAsmType) -> Option<Self> {
+        None
+    }
+
+    pub fn suggest_modifier(
+        self,
+        _arch: InlineAsmArch,
+        _ty: InlineAsmType,
+    ) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn default_modifier(self, _arch: InlineAsmArch) -> Option<(char, &'static str)> {
+        None
+    }
+
+    pub fn supported_types(
+        self,
+        _arch: InlineAsmArch,
+    ) -> &'static [(InlineAsmType, Option<&'static str>)] {
+        match self {
+            Self::reg16 => types! { _: I8, I16; },
+            Self::reg32 => types! { _: I8, I16, I32, F32; },
+            Self::reg64 => types! { _: I8, I16, I32, F32, I64, F64; },
+        }
+    }
+}
+
+def_regs! {
+    // Registers in PTX are declared in the assembly.
+    // There are no predefined registers that one can use.
+    Nvptx NvptxInlineAsmReg NvptxInlineAsmRegClass {}
+}
diff --git a/src/librustc_target/spec/mod.rs b/src/librustc_target/spec/mod.rs
index df17231633e..c9558879a1c 100644
--- a/src/librustc_target/spec/mod.rs
+++ b/src/librustc_target/spec/mod.rs
@@ -856,6 +856,8 @@ pub struct TargetOptions {
     /// the functions in the executable are not randomized and can be used
     /// during an exploit of a vulnerability in any code.
     pub position_independent_executables: bool,
+    /// Executables that are both statically linked and position-independent are supported.
+    pub static_position_independent_executables: bool,
     /// Determines if the target always requires using the PLT for indirect
     /// library calls or not. This controls the default value of the `-Z plt` flag.
     pub needs_plt: bool,
@@ -1029,6 +1031,7 @@ impl Default for TargetOptions {
             has_rpath: false,
             no_default_libraries: true,
             position_independent_executables: false,
+            static_position_independent_executables: false,
             needs_plt: false,
             relro_level: RelroLevel::None,
             pre_link_objects: Default::default(),
@@ -1433,6 +1436,7 @@ impl Target {
         key!(has_rpath, bool);
         key!(no_default_libraries, bool);
         key!(position_independent_executables, bool);
+        key!(static_position_independent_executables, bool);
         key!(needs_plt, bool);
         key!(relro_level, RelroLevel)?;
         key!(archive_format);
@@ -1664,6 +1668,7 @@ impl ToJson for Target {
         target_option_val!(has_rpath);
         target_option_val!(no_default_libraries);
         target_option_val!(position_independent_executables);
+        target_option_val!(static_position_independent_executables);
         target_option_val!(needs_plt);
         target_option_val!(relro_level);
         target_option_val!(archive_format);
diff --git a/src/librustc_trait_selection/traits/project.rs b/src/librustc_trait_selection/traits/project.rs
index cd5d0be003a..1126480b02a 100644
--- a/src/librustc_trait_selection/traits/project.rs
+++ b/src/librustc_trait_selection/traits/project.rs
@@ -333,10 +333,10 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
 
                     Reveal::All => {
                         let recursion_limit = self.tcx().sess.recursion_limit();
-                        if self.depth >= recursion_limit {
+                        if !recursion_limit.value_within_limit(self.depth) {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
-                                recursion_limit,
+                                recursion_limit.0,
                                 self.param_env,
                                 ty,
                             );
@@ -522,7 +522,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
             // But for now, let's classify this as an overflow:
             let recursion_limit = selcx.tcx().sess.recursion_limit();
             let obligation =
-                Obligation::with_depth(cause, recursion_limit, param_env, projection_ty);
+                Obligation::with_depth(cause, recursion_limit.0, param_env, projection_ty);
             selcx.infcx().report_overflow_error(&obligation, false);
         }
         Err(ProjectionCacheEntry::NormalizedTy(ty)) => {
@@ -814,8 +814,7 @@ fn project_type<'cx, 'tcx>(
 ) -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>> {
     debug!("project(obligation={:?})", obligation);
 
-    let recursion_limit = selcx.tcx().sess.recursion_limit();
-    if obligation.recursion_depth >= recursion_limit {
+    if !selcx.tcx().sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
         debug!("project: overflow!");
         return Err(ProjectionTyError::TraitSelectionError(SelectionError::Overflow));
     }
diff --git a/src/librustc_trait_selection/traits/query/normalize.rs b/src/librustc_trait_selection/traits/query/normalize.rs
index 008ca8d526d..3e7749356d2 100644
--- a/src/librustc_trait_selection/traits/query/normalize.rs
+++ b/src/librustc_trait_selection/traits/query/normalize.rs
@@ -109,10 +109,10 @@ impl<'cx, 'tcx> TypeFolder<'tcx> for QueryNormalizer<'cx, 'tcx> {
 
                     Reveal::All => {
                         let recursion_limit = self.tcx().sess.recursion_limit();
-                        if self.anon_depth >= recursion_limit {
+                        if !recursion_limit.value_within_limit(self.anon_depth) {
                             let obligation = Obligation::with_depth(
                                 self.cause.clone(),
-                                recursion_limit,
+                                recursion_limit.0,
                                 self.param_env,
                                 ty,
                             );
diff --git a/src/librustc_trait_selection/traits/select.rs b/src/librustc_trait_selection/traits/select.rs
index b27fba2f82b..7aa5aa2dae8 100644
--- a/src/librustc_trait_selection/traits/select.rs
+++ b/src/librustc_trait_selection/traits/select.rs
@@ -919,7 +919,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         obligation: &Obligation<'tcx, T>,
         error_obligation: &Obligation<'tcx, V>,
     ) -> Result<(), OverflowError> {
-        if obligation.recursion_depth >= self.infcx.tcx.sess.recursion_limit() {
+        if !self.infcx.tcx.sess.recursion_limit().value_within_limit(obligation.recursion_depth) {
             match self.query_mode {
                 TraitQueryMode::Standard => {
                     self.infcx().report_overflow_error(error_obligation, true);
@@ -1040,17 +1040,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         &mut self,
         stack: &TraitObligationStack<'o, 'tcx>,
     ) -> SelectionResult<'tcx, SelectionCandidate<'tcx>> {
-        if stack.obligation.predicate.references_error() {
-            // If we encounter a `Error`, we generally prefer the
-            // most "optimistic" result in response -- that is, the
-            // one least likely to report downstream errors. But
-            // because this routine is shared by coherence and by
-            // trait selection, there isn't an obvious "right" choice
-            // here in that respect, so we opt to just return
-            // ambiguity and let the upstream clients sort it out.
-            return Ok(None);
-        }
-
         if let Some(conflict) = self.is_knowable(stack) {
             debug!("coherence stage: not knowable");
             if self.intercrate_ambiguity_causes.is_some() {
diff --git a/src/librustc_traits/dropck_outlives.rs b/src/librustc_traits/dropck_outlives.rs
index fb9c0d7f990..11c48559bd6 100644
--- a/src/librustc_traits/dropck_outlives.rs
+++ b/src/librustc_traits/dropck_outlives.rs
@@ -163,7 +163,7 @@ fn dtorck_constraint_for_ty<'tcx>(
 ) -> Result<(), NoSolution> {
     debug!("dtorck_constraint_for_ty({:?}, {:?}, {:?}, {:?})", span, for_ty, depth, ty);
 
-    if depth >= tcx.sess.recursion_limit() {
+    if !tcx.sess.recursion_limit().value_within_limit(depth) {
         constraints.overflows.push(ty);
         return Ok(());
     }
diff --git a/src/librustc_ty/needs_drop.rs b/src/librustc_ty/needs_drop.rs
index 1b059fa3dbd..c54704e7877 100644
--- a/src/librustc_ty/needs_drop.rs
+++ b/src/librustc_ty/needs_drop.rs
@@ -5,6 +5,7 @@ use rustc_hir::def_id::DefId;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::util::{needs_drop_components, AlwaysRequiresDrop};
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_session::Limit;
 use rustc_span::DUMMY_SP;
 
 type NeedsDropResult<T> = Result<T, AlwaysRequiresDrop>;
@@ -30,7 +31,7 @@ struct NeedsDropTypes<'tcx, F> {
     /// if it needs drop. If the result depends on whether some other types
     /// need drop we push them onto the stack.
     unchecked_tys: Vec<(Ty<'tcx>, usize)>,
-    recursion_limit: usize,
+    recursion_limit: Limit,
     adt_components: F,
 }
 
@@ -66,7 +67,7 @@ where
         let tcx = self.tcx;
 
         while let Some((ty, level)) = self.unchecked_tys.pop() {
-            if level > self.recursion_limit {
+            if !self.recursion_limit.value_within_limit(level) {
                 // Not having a `Span` isn't great. But there's hopefully some other
                 // recursion limit error as well.
                 tcx.sess.span_err(
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9a5fe9552d3..12edfed19c0 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -123,7 +123,22 @@ enum ConvertedBindingKind<'a, 'tcx> {
     Constraint(&'a [hir::GenericBound<'a>]),
 }
 
-#[derive(PartialEq)]
+/// New-typed boolean indicating whether explicit late-bound lifetimes
+/// are present in a set of generic arguments.
+///
+/// For example if we have some method `fn f<'a>(&'a self)` implemented
+/// for some type `T`, although `f` is generic in the lifetime `'a`, `'a`
+/// is late-bound so should not be provided explicitly. Thus, if `f` is
+/// instantiated with some generic arguments providing `'a` explicitly,
+/// we taint those arguments with `ExplicitLateBound::Yes` so that we
+/// can provide an appropriate diagnostic later.
+#[derive(Copy, Clone, PartialEq)]
+pub enum ExplicitLateBound {
+    Yes,
+    No,
+}
+
+#[derive(Copy, Clone, PartialEq)]
 enum GenericArgPosition {
     Type,
     Value, // e.g., functions
@@ -132,6 +147,7 @@ enum GenericArgPosition {
 
 /// A marker denoting that the generic arguments that were
 /// provided did not match the respective generic parameters.
+#[derive(Clone, Default)]
 pub struct GenericArgCountMismatch {
     /// Indicates whether a fatal error was reported (`Some`), or just a lint (`None`).
     pub reported: Option<ErrorReported>,
@@ -139,6 +155,14 @@ pub struct GenericArgCountMismatch {
     pub invalid_args: Vec<Span>,
 }
 
+/// Decorates the result of a generic argument count mismatch
+/// check with whether explicit late bounds were provided.
+#[derive(Clone)]
+pub struct GenericArgCountResult {
+    pub explicit_late_bound: ExplicitLateBound,
+    pub correct: Result<(), GenericArgCountMismatch>,
+}
+
 impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
     pub fn ast_region_to_region(
         &self,
@@ -271,7 +295,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         def: &ty::Generics,
         seg: &hir::PathSegment<'_>,
         is_method_call: bool,
-    ) -> Result<(), GenericArgCountMismatch> {
+    ) -> GenericArgCountResult {
         let empty_args = hir::GenericArgs::none();
         let suppress_mismatch = Self::check_impl_trait(tcx, seg, &def);
         Self::check_generic_arg_count(
@@ -295,7 +319,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         position: GenericArgPosition,
         has_self: bool,
         infer_args: bool,
-    ) -> Result<(), GenericArgCountMismatch> {
+    ) -> GenericArgCountResult {
         // At this stage we are guaranteed that the generic arguments are in the correct order, e.g.
         // that lifetimes will proceed types. So it suffices to check the number of each generic
         // arguments in order to validate them with respect to the generic parameters.
@@ -320,105 +344,86 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             AstConv::prohibit_assoc_ty_binding(tcx, args.bindings[0].span);
         }
 
-        // Prohibit explicit lifetime arguments if late-bound lifetime parameters are present.
-        let mut explicit_lifetimes = Ok(());
-        if !infer_lifetimes {
-            if let Some(span_late) = def.has_late_bound_regions {
-                let msg = "cannot specify lifetime arguments explicitly \
-                           if late bound lifetime parameters are present";
-                let note = "the late bound lifetime parameter is introduced here";
-                let span = args.args[0].span();
-                if position == GenericArgPosition::Value
-                    && arg_counts.lifetimes != param_counts.lifetimes
-                {
-                    explicit_lifetimes = Err(true);
-                    let mut err = tcx.sess.struct_span_err(span, msg);
-                    err.span_note(span_late, note);
-                    err.emit();
-                } else {
-                    explicit_lifetimes = Err(false);
-                    let mut multispan = MultiSpan::from_span(span);
-                    multispan.push_span_label(span_late, note.to_string());
-                    tcx.struct_span_lint_hir(
-                        LATE_BOUND_LIFETIME_ARGUMENTS,
-                        args.args[0].id(),
-                        multispan,
-                        |lint| lint.build(msg).emit(),
-                    );
-                }
+        let explicit_late_bound =
+            Self::prohibit_explicit_late_bound_lifetimes(tcx, def, args, position);
+
+        let check_kind_count = |kind,
+                                required,
+                                permitted,
+                                provided,
+                                offset,
+                                unexpected_spans: &mut Vec<Span>,
+                                silent| {
+            debug!(
+                "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
+                kind, required, permitted, provided, offset
+            );
+            // We enforce the following: `required` <= `provided` <= `permitted`.
+            // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
+            // For other kinds (i.e., types), `permitted` may be greater than `required`.
+            if required <= provided && provided <= permitted {
+                return Ok(());
             }
-        }
 
-        let check_kind_count =
-            |kind, required, permitted, provided, offset, unexpected_spans: &mut Vec<Span>| {
-                debug!(
-                    "check_kind_count: kind: {} required: {} permitted: {} provided: {} offset: {}",
-                    kind, required, permitted, provided, offset
-                );
-                // We enforce the following: `required` <= `provided` <= `permitted`.
-                // For kinds without defaults (e.g.., lifetimes), `required == permitted`.
-                // For other kinds (i.e., types), `permitted` may be greater than `required`.
-                if required <= provided && provided <= permitted {
-                    return Ok(());
-                }
-
-                // Unfortunately lifetime and type parameter mismatches are typically styled
-                // differently in diagnostics, which means we have a few cases to consider here.
-                let (bound, quantifier) = if required != permitted {
-                    if provided < required {
-                        (required, "at least ")
-                    } else {
-                        // provided > permitted
-                        (permitted, "at most ")
-                    }
-                } else {
-                    (required, "")
-                };
+            if silent {
+                return Err(true);
+            }
 
-                let (spans, label) = if required == permitted && provided > permitted {
-                    // In the case when the user has provided too many arguments,
-                    // we want to point to the unexpected arguments.
-                    let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
-                        .iter()
-                        .map(|arg| arg.span())
-                        .collect();
-                    unexpected_spans.extend(spans.clone());
-                    (spans, format!("unexpected {} argument", kind))
+            // Unfortunately lifetime and type parameter mismatches are typically styled
+            // differently in diagnostics, which means we have a few cases to consider here.
+            let (bound, quantifier) = if required != permitted {
+                if provided < required {
+                    (required, "at least ")
                 } else {
-                    (
-                        vec![span],
-                        format!(
-                            "expected {}{} {} argument{}",
-                            quantifier,
-                            bound,
-                            kind,
-                            pluralize!(bound),
-                        ),
-                    )
-                };
-
-                let mut err = tcx.sess.struct_span_err_with_code(
-                    spans.clone(),
-                    &format!(
-                        "wrong number of {} arguments: expected {}{}, found {}",
-                        kind, quantifier, bound, provided,
-                    ),
-                    DiagnosticId::Error("E0107".into()),
-                );
-                for span in spans {
-                    err.span_label(span, label.as_str());
+                    // provided > permitted
+                    (permitted, "at most ")
                 }
-                err.emit();
+            } else {
+                (required, "")
+            };
 
-                Err(true)
+            let (spans, label) = if required == permitted && provided > permitted {
+                // In the case when the user has provided too many arguments,
+                // we want to point to the unexpected arguments.
+                let spans: Vec<Span> = args.args[offset + permitted..offset + provided]
+                    .iter()
+                    .map(|arg| arg.span())
+                    .collect();
+                unexpected_spans.extend(spans.clone());
+                (spans, format!("unexpected {} argument", kind))
+            } else {
+                (
+                    vec![span],
+                    format!(
+                        "expected {}{} {} argument{}",
+                        quantifier,
+                        bound,
+                        kind,
+                        pluralize!(bound),
+                    ),
+                )
             };
 
-        let mut arg_count_correct = explicit_lifetimes;
+            let mut err = tcx.sess.struct_span_err_with_code(
+                spans.clone(),
+                &format!(
+                    "wrong number of {} arguments: expected {}{}, found {}",
+                    kind, quantifier, bound, provided,
+                ),
+                DiagnosticId::Error("E0107".into()),
+            );
+            for span in spans {
+                err.span_label(span, label.as_str());
+            }
+            err.emit();
+
+            Err(true)
+        };
+
+        let mut arg_count_correct = Ok(());
         let mut unexpected_spans = vec![];
 
-        if arg_count_correct.is_ok()
-            && (!infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes)
-        {
+        if !infer_lifetimes || arg_counts.lifetimes > param_counts.lifetimes {
             arg_count_correct = check_kind_count(
                 "lifetime",
                 param_counts.lifetimes,
@@ -426,6 +431,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 arg_counts.lifetimes,
                 0,
                 &mut unexpected_spans,
+                explicit_late_bound == ExplicitLateBound::Yes,
             )
             .and(arg_count_correct);
         }
@@ -438,6 +444,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 arg_counts.consts,
                 arg_counts.lifetimes + arg_counts.types,
                 &mut unexpected_spans,
+                false,
             )
             .and(arg_count_correct);
         }
@@ -451,14 +458,18 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 arg_counts.types,
                 arg_counts.lifetimes,
                 &mut unexpected_spans,
+                false,
             )
             .and(arg_count_correct);
         }
 
-        arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
-            reported: if reported_err { Some(ErrorReported) } else { None },
-            invalid_args: unexpected_spans,
-        })
+        GenericArgCountResult {
+            explicit_late_bound,
+            correct: arg_count_correct.map_err(|reported_err| GenericArgCountMismatch {
+                reported: if reported_err { Some(ErrorReported) } else { None },
+                invalid_args: unexpected_spans,
+            }),
+        }
     }
 
     /// Report an error that a generic argument did not match the generic parameter that was
@@ -512,7 +523,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         parent_substs: &[subst::GenericArg<'tcx>],
         has_self: bool,
         self_ty: Option<Ty<'tcx>>,
-        arg_count_correct: bool,
+        arg_count: GenericArgCountResult,
         args_for_def_id: impl Fn(DefId) -> (Option<&'b GenericArgs<'b>>, bool),
         mut provided_kind: impl FnMut(&GenericParamDef, &GenericArg<'_>) -> subst::GenericArg<'tcx>,
         mut inferred_kind: impl FnMut(
@@ -585,10 +596,10 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 // input. We try to handle both sensibly.
                 match (args.peek(), params.peek()) {
                     (Some(&arg), Some(&param)) => {
-                        match (arg, &param.kind) {
-                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime)
-                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. })
-                            | (GenericArg::Const(_), GenericParamDefKind::Const) => {
+                        match (arg, &param.kind, arg_count.explicit_late_bound) {
+                            (GenericArg::Lifetime(_), GenericParamDefKind::Lifetime, _)
+                            | (GenericArg::Type(_), GenericParamDefKind::Type { .. }, _)
+                            | (GenericArg::Const(_), GenericParamDefKind::Const, _) => {
                                 substs.push(provided_kind(param, arg));
                                 args.next();
                                 params.next();
@@ -596,6 +607,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             (
                                 GenericArg::Type(_) | GenericArg::Const(_),
                                 GenericParamDefKind::Lifetime,
+                                _,
                             ) => {
                                 // We expected a lifetime argument, but got a type or const
                                 // argument. That means we're inferring the lifetimes.
@@ -603,12 +615,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                                 force_infer_lt = Some(arg);
                                 params.next();
                             }
-                            (_, kind) => {
+                            (GenericArg::Lifetime(_), _, ExplicitLateBound::Yes) => {
+                                // We've come across a lifetime when we expected something else in
+                                // the presence of explicit late bounds. This is most likely
+                                // due to the presence of the explicit bound so we're just going to
+                                // ignore it.
+                                args.next();
+                            }
+                            (_, kind, _) => {
                                 // We expected one kind of parameter, but the user provided
                                 // another. This is an error. However, if we already know that
                                 // the arguments don't match up with the parameters, we won't issue
                                 // an additional error, as the user already knows what's wrong.
-                                if arg_count_correct {
+                                if arg_count.correct.is_ok()
+                                    && arg_count.explicit_late_bound == ExplicitLateBound::No
+                                {
                                     Self::generic_arg_mismatch_err(tcx.sess, arg, kind.descr());
                                 }
 
@@ -624,17 +645,19 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
                     (Some(&arg), None) => {
                         // We should never be able to reach this point with well-formed input.
-                        // There are two situations in which we can encounter this issue.
+                        // There are three situations in which we can encounter this issue.
                         //
                         //  1.  The number of arguments is incorrect. In this case, an error
-                        //      will already have been emitted, and we can ignore it. This case
-                        //      also occurs when late-bound lifetime parameters are present, yet
-                        //      the lifetime arguments have also been explicitly specified by the
+                        //      will already have been emitted, and we can ignore it.
+                        //  2.  There are late-bound lifetime parameters present, yet the
+                        //      lifetime arguments have also been explicitly specified by the
                         //      user.
-                        //  2.  We've inferred some lifetimes, which have been provided later (i.e.
+                        //  3.  We've inferred some lifetimes, which have been provided later (i.e.
                         //      after a type or const). We want to throw an error in this case.
 
-                        if arg_count_correct {
+                        if arg_count.correct.is_ok()
+                            && arg_count.explicit_late_bound == ExplicitLateBound::No
+                        {
                             let kind = arg.descr();
                             assert_eq!(kind, "lifetime");
                             let provided =
@@ -699,8 +722,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         generic_args: &'a hir::GenericArgs<'_>,
         infer_args: bool,
         self_ty: Option<Ty<'tcx>>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
-    {
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
         // If the type is parameterized by this region, then replace this
         // region with the current anon region binding (in other words,
         // whatever & would get replaced with).
@@ -726,7 +748,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             assert!(self_ty.is_none() && parent_substs.is_empty());
         }
 
-        let arg_count_correct = Self::check_generic_arg_count(
+        let arg_count = Self::check_generic_arg_count(
             tcx,
             span,
             &generic_params,
@@ -761,7 +783,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             parent_substs,
             self_ty.is_some(),
             self_ty,
-            arg_count_correct.is_ok(),
+            arg_count.clone(),
             // Provide the generic args, and whether types should be inferred.
             |did| {
                 if did == def_id {
@@ -880,7 +902,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             generic_params, self_ty, substs
         );
 
-        (substs, assoc_bindings, arg_count_correct)
+        (substs, assoc_bindings, arg_count)
     }
 
     crate fn create_substs_for_associated_item(
@@ -1011,14 +1033,14 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
         speculative: bool,
-    ) -> Result<(), GenericArgCountMismatch> {
+    ) -> GenericArgCountResult {
         let trait_def_id = trait_ref.trait_def_id().unwrap_or_else(|| FatalError.raise());
 
         debug!("instantiate_poly_trait_ref({:?}, def_id={:?})", trait_ref, trait_def_id);
 
         self.prohibit_generics(trait_ref.path.segments.split_last().unwrap().1);
 
-        let (substs, assoc_bindings, arg_count_correct) = self.create_substs_for_ast_trait_ref(
+        let (substs, assoc_bindings, arg_count) = self.create_substs_for_ast_trait_ref(
             trait_ref.path.span,
             trait_def_id,
             self_ty,
@@ -1048,7 +1070,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
             trait_ref, bounds, poly_trait_ref
         );
 
-        arg_count_correct
+        arg_count
     }
 
     /// Given a trait bound like `Debug`, applies that trait bound the given self-type to construct
@@ -1076,7 +1098,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         constness: Constness,
         self_ty: Ty<'tcx>,
         bounds: &mut Bounds<'tcx>,
-    ) -> Result<(), GenericArgCountMismatch> {
+    ) -> GenericArgCountResult {
         self.instantiate_poly_trait_ref_inner(
             &poly_trait_ref.trait_ref,
             poly_trait_ref.span,
@@ -1166,8 +1188,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         trait_def_id: DefId,
         self_ty: Ty<'tcx>,
         trait_segment: &'a hir::PathSegment<'a>,
-    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, Result<(), GenericArgCountMismatch>)
-    {
+    ) -> (SubstsRef<'tcx>, Vec<ConvertedBinding<'a, 'tcx>>, GenericArgCountResult) {
         debug!("create_substs_for_ast_trait_ref(trait_segment={:?})", trait_segment);
 
         self.complain_about_internal_fn_trait(span, trait_def_id, trait_segment);
@@ -1515,9 +1536,11 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         let mut potential_assoc_types = Vec::new();
         let dummy_self = self.tcx().types.trait_object_dummy_self;
         for trait_bound in trait_bounds.iter().rev() {
-            if let Err(GenericArgCountMismatch {
-                invalid_args: cur_potential_assoc_types, ..
-            }) = self.instantiate_poly_trait_ref(
+            if let GenericArgCountResult {
+                correct:
+                    Err(GenericArgCountMismatch { invalid_args: cur_potential_assoc_types, .. }),
+                ..
+            } = self.instantiate_poly_trait_ref(
                 trait_bound,
                 Constness::NotConst,
                 dummy_self,
@@ -2473,6 +2496,47 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         err.span_label(span, "associated type not allowed here").emit();
     }
 
+    /// Prohibits explicit lifetime arguments if late-bound lifetime parameters
+    /// are present. This is used both for datatypes and function calls.
+    fn prohibit_explicit_late_bound_lifetimes(
+        tcx: TyCtxt<'_>,
+        def: &ty::Generics,
+        args: &hir::GenericArgs<'_>,
+        position: GenericArgPosition,
+    ) -> ExplicitLateBound {
+        let param_counts = def.own_counts();
+        let arg_counts = args.own_counts();
+        let infer_lifetimes = position != GenericArgPosition::Type && arg_counts.lifetimes == 0;
+
+        if infer_lifetimes {
+            ExplicitLateBound::No
+        } else if let Some(span_late) = def.has_late_bound_regions {
+            let msg = "cannot specify lifetime arguments explicitly \
+                       if late bound lifetime parameters are present";
+            let note = "the late bound lifetime parameter is introduced here";
+            let span = args.args[0].span();
+            if position == GenericArgPosition::Value
+                && arg_counts.lifetimes != param_counts.lifetimes
+            {
+                let mut err = tcx.sess.struct_span_err(span, msg);
+                err.span_note(span_late, note);
+                err.emit();
+            } else {
+                let mut multispan = MultiSpan::from_span(span);
+                multispan.push_span_label(span_late, note.to_string());
+                tcx.struct_span_lint_hir(
+                    LATE_BOUND_LIFETIME_ARGUMENTS,
+                    args.args[0].id(),
+                    multispan,
+                    |lint| lint.build(msg).emit(),
+                );
+            }
+            ExplicitLateBound::Yes
+        } else {
+            ExplicitLateBound::No
+        }
+    }
+
     // FIXME(eddyb, varkor) handle type paths here too, not just value ones.
     pub fn def_ids_for_value_path_segments(
         &self,
diff --git a/src/librustc_typeck/check/autoderef.rs b/src/librustc_typeck/check/autoderef.rs
index d4c01a82e0a..73d4e2b7820 100644
--- a/src/librustc_typeck/check/autoderef.rs
+++ b/src/librustc_typeck/check/autoderef.rs
@@ -48,7 +48,7 @@ impl<'a, 'tcx> Iterator for Autoderef<'a, 'tcx> {
             return Some((self.cur_ty, 0));
         }
 
-        if self.steps.len() >= tcx.sess.recursion_limit() {
+        if !tcx.sess.recursion_limit().value_within_limit(self.steps.len()) {
             if !self.silence_errors {
                 report_autoderef_recursion_limit_error(tcx, self.span, self.cur_ty);
             }
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 52ddacc1c4b..f4e46a04931 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -21,11 +21,31 @@ use rustc_target::spec::abi;
 /// Checks that it is legal to call methods of the trait corresponding
 /// to `trait_id` (this only cares about the trait, not the specific
 /// method that is called).
-pub fn check_legal_trait_for_method_call(tcx: TyCtxt<'_>, span: Span, trait_id: DefId) {
+pub fn check_legal_trait_for_method_call(
+    tcx: TyCtxt<'_>,
+    span: Span,
+    receiver: Option<Span>,
+    trait_id: DefId,
+) {
     if tcx.lang_items().drop_trait() == Some(trait_id) {
-        struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method")
-            .span_label(span, "explicit destructor calls not allowed")
-            .emit();
+        let mut err = struct_span_err!(tcx.sess, span, E0040, "explicit use of destructor method");
+        err.span_label(span, "explicit destructor calls not allowed");
+
+        let snippet = receiver
+            .and_then(|s| tcx.sess.source_map().span_to_snippet(s).ok())
+            .unwrap_or_default();
+
+        let suggestion =
+            if snippet.is_empty() { "drop".to_string() } else { format!("drop({})", snippet) };
+
+        err.span_suggestion(
+            span,
+            &format!("consider using `drop` function: `{}`", suggestion),
+            String::new(),
+            Applicability::Unspecified,
+        );
+
+        err.emit();
     }
 }
 
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 410c5efdf37..48d27387476 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -312,7 +312,7 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             parent_substs,
             false,
             None,
-            arg_count_correct.is_ok(),
+            arg_count_correct,
             // Provide the generic args, and whether types should be inferred.
             |def_id| {
                 // The last component of the returned tuple here is unimportant.
@@ -597,9 +597,12 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
     fn enforce_illegal_method_limitations(&self, pick: &probe::Pick<'_>) {
         // Disallow calls to the method `drop` defined in the `Drop` trait.
         match pick.item.container {
-            ty::TraitContainer(trait_def_id) => {
-                callee::check_legal_trait_for_method_call(self.tcx, self.span, trait_def_id)
-            }
+            ty::TraitContainer(trait_def_id) => callee::check_legal_trait_for_method_call(
+                self.tcx,
+                self.span,
+                Some(self.self_expr.span),
+                trait_def_id,
+            ),
             ty::ImplContainer(..) => {}
         }
     }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index da711b9d480..a8fa65a135a 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -87,7 +87,9 @@ mod upvar;
 mod wfcheck;
 pub mod writeback;
 
-use crate::astconv::{AstConv, GenericArgCountMismatch, PathSeg};
+use crate::astconv::{
+    AstConv, ExplicitLateBound, GenericArgCountMismatch, GenericArgCountResult, PathSeg,
+};
 use rustc_ast::ast;
 use rustc_ast::util::parser::ExprPrecedence;
 use rustc_attr as attr;
@@ -5433,7 +5435,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 debug!("instantiate_value_path: def_id={:?} container={:?}", def_id, container);
                 match container {
                     ty::TraitContainer(trait_did) => {
-                        callee::check_legal_trait_for_method_call(tcx, span, trait_did)
+                        callee::check_legal_trait_for_method_call(tcx, span, None, trait_did)
                     }
                     ty::ImplContainer(impl_def_id) => {
                         if segments.len() == 1 {
@@ -5495,11 +5497,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // parameter internally, but we don't allow users to specify the
             // parameter's value explicitly, so we have to do some error-
             // checking here.
-            if let Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }) =
-                AstConv::check_generic_arg_count_for_call(
-                    tcx, span, &generics, &seg, false, // `is_method_call`
-                )
-            {
+            if let GenericArgCountResult {
+                correct: Err(GenericArgCountMismatch { reported: Some(ErrorReported), .. }),
+                ..
+            } = AstConv::check_generic_arg_count_for_call(
+                tcx, span, &generics, &seg, false, // `is_method_call`
+            ) {
                 infer_args_for_err.insert(index);
                 self.set_tainted_by_errors(); // See issue #53251.
             }
@@ -5555,6 +5558,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // escaping late-bound regions, and nor should the base type scheme.
         let ty = tcx.type_of(def_id);
 
+        let arg_count = GenericArgCountResult {
+            explicit_late_bound: ExplicitLateBound::No,
+            correct: if infer_args_for_err.is_empty() {
+                Ok(())
+            } else {
+                Err(GenericArgCountMismatch::default())
+            },
+        };
+
         let substs = self_ctor_substs.unwrap_or_else(|| {
             AstConv::create_substs_for_generic_args(
                 tcx,
@@ -5562,7 +5574,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &[][..],
                 has_self,
                 self_ty,
-                infer_args_for_err.is_empty(),
+                arg_count,
                 // Provide the generic args, and whether types should be inferred.
                 |def_id| {
                     if let Some(&PathSeg(_, index)) =
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 00ff2af82e3..d89993e3547 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -121,9 +121,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         match BinOpCategory::from(op) {
             BinOpCategory::Shortcircuit => {
-                self.demand_suptype(*lhs_span, tcx.mk_bool(), lhs_ty);
-                self.demand_suptype(*rhs_span, tcx.mk_bool(), rhs_ty);
-                tcx.mk_bool()
+                self.demand_suptype(*lhs_span, tcx.types.bool, lhs_ty);
+                self.demand_suptype(*rhs_span, tcx.types.bool, rhs_ty);
+                tcx.types.bool
             }
 
             BinOpCategory::Shift => {
@@ -140,7 +140,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             BinOpCategory::Comparison => {
                 // both LHS and RHS and result will have the same type
                 self.demand_suptype(*rhs_span, lhs_ty, rhs_ty);
-                tcx.mk_bool()
+                tcx.types.bool
             }
         }
     }
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 8707e4fe84a..19a23e5a594 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -112,7 +112,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         if let Some(upvars) = self.tcx.upvars_mentioned(closure_def_id) {
-            let mut upvar_list: FxIndexMap<hir::HirId, ty::UpvarId> =
+            let mut closure_captures: FxIndexMap<hir::HirId, ty::UpvarId> =
                 FxIndexMap::with_capacity_and_hasher(upvars.len(), Default::default());
             for (&var_hir_id, _) in upvars.iter() {
                 let upvar_id = ty::UpvarId {
@@ -122,7 +122,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 debug!("seed upvar_id {:?}", upvar_id);
                 // Adding the upvar Id to the list of Upvars, which will be added
                 // to the map for the closure at the end of the for loop.
-                upvar_list.insert(var_hir_id, upvar_id);
+                closure_captures.insert(var_hir_id, upvar_id);
 
                 let capture_kind = match capture_clause {
                     hir::CaptureBy::Value => ty::UpvarCapture::ByValue,
@@ -140,8 +140,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Add the vector of upvars to the map keyed with the closure id.
             // This gives us an easier access to them without having to call
             // tcx.upvars again..
-            if !upvar_list.is_empty() {
-                self.tables.borrow_mut().upvar_list.insert(closure_def_id, upvar_list);
+            if !closure_captures.is_empty() {
+                self.tables.borrow_mut().closure_captures.insert(closure_def_id, closure_captures);
             }
         }
 
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 154ca391aa5..3473dc7a58d 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -74,8 +74,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!("used_trait_imports({:?}) = {:?}", item_def_id, used_trait_imports);
         wbcx.tables.used_trait_imports = used_trait_imports;
 
-        wbcx.tables.upvar_list =
-            mem::replace(&mut self.tables.borrow_mut().upvar_list, Default::default());
+        wbcx.tables.closure_captures =
+            mem::replace(&mut self.tables.borrow_mut().closure_captures, Default::default());
 
         if self.is_tainted_by_errors() {
             // FIXME(eddyb) keep track of `ErrorReported` from where the error was emitted.
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index bf59b3f2573..99ca7084c30 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -226,6 +226,11 @@ where
 {
     let warnings_lint_name = lint::builtin::WARNINGS.name;
 
+    // Whitelist feature-gated lints to avoid feature errors when trying to
+    // allow all lints.
+    // FIXME(#72694): handle feature-gated lints properly.
+    let unsafe_op_in_unsafe_fn_name = rustc_lint::builtin::UNSAFE_OP_IN_UNSAFE_FN.name;
+
     whitelisted_lints.push(warnings_lint_name.to_owned());
     whitelisted_lints.extend(lint_opts.iter().map(|(lint, _)| lint).cloned());
 
@@ -236,7 +241,13 @@ where
     };
 
     let lint_opts = lints()
-        .filter_map(|lint| if lint.name == warnings_lint_name { None } else { filter_call(lint) })
+        .filter_map(|lint| {
+            if lint.name == warnings_lint_name || lint.name == unsafe_op_in_unsafe_fn_name {
+                None
+            } else {
+                filter_call(lint)
+            }
+        })
         .chain(lint_opts.into_iter())
         .collect::<Vec<_>>();
 
diff --git a/src/libstd/collections/hash/map.rs b/src/libstd/collections/hash/map.rs
index 56cf9be3391..5ba5eff4407 100644
--- a/src/libstd/collections/hash/map.rs
+++ b/src/libstd/collections/hash/map.rs
@@ -2426,6 +2426,24 @@ where
     fn extend<T: IntoIterator<Item = (K, V)>>(&mut self, iter: T) {
         self.base.extend(iter)
     }
+
+    #[inline]
+    fn extend_one(&mut self, (k, v): (K, V)) {
+        self.base.insert(k, v);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        // self.base.extend_reserve(additional);
+        // FIXME: hashbrown should implement this method.
+        // But until then, use the same reservation logic:
+
+        // Reserve the entire hint lower bound if the map is empty.
+        // Otherwise reserve half the hint (rounded up), so the map
+        // will only resize twice in the worst case.
+        let reserve = if self.is_empty() { additional } else { (additional + 1) / 2 };
+        self.base.reserve(reserve);
+    }
 }
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
@@ -2439,6 +2457,16 @@ where
     fn extend<T: IntoIterator<Item = (&'a K, &'a V)>>(&mut self, iter: T) {
         self.base.extend(iter)
     }
+
+    #[inline]
+    fn extend_one(&mut self, (&k, &v): (&'a K, &'a V)) {
+        self.base.insert(k, v);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        Extend::<(K, V)>::extend_reserve(self, additional)
+    }
 }
 
 /// `RandomState` is the default state for [`HashMap`] types.
diff --git a/src/libstd/collections/hash/set.rs b/src/libstd/collections/hash/set.rs
index ca06457291c..cb2f829803b 100644
--- a/src/libstd/collections/hash/set.rs
+++ b/src/libstd/collections/hash/set.rs
@@ -970,6 +970,16 @@ where
     fn extend<I: IntoIterator<Item = T>>(&mut self, iter: I) {
         self.map.extend(iter.into_iter().map(|k| (k, ())));
     }
+
+    #[inline]
+    fn extend_one(&mut self, item: T) {
+        self.map.insert(item, ());
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        self.map.extend_reserve(additional);
+    }
 }
 
 #[stable(feature = "hash_extend_copy", since = "1.4.0")]
@@ -982,6 +992,16 @@ where
     fn extend<I: IntoIterator<Item = &'a T>>(&mut self, iter: I) {
         self.extend(iter.into_iter().cloned());
     }
+
+    #[inline]
+    fn extend_one(&mut self, &item: &'a T) {
+        self.map.insert(item, ());
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        Extend::<T>::extend_reserve(self, additional)
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/f32.rs b/src/libstd/f32.rs
index deb9eb5b4b0..8ff19557a30 100644
--- a/src/libstd/f32.rs
+++ b/src/libstd/f32.rs
@@ -1531,4 +1531,147 @@ mod tests {
     fn test_clamp_max_is_nan() {
         let _ = 1.0f32.clamp(3.0, NAN);
     }
+
+    #[test]
+    fn test_total_cmp() {
+        use core::cmp::Ordering;
+
+        fn quiet_bit_mask() -> u32 {
+            1 << (f32::MANTISSA_DIGITS - 2)
+        }
+
+        fn min_subnorm() -> f32 {
+            f32::MIN_POSITIVE / f32::powf(2.0, f32::MANTISSA_DIGITS as f32 - 1.0)
+        }
+
+        fn max_subnorm() -> f32 {
+            f32::MIN_POSITIVE - min_subnorm()
+        }
+
+        fn q_nan() -> f32 {
+            f32::from_bits(f32::NAN.to_bits() | quiet_bit_mask())
+        }
+
+        fn s_nan() -> f32 {
+            f32::from_bits((f32::NAN.to_bits() & !quiet_bit_mask()) + 42)
+        }
+
+        assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+        assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Equal, (-f32::INFINITY).total_cmp(&-f32::INFINITY));
+        assert_eq!(Ordering::Equal, (-f32::MAX).total_cmp(&-f32::MAX));
+        assert_eq!(Ordering::Equal, (-2.5_f32).total_cmp(&-2.5));
+        assert_eq!(Ordering::Equal, (-1.0_f32).total_cmp(&-1.0));
+        assert_eq!(Ordering::Equal, (-1.5_f32).total_cmp(&-1.5));
+        assert_eq!(Ordering::Equal, (-0.5_f32).total_cmp(&-0.5));
+        assert_eq!(Ordering::Equal, (-f32::MIN_POSITIVE).total_cmp(&-f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Equal, (-0.0_f32).total_cmp(&-0.0));
+        assert_eq!(Ordering::Equal, 0.0_f32.total_cmp(&0.0));
+        assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Equal, f32::MIN_POSITIVE.total_cmp(&f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, 0.5_f32.total_cmp(&0.5));
+        assert_eq!(Ordering::Equal, 1.0_f32.total_cmp(&1.0));
+        assert_eq!(Ordering::Equal, 1.5_f32.total_cmp(&1.5));
+        assert_eq!(Ordering::Equal, 2.5_f32.total_cmp(&2.5));
+        assert_eq!(Ordering::Equal, f32::MAX.total_cmp(&f32::MAX));
+        assert_eq!(Ordering::Equal, f32::INFINITY.total_cmp(&f32::INFINITY));
+        assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+        assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
+        assert_eq!(Ordering::Less, (-f32::INFINITY).total_cmp(&-f32::MAX));
+        assert_eq!(Ordering::Less, (-f32::MAX).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-2.5_f32).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-1.5_f32).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-1.0_f32).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-0.5_f32).total_cmp(&-f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-f32::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-0.0_f32).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, 0.0_f32.total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, f32::MIN_POSITIVE.total_cmp(&0.5));
+        assert_eq!(Ordering::Less, 0.5_f32.total_cmp(&1.0));
+        assert_eq!(Ordering::Less, 1.0_f32.total_cmp(&1.5));
+        assert_eq!(Ordering::Less, 1.5_f32.total_cmp(&2.5));
+        assert_eq!(Ordering::Less, 2.5_f32.total_cmp(&f32::MAX));
+        assert_eq!(Ordering::Less, f32::MAX.total_cmp(&f32::INFINITY));
+        assert_eq!(Ordering::Less, f32::INFINITY.total_cmp(&s_nan()));
+        assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+        assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+        assert_eq!(Ordering::Greater, (-f32::INFINITY).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Greater, (-f32::MAX).total_cmp(&-f32::INFINITY));
+        assert_eq!(Ordering::Greater, (-2.5_f32).total_cmp(&-f32::MAX));
+        assert_eq!(Ordering::Greater, (-1.5_f32).total_cmp(&-2.5));
+        assert_eq!(Ordering::Greater, (-1.0_f32).total_cmp(&-1.5));
+        assert_eq!(Ordering::Greater, (-0.5_f32).total_cmp(&-1.0));
+        assert_eq!(Ordering::Greater, (-f32::MIN_POSITIVE).total_cmp(&-0.5));
+        assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Greater, (-0.0_f32).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Greater, 0.0_f32.total_cmp(&-0.0));
+        assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+        assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Greater, f32::MIN_POSITIVE.total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Greater, 0.5_f32.total_cmp(&f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, 1.0_f32.total_cmp(&0.5));
+        assert_eq!(Ordering::Greater, 1.5_f32.total_cmp(&1.0));
+        assert_eq!(Ordering::Greater, 2.5_f32.total_cmp(&1.5));
+        assert_eq!(Ordering::Greater, f32::MAX.total_cmp(&2.5));
+        assert_eq!(Ordering::Greater, f32::INFINITY.total_cmp(&f32::MAX));
+        assert_eq!(Ordering::Greater, s_nan().total_cmp(&f32::INFINITY));
+        assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::INFINITY));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MAX));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::MAX));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f32::INFINITY));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::INFINITY));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MAX));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::MAX));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f32::INFINITY));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+    }
 }
diff --git a/src/libstd/f64.rs b/src/libstd/f64.rs
index b79e550ed26..d7845fd2c4d 100644
--- a/src/libstd/f64.rs
+++ b/src/libstd/f64.rs
@@ -1554,4 +1554,147 @@ mod tests {
     fn test_clamp_max_is_nan() {
         let _ = 1.0f64.clamp(3.0, NAN);
     }
+
+    #[test]
+    fn test_total_cmp() {
+        use core::cmp::Ordering;
+
+        fn quiet_bit_mask() -> u64 {
+            1 << (f64::MANTISSA_DIGITS - 2)
+        }
+
+        fn min_subnorm() -> f64 {
+            f64::MIN_POSITIVE / f64::powf(2.0, f64::MANTISSA_DIGITS as f64 - 1.0)
+        }
+
+        fn max_subnorm() -> f64 {
+            f64::MIN_POSITIVE - min_subnorm()
+        }
+
+        fn q_nan() -> f64 {
+            f64::from_bits(f64::NAN.to_bits() | quiet_bit_mask())
+        }
+
+        fn s_nan() -> f64 {
+            f64::from_bits((f64::NAN.to_bits() & !quiet_bit_mask()) + 42)
+        }
+
+        assert_eq!(Ordering::Equal, (-q_nan()).total_cmp(&-q_nan()));
+        assert_eq!(Ordering::Equal, (-s_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Equal, (-f64::INFINITY).total_cmp(&-f64::INFINITY));
+        assert_eq!(Ordering::Equal, (-f64::MAX).total_cmp(&-f64::MAX));
+        assert_eq!(Ordering::Equal, (-2.5_f64).total_cmp(&-2.5));
+        assert_eq!(Ordering::Equal, (-1.0_f64).total_cmp(&-1.0));
+        assert_eq!(Ordering::Equal, (-1.5_f64).total_cmp(&-1.5));
+        assert_eq!(Ordering::Equal, (-0.5_f64).total_cmp(&-0.5));
+        assert_eq!(Ordering::Equal, (-f64::MIN_POSITIVE).total_cmp(&-f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, (-max_subnorm()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Equal, (-min_subnorm()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Equal, (-0.0_f64).total_cmp(&-0.0));
+        assert_eq!(Ordering::Equal, 0.0_f64.total_cmp(&0.0));
+        assert_eq!(Ordering::Equal, min_subnorm().total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Equal, max_subnorm().total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Equal, f64::MIN_POSITIVE.total_cmp(&f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Equal, 0.5_f64.total_cmp(&0.5));
+        assert_eq!(Ordering::Equal, 1.0_f64.total_cmp(&1.0));
+        assert_eq!(Ordering::Equal, 1.5_f64.total_cmp(&1.5));
+        assert_eq!(Ordering::Equal, 2.5_f64.total_cmp(&2.5));
+        assert_eq!(Ordering::Equal, f64::MAX.total_cmp(&f64::MAX));
+        assert_eq!(Ordering::Equal, f64::INFINITY.total_cmp(&f64::INFINITY));
+        assert_eq!(Ordering::Equal, s_nan().total_cmp(&s_nan()));
+        assert_eq!(Ordering::Equal, q_nan().total_cmp(&q_nan()));
+
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
+        assert_eq!(Ordering::Less, (-f64::INFINITY).total_cmp(&-f64::MAX));
+        assert_eq!(Ordering::Less, (-f64::MAX).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-2.5_f64).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-1.5_f64).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-1.0_f64).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-0.5_f64).total_cmp(&-f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-f64::MIN_POSITIVE).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-max_subnorm()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-min_subnorm()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-0.0_f64).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, 0.0_f64.total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, min_subnorm().total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, max_subnorm().total_cmp(&f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, f64::MIN_POSITIVE.total_cmp(&0.5));
+        assert_eq!(Ordering::Less, 0.5_f64.total_cmp(&1.0));
+        assert_eq!(Ordering::Less, 1.0_f64.total_cmp(&1.5));
+        assert_eq!(Ordering::Less, 1.5_f64.total_cmp(&2.5));
+        assert_eq!(Ordering::Less, 2.5_f64.total_cmp(&f64::MAX));
+        assert_eq!(Ordering::Less, f64::MAX.total_cmp(&f64::INFINITY));
+        assert_eq!(Ordering::Less, f64::INFINITY.total_cmp(&s_nan()));
+        assert_eq!(Ordering::Less, s_nan().total_cmp(&q_nan()));
+
+        assert_eq!(Ordering::Greater, (-s_nan()).total_cmp(&-q_nan()));
+        assert_eq!(Ordering::Greater, (-f64::INFINITY).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Greater, (-f64::MAX).total_cmp(&-f64::INFINITY));
+        assert_eq!(Ordering::Greater, (-2.5_f64).total_cmp(&-f64::MAX));
+        assert_eq!(Ordering::Greater, (-1.5_f64).total_cmp(&-2.5));
+        assert_eq!(Ordering::Greater, (-1.0_f64).total_cmp(&-1.5));
+        assert_eq!(Ordering::Greater, (-0.5_f64).total_cmp(&-1.0));
+        assert_eq!(Ordering::Greater, (-f64::MIN_POSITIVE).total_cmp(&-0.5));
+        assert_eq!(Ordering::Greater, (-max_subnorm()).total_cmp(&-f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, (-min_subnorm()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Greater, (-0.0_f64).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Greater, 0.0_f64.total_cmp(&-0.0));
+        assert_eq!(Ordering::Greater, min_subnorm().total_cmp(&0.0));
+        assert_eq!(Ordering::Greater, max_subnorm().total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Greater, f64::MIN_POSITIVE.total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Greater, 0.5_f64.total_cmp(&f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Greater, 1.0_f64.total_cmp(&0.5));
+        assert_eq!(Ordering::Greater, 1.5_f64.total_cmp(&1.0));
+        assert_eq!(Ordering::Greater, 2.5_f64.total_cmp(&1.5));
+        assert_eq!(Ordering::Greater, f64::MAX.total_cmp(&2.5));
+        assert_eq!(Ordering::Greater, f64::INFINITY.total_cmp(&f64::MAX));
+        assert_eq!(Ordering::Greater, s_nan().total_cmp(&f64::INFINITY));
+        assert_eq!(Ordering::Greater, q_nan().total_cmp(&s_nan()));
+
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-s_nan()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::INFINITY));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MAX));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&0.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.0));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&1.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&2.5));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::MAX));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&f64::INFINITY));
+        assert_eq!(Ordering::Less, (-q_nan()).total_cmp(&s_nan()));
+
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::INFINITY));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MAX));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-2.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-1.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-max_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-min_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&-0.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&min_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&max_subnorm()));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MIN_POSITIVE));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&0.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.0));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&1.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&2.5));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::MAX));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&f64::INFINITY));
+        assert_eq!(Ordering::Less, (-s_nan()).total_cmp(&s_nan()));
+    }
 }
diff --git a/src/libstd/lib.rs b/src/libstd/lib.rs
index cc3e613fa3d..9ddaa100c0e 100644
--- a/src/libstd/lib.rs
+++ b/src/libstd/lib.rs
@@ -263,6 +263,7 @@
 #![feature(duration_constants)]
 #![feature(exact_size_is_empty)]
 #![feature(exhaustive_patterns)]
+#![feature(extend_one)]
 #![feature(external_doc)]
 #![feature(fn_traits)]
 #![feature(format_args_nl)]
@@ -311,6 +312,7 @@
 #![feature(test)]
 #![feature(thread_local)]
 #![feature(toowned_clone_into)]
+#![feature(total_cmp)]
 #![feature(trace_macros)]
 #![feature(track_caller)]
 #![feature(try_reserve)]
diff --git a/src/libstd/net/addr.rs b/src/libstd/net/addr.rs
index 08536de4d55..b780340884e 100644
--- a/src/libstd/net/addr.rs
+++ b/src/libstd/net/addr.rs
@@ -2,7 +2,7 @@ use crate::cmp::Ordering;
 use crate::convert::TryInto;
 use crate::fmt;
 use crate::hash;
-use crate::io;
+use crate::io::{self, Write};
 use crate::iter;
 use crate::mem;
 use crate::net::{htons, ntohs, IpAddr, Ipv4Addr, Ipv6Addr};
@@ -600,7 +600,26 @@ impl fmt::Display for SocketAddr {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV4 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{}:{}", self.ip(), self.port())
+        // Fast path: if there's no alignment stuff, write to the output buffer
+        // directly
+        if f.precision().is_none() && f.width().is_none() {
+            write!(f, "{}:{}", self.ip(), self.port())
+        } else {
+            const IPV4_SOCKET_BUF_LEN: usize = (3 * 4)  // the segments
+                + 3  // the separators
+                + 1 + 5; // the port
+            let mut buf = [0; IPV4_SOCKET_BUF_LEN];
+            let mut buf_slice = &mut buf[..];
+
+            // Unwrap is fine because writing to a sufficiently-sized
+            // buffer is infallible
+            write!(buf_slice, "{}:{}", self.ip(), self.port()).unwrap();
+            let len = IPV4_SOCKET_BUF_LEN - buf_slice.len();
+
+            // This unsafe is OK because we know what is being written to the buffer
+            let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+            f.pad(buf)
+        }
     }
 }
 
@@ -614,7 +633,28 @@ impl fmt::Debug for SocketAddrV4 {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for SocketAddrV6 {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "[{}]:{}", self.ip(), self.port())
+        // Fast path: if there's no alignment stuff, write to the output
+        // buffer directly
+        if f.precision().is_none() && f.width().is_none() {
+            write!(f, "[{}]:{}", self.ip(), self.port())
+        } else {
+            const IPV6_SOCKET_BUF_LEN: usize = (4 * 8)  // The address
+            + 7  // The colon separators
+            + 2  // The brackets
+            + 1 + 5; // The port
+
+            let mut buf = [0; IPV6_SOCKET_BUF_LEN];
+            let mut buf_slice = &mut buf[..];
+
+            // Unwrap is fine because writing to a sufficiently-sized
+            // buffer is infallible
+            write!(buf_slice, "[{}]:{}", self.ip(), self.port()).unwrap();
+            let len = IPV6_SOCKET_BUF_LEN - buf_slice.len();
+
+            // This unsafe is OK because we know what is being written to the buffer
+            let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+            f.pad(buf)
+        }
     }
 }
 
@@ -1169,6 +1209,28 @@ mod tests {
     }
 
     #[test]
+    fn socket_v4_to_str() {
+        let socket = SocketAddrV4::new(Ipv4Addr::new(192, 168, 0, 1), 8080);
+
+        assert_eq!(format!("{}", socket), "192.168.0.1:8080");
+        assert_eq!(format!("{:<20}", socket), "192.168.0.1:8080    ");
+        assert_eq!(format!("{:>20}", socket), "    192.168.0.1:8080");
+        assert_eq!(format!("{:^20}", socket), "  192.168.0.1:8080  ");
+        assert_eq!(format!("{:.10}", socket), "192.168.0.");
+    }
+
+    #[test]
+    fn socket_v6_to_str() {
+        let socket: SocketAddrV6 = "[2a02:6b8:0:1::1]:53".parse().unwrap();
+
+        assert_eq!(format!("{}", socket), "[2a02:6b8:0:1::1]:53");
+        assert_eq!(format!("{:<24}", socket), "[2a02:6b8:0:1::1]:53    ");
+        assert_eq!(format!("{:>24}", socket), "    [2a02:6b8:0:1::1]:53");
+        assert_eq!(format!("{:^24}", socket), "  [2a02:6b8:0:1::1]:53  ");
+        assert_eq!(format!("{:.15}", socket), "[2a02:6b8:0:1::");
+    }
+
+    #[test]
     fn compare() {
         let v4_1 = "224.120.45.1:23456".parse::<SocketAddrV4>().unwrap();
         let v4_2 = "224.210.103.5:12345".parse::<SocketAddrV4>().unwrap();
diff --git a/src/libstd/net/ip.rs b/src/libstd/net/ip.rs
index 6e2478b8308..0f0be2c4883 100644
--- a/src/libstd/net/ip.rs
+++ b/src/libstd/net/ip.rs
@@ -7,9 +7,9 @@
 )]
 
 use crate::cmp::Ordering;
-use crate::fmt;
+use crate::fmt::{self, Write as FmtWrite};
 use crate::hash;
-use crate::io::Write;
+use crate::io::Write as IoWrite;
 use crate::sys::net::netc as c;
 use crate::sys_common::{AsInner, FromInner};
 
@@ -1532,102 +1532,100 @@ impl Ipv6Addr {
     }
 }
 
+/// Write an Ipv6Addr, conforming to the canonical style described by
+/// [RFC 5952](https://tools.ietf.org/html/rfc5952).
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Display for Ipv6Addr {
-    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Note: The calls to write should never fail, hence the unwraps in the function
-        // Long enough for the longest possible IPv6: 39
-        const IPV6_BUF_LEN: usize = 39;
-        let mut buf = [0u8; IPV6_BUF_LEN];
-        let mut buf_slice = &mut buf[..];
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // If there are no alignment requirements, write out the IP address to
+        // f. Otherwise, write it to a local buffer, then use f.pad.
+        if f.precision().is_none() && f.width().is_none() {
+            let segments = self.segments();
+
+            // Special case for :: and ::1; otherwise they get written with the
+            // IPv4 formatter
+            if self.is_unspecified() {
+                f.write_str("::")
+            } else if self.is_loopback() {
+                f.write_str("::1")
+            } else if let Some(ipv4) = self.to_ipv4() {
+                match segments[5] {
+                    // IPv4 Compatible address
+                    0 => write!(f, "::{}", ipv4),
+                    // IPv4 Mapped address
+                    0xffff => write!(f, "::ffff:{}", ipv4),
+                    _ => unreachable!(),
+                }
+            } else {
+                #[derive(Copy, Clone, Default)]
+                struct Span {
+                    start: usize,
+                    len: usize,
+                }
 
-        match self.segments() {
-            // We need special cases for :: and ::1, otherwise they're formatted
-            // as ::0.0.0.[01]
-            [0, 0, 0, 0, 0, 0, 0, 0] => write!(buf_slice, "::").unwrap(),
-            [0, 0, 0, 0, 0, 0, 0, 1] => write!(buf_slice, "::1").unwrap(),
-            // Ipv4 Compatible address
-            [0, 0, 0, 0, 0, 0, g, h] => {
-                write!(
-                    buf_slice,
-                    "::{}.{}.{}.{}",
-                    (g >> 8) as u8,
-                    g as u8,
-                    (h >> 8) as u8,
-                    h as u8
-                )
-                .unwrap();
-            }
-            // Ipv4-Mapped address
-            [0, 0, 0, 0, 0, 0xffff, g, h] => {
-                write!(
-                    buf_slice,
-                    "::ffff:{}.{}.{}.{}",
-                    (g >> 8) as u8,
-                    g as u8,
-                    (h >> 8) as u8,
-                    h as u8
-                )
-                .unwrap();
-            }
-            _ => {
-                fn find_zero_slice(segments: &[u16; 8]) -> (usize, usize) {
-                    let mut longest_span_len = 0;
-                    let mut longest_span_at = 0;
-                    let mut cur_span_len = 0;
-                    let mut cur_span_at = 0;
-
-                    for i in 0..8 {
-                        if segments[i] == 0 {
-                            if cur_span_len == 0 {
-                                cur_span_at = i;
+                // Find the inner 0 span
+                let zeroes = {
+                    let mut longest = Span::default();
+                    let mut current = Span::default();
+
+                    for (i, &segment) in segments.iter().enumerate() {
+                        if segment == 0 {
+                            if current.len == 0 {
+                                current.start = i;
                             }
 
-                            cur_span_len += 1;
+                            current.len += 1;
 
-                            if cur_span_len > longest_span_len {
-                                longest_span_len = cur_span_len;
-                                longest_span_at = cur_span_at;
+                            if current.len > longest.len {
+                                longest = current;
                             }
                         } else {
-                            cur_span_len = 0;
-                            cur_span_at = 0;
+                            current = Span::default();
                         }
                     }
 
-                    (longest_span_at, longest_span_len)
-                }
-
-                let (zeros_at, zeros_len) = find_zero_slice(&self.segments());
-
-                if zeros_len > 1 {
-                    fn fmt_subslice(segments: &[u16], buf: &mut &mut [u8]) {
-                        if !segments.is_empty() {
-                            write!(*buf, "{:x}", segments[0]).unwrap();
-                            for &seg in &segments[1..] {
-                                write!(*buf, ":{:x}", seg).unwrap();
-                            }
+                    longest
+                };
+
+                /// Write a colon-separated part of the address
+                #[inline]
+                fn fmt_subslice(f: &mut fmt::Formatter<'_>, chunk: &[u16]) -> fmt::Result {
+                    if let Some(first) = chunk.first() {
+                        fmt::LowerHex::fmt(first, f)?;
+                        for segment in &chunk[1..] {
+                            f.write_char(':')?;
+                            fmt::LowerHex::fmt(segment, f)?;
                         }
                     }
+                    Ok(())
+                }
 
-                    fmt_subslice(&self.segments()[..zeros_at], &mut buf_slice);
-                    write!(buf_slice, "::").unwrap();
-                    fmt_subslice(&self.segments()[zeros_at + zeros_len..], &mut buf_slice);
+                if zeroes.len > 1 {
+                    fmt_subslice(f, &segments[..zeroes.start])?;
+                    f.write_str("::")?;
+                    fmt_subslice(f, &segments[zeroes.start + zeroes.len..])
                 } else {
-                    let &[a, b, c, d, e, f, g, h] = &self.segments();
-                    write!(
-                        buf_slice,
-                        "{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}:{:x}",
-                        a, b, c, d, e, f, g, h
-                    )
-                    .unwrap();
+                    fmt_subslice(f, &segments)
                 }
             }
+        } else {
+            // Slow path: write the address to a local buffer, the use f.pad.
+            // Defined recursively by using the fast path to write to the
+            // buffer.
+
+            // This is the largest possible size of an IPv6 address
+            const IPV6_BUF_LEN: usize = (4 * 8) + 7;
+            let mut buf = [0u8; IPV6_BUF_LEN];
+            let mut buf_slice = &mut buf[..];
+
+            // Note: This call to write should never fail, so unwrap is okay.
+            write!(buf_slice, "{}", self).unwrap();
+            let len = IPV6_BUF_LEN - buf_slice.len();
+
+            // This is safe because we know exactly what can be in this buffer
+            let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
+            f.pad(buf)
         }
-        let len = IPV6_BUF_LEN - buf_slice.len();
-        // This is safe because we know exactly what can be in this buffer
-        let buf = unsafe { crate::str::from_utf8_unchecked(&buf[..len]) };
-        fmt.pad(buf)
     }
 }
 
diff --git a/src/libstd/path.rs b/src/libstd/path.rs
index 0fe5451bb95..8ff7508ba64 100644
--- a/src/libstd/path.rs
+++ b/src/libstd/path.rs
@@ -1534,6 +1534,11 @@ impl<P: AsRef<Path>> iter::Extend<P> for PathBuf {
     fn extend<I: IntoIterator<Item = P>>(&mut self, iter: I) {
         iter.into_iter().for_each(move |p| self.push(p.as_ref()));
     }
+
+    #[inline]
+    fn extend_one(&mut self, p: P) {
+        self.push(p.as_ref());
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/src/libstd/sys_common/wtf8.rs b/src/libstd/sys_common/wtf8.rs
index a98407da448..a5ba3daba3e 100644
--- a/src/libstd/sys_common/wtf8.rs
+++ b/src/libstd/sys_common/wtf8.rs
@@ -386,6 +386,17 @@ impl Extend<CodePoint> for Wtf8Buf {
         self.bytes.reserve(low);
         iterator.for_each(move |code_point| self.push(code_point));
     }
+
+    #[inline]
+    fn extend_one(&mut self, code_point: CodePoint) {
+        self.push(code_point);
+    }
+
+    #[inline]
+    fn extend_reserve(&mut self, additional: usize) {
+        // Lower bound of one byte per code point (ASCII only)
+        self.bytes.reserve(additional);
+    }
 }
 
 /// A borrowed slice of well-formed WTF-8 data.
diff --git a/src/test/assembly/asm/nvptx-types.rs b/src/test/assembly/asm/nvptx-types.rs
new file mode 100644
index 00000000000..4ee79d1bcc8
--- /dev/null
+++ b/src/test/assembly/asm/nvptx-types.rs
@@ -0,0 +1,133 @@
+// no-system-llvm
+// assembly-output: emit-asm
+// compile-flags: --target nvptx64-nvidia-cuda
+// compile-flags: --crate-type cdylib
+
+#![feature(no_core, lang_items, rustc_attrs)]
+#![no_core]
+
+#[rustc_builtin_macro]
+macro_rules! asm {
+    () => {};
+}
+#[rustc_builtin_macro]
+macro_rules! concat {
+    () => {};
+}
+
+#[lang = "sized"]
+trait Sized {}
+#[lang = "copy"]
+trait Copy {}
+
+type ptr = *mut u8;
+
+impl Copy for i8 {}
+impl Copy for i16 {}
+impl Copy for i32 {}
+impl Copy for f32 {}
+impl Copy for i64 {}
+impl Copy for f64 {}
+impl Copy for ptr {}
+
+// NVPTX does not support static variables
+#[no_mangle]
+fn extern_func() {}
+
+// CHECK-LABEL: .visible .func sym_fn()
+// CHECK: // begin inline asm
+// CHECK: call extern_func;
+// CHECK: // end inline asm
+#[no_mangle]
+pub unsafe fn sym_fn() {
+    asm!("call {};", sym extern_func);
+}
+
+macro_rules! check {
+    ($func:ident $ty:ident $class:ident $mov:literal) => {
+        #[no_mangle]
+        pub unsafe fn $func(x: $ty) -> $ty {
+            let y;
+            asm!(concat!($mov, " {}, {};"), out($class) y, in($class) x);
+            y
+        }
+    };
+}
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg16_i8 i8 reg16 "mov.i16");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg16_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i16 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg16_i16 i16 reg16 "mov.i16");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i8 i8 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i16 i16 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_i32
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_i32 i32 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg32_f32
+// CHECK: // begin inline asm
+// CHECK: mov.i32 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg32_f32 f32 reg32 "mov.i32");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i8
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i8 i8 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i16
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i16 i16 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_i32
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i32 i32 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b32 func_retval0) reg64_f32
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_f32 f32 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_i64
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_i64 i64 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_f64
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_f64 f64 reg64 "mov.i64");
+
+// CHECK-LABEL: .visible .func (.param .b64 func_retval0) reg64_ptr
+// CHECK: // begin inline asm
+// CHECK: mov.i64 %{{[a-z0-9]+}}, %{{[a-z0-9]+}};
+// CHECK: // end inline asm
+check!(reg64_ptr ptr reg64 "mov.i64");
diff --git a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
index 96fb16b1fcc..f313798de21 100644
--- a/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
+++ b/src/test/run-make-fulldeps/long-linker-command-lines/foo.rs
@@ -90,7 +90,7 @@ fn main() {
         }
 
         let linker_args = read_linker_args(&ok);
-        for mut arg in linker_args.split('S') {
+        for arg in linker_args.split('S') {
             expected_libs.remove(arg);
         }
 
diff --git a/src/test/ui/asm/issue-72570.rs b/src/test/ui/asm/issue-72570.rs
new file mode 100644
index 00000000000..f34525a664e
--- /dev/null
+++ b/src/test/ui/asm/issue-72570.rs
@@ -0,0 +1,10 @@
+// only-x86_64
+
+#![feature(asm)]
+
+fn main() {
+    unsafe {
+        asm!("", in("invalid") "".len());
+        //~^ ERROR: invalid register `invalid`: unknown register
+    }
+}
diff --git a/src/test/ui/asm/issue-72570.stderr b/src/test/ui/asm/issue-72570.stderr
new file mode 100644
index 00000000000..49013a23ced
--- /dev/null
+++ b/src/test/ui/asm/issue-72570.stderr
@@ -0,0 +1,8 @@
+error: invalid register `invalid`: unknown register
+  --> $DIR/issue-72570.rs:7:18
+   |
+LL |         asm!("", in("invalid") "".len());
+   |                  ^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/asm/sym.rs b/src/test/ui/asm/sym.rs
new file mode 100644
index 00000000000..83a3672af49
--- /dev/null
+++ b/src/test/ui/asm/sym.rs
@@ -0,0 +1,38 @@
+// no-system-llvm
+// only-x86_64
+// run-pass
+
+#![feature(asm, track_caller)]
+
+extern "C" fn f1() -> i32 {
+    111
+}
+
+// The compiler will generate a shim to hide the caller location parameter.
+#[track_caller]
+fn f2() -> i32 {
+    222
+}
+
+macro_rules! call {
+    ($func:path) => {{
+        let result: i32;
+        unsafe {
+            asm!("call {}", sym $func,
+                out("rax") result,
+                out("rcx") _, out("rdx") _, out("rdi") _, out("rsi") _,
+                out("r8") _, out("r9") _, out("r10") _, out("r11") _,
+                out("xmm0") _, out("xmm1") _, out("xmm2") _, out("xmm3") _,
+                out("xmm4") _, out("xmm5") _, out("xmm6") _, out("xmm7") _,
+                out("xmm8") _, out("xmm9") _, out("xmm10") _, out("xmm11") _,
+                out("xmm12") _, out("xmm13") _, out("xmm14") _, out("xmm15") _,
+            );
+        }
+        result
+    }}
+}
+
+fn main() {
+    assert_eq!(call!(f1), 111);
+    assert_eq!(call!(f2), 222);
+}
diff --git a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
index 3e39c8a7924..137cb83ccd3 100644
--- a/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
+++ b/src/test/ui/associated-types/cache/project-fn-ret-invariant.transmute.stderr
@@ -14,16 +14,16 @@ note: ...so that the expression is assignable
    |
 LL |    bar(foo, x)
    |             ^
-   = note: expected  `Type<'_>`
-              found  `Type<'a>`
+   = note: expected `Type<'_>`
+              found `Type<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the expression is assignable
   --> $DIR/project-fn-ret-invariant.rs:48:4
    |
 LL |    bar(foo, x)
    |    ^^^^^^^^^^^
-   = note: expected  `Type<'static>`
-              found  `Type<'_>`
+   = note: expected `Type<'static>`
+              found `Type<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/ast-json/ast-json-noexpand-output.stdout b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
index f60b6a00be1..c7b0fbeb0e3 100644
--- a/src/test/ui/ast-json/ast-json-noexpand-output.stdout
+++ b/src/test/ui/ast-json/ast-json-noexpand-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/ast-json/ast-json-output.stdout b/src/test/ui/ast-json/ast-json-output.stdout
index 42e7e789980..59ed68c2a77 100644
--- a/src/test/ui/ast-json/ast-json-output.stdout
+++ b/src/test/ui/ast-json/ast-json-output.stdout
@@ -1 +1 @@
-{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["extern",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["crate",false]},"span":{"lo":0,"hi":0}}]},"NonJoint"],[{"variant":"Token","fields":[{"kind":{"variant":"Ident","fields":["core",false]},"span":{"lo":0,"hi":0}}]},"Joint"],[{"variant":"Token","fields":[{"kind":"Semi","span":{"lo":0,"hi":0}}]},"NonJoint"]]}}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
+{"module":{"inner":{"lo":0,"hi":0},"items":[{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"prelude_import","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"","span":{"lo":0,"hi":0}},"kind":{"variant":"Use","fields":[{"prefix":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"{{root}}","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"std","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"prelude","span":{"lo":0,"hi":0}},"id":0,"args":null},{"ident":{"name":"v1","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"kind":"Glob","span":{"lo":0,"hi":0}}]},"tokens":null},{"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"macro_use","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":"Empty"}]},"id":null,"style":"Outer","span":{"lo":0,"hi":0}}],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"std","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null},{"attrs":[],"id":0,"span":{"lo":0,"hi":0},"vis":{"node":"Inherited","span":{"lo":0,"hi":0}},"ident":{"name":"core","span":{"lo":0,"hi":0}},"kind":{"variant":"ExternCrate","fields":[null]},"tokens":null}],"inline":true},"attrs":[{"kind":{"variant":"Normal","fields":[{"path":{"span":{"lo":0,"hi":0},"segments":[{"ident":{"name":"crate_type","span":{"lo":0,"hi":0}},"id":0,"args":null}]},"args":{"variant":"Eq","fields":[{"lo":0,"hi":0},{"_field0":[[{"variant":"Token","fields":[{"kind":{"variant":"Literal","fields":[{"kind":"Str","symbol":"lib","suffix":null}]},"span":{"lo":0,"hi":0}}]},"NonJoint"]]}]}}]},"id":null,"style":"Inner","span":{"lo":0,"hi":0}}],"span":{"lo":0,"hi":0},"proc_macros":[]}
diff --git a/src/test/ui/async-await/issue-72590-type-error-sized.rs b/src/test/ui/async-await/issue-72590-type-error-sized.rs
new file mode 100644
index 00000000000..00e098d43e0
--- /dev/null
+++ b/src/test/ui/async-await/issue-72590-type-error-sized.rs
@@ -0,0 +1,22 @@
+// Regression test for issue #72590
+// Tests that we don't emit a spurious "size cannot be statically determined" error
+// edition:2018
+
+struct Foo {
+    foo: Nonexistent, //~ ERROR cannot find
+    other: str
+}
+
+struct Bar {
+    test: Missing //~ ERROR cannot find
+}
+
+impl Foo {
+    async fn frob(self) {} //~ ERROR the size
+}
+
+impl Bar {
+    async fn myfn(self) {}
+}
+
+fn main() {}
diff --git a/src/test/ui/async-await/issue-72590-type-error-sized.stderr b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
new file mode 100644
index 00000000000..603895b598c
--- /dev/null
+++ b/src/test/ui/async-await/issue-72590-type-error-sized.stderr
@@ -0,0 +1,28 @@
+error[E0412]: cannot find type `Nonexistent` in this scope
+  --> $DIR/issue-72590-type-error-sized.rs:6:10
+   |
+LL |     foo: Nonexistent,
+   |          ^^^^^^^^^^^ not found in this scope
+
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/issue-72590-type-error-sized.rs:11:11
+   |
+LL |     test: Missing
+   |           ^^^^^^^ not found in this scope
+
+error[E0277]: the size for values of type `str` cannot be known at compilation time
+  --> $DIR/issue-72590-type-error-sized.rs:15:19
+   |
+LL |     async fn frob(self) {}
+   |                   ^^^^ doesn't have a size known at compile-time
+   |
+   = help: within `Foo`, the trait `std::marker::Sized` is not implemented for `str`
+   = note: to learn more, visit <https://doc.rust-lang.org/book/ch19-04-advanced-types.html#dynamically-sized-types-and-the-sized-trait>
+   = note: required because it appears within the type `Foo`
+   = note: all local variables must have a statically known size
+   = help: unsized locals are gated as an unstable feature
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0277, E0412.
+For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/async-await/issues/issue-62097.stderr b/src/test/ui/async-await/issues/issue-62097.stderr
index 94afccc06a9..af8fc2cd2ab 100644
--- a/src/test/ui/async-await/issues/issue-62097.stderr
+++ b/src/test/ui/async-await/issues/issue-62097.stderr
@@ -2,15 +2,12 @@ error: cannot infer an appropriate lifetime
   --> $DIR/issue-62097.rs:12:31
    |
 LL |     pub async fn run_dummy_fn(&self) {
-   |                               ^^^^^ ...but this borrow...
+   |                               ^^^^^
+   |                               |
+   |                               data with this lifetime...
+   |                               ...is captured here...
 LL |         foo(|| self.bar()).await;
-   |         --- this return type evaluates to the `'static` lifetime...
-   |
-note: ...can't outlive the lifetime `'_` as defined on the method body at 12:31
-  --> $DIR/issue-62097.rs:12:31
-   |
-LL |     pub async fn run_dummy_fn(&self) {
-   |                               ^
+   |         --- ...and required to be `'static` by this
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
index 999a5839ba6..2dac4a22ae7 100644
--- a/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
+++ b/src/test/ui/builtin-superkinds/builtin-superkinds-self-type.stderr
@@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/builtin-superkinds-self-type.rs:10:16
    |
 LL | impl <T: Sync> Foo for T { }
-   |       --       ^^^
+   |       --       ^^^ ...so that the type `T` will meet its required lifetime bounds
    |       |
    |       help: consider adding an explicit lifetime bound...: `T: 'static +`
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/builtin-superkinds-self-type.rs:10:16
-   |
-LL | impl <T: Sync> Foo for T { }
-   |                ^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.fixed b/src/test/ui/closures/closure-immutable-outer-variable.fixed
index 102f1f94a36..1b0feede34e 100644
--- a/src/test/ui/closures/closure-immutable-outer-variable.fixed
+++ b/src/test/ui/closures/closure-immutable-outer-variable.fixed
@@ -8,6 +8,6 @@ fn foo(mut f: Box<dyn FnMut()>) {
 
 fn main() {
     let mut y = true;
-    foo(Box::new(move || y = false) as Box<_>);
+    foo(Box::new(move || y = !y) as Box<_>);
     //~^ ERROR cannot assign to `y`, as it is not declared as mutable
 }
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.rs b/src/test/ui/closures/closure-immutable-outer-variable.rs
index 6eb43b372c9..50ec1c6148a 100644
--- a/src/test/ui/closures/closure-immutable-outer-variable.rs
+++ b/src/test/ui/closures/closure-immutable-outer-variable.rs
@@ -8,6 +8,6 @@ fn foo(mut f: Box<dyn FnMut()>) {
 
 fn main() {
     let y = true;
-    foo(Box::new(move || y = false) as Box<_>);
+    foo(Box::new(move || y = !y) as Box<_>);
     //~^ ERROR cannot assign to `y`, as it is not declared as mutable
 }
diff --git a/src/test/ui/closures/closure-immutable-outer-variable.stderr b/src/test/ui/closures/closure-immutable-outer-variable.stderr
index 7e60f3cd8ff..799097889cd 100644
--- a/src/test/ui/closures/closure-immutable-outer-variable.stderr
+++ b/src/test/ui/closures/closure-immutable-outer-variable.stderr
@@ -3,8 +3,8 @@ error[E0594]: cannot assign to `y`, as it is not declared as mutable
    |
 LL |     let y = true;
    |         - help: consider changing this to be mutable: `mut y`
-LL |     foo(Box::new(move || y = false) as Box<_>);
-   |                          ^^^^^^^^^ cannot assign
+LL |     foo(Box::new(move || y = !y) as Box<_>);
+   |                          ^^^^^^ cannot assign
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs b/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs
index 0d0765e971d..b4a083636b6 100644
--- a/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs
+++ b/src/test/ui/const-generics/array-impls/alloc-traits-impls-length-32.rs
@@ -18,6 +18,10 @@ pub fn yes_array_into_vec<T>() -> Vec<T> {
     [].into()
 }
 
+pub fn yes_array_into_box<T>() -> Box<[T]> {
+    [].into()
+}
+
 use std::collections::VecDeque;
 
 pub fn yes_vecdeque_partial_eq_array<A, B>() -> impl PartialEq<[B; 32]>
diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs
index 4b195f3a06e..48cf21d489a 100644
--- a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs
+++ b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.rs
@@ -12,6 +12,8 @@ pub fn no_box() {
     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
     //~^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::From<std::boxed::Box<[i32]>>` is not satisfied
     //~^^ ERROR the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
+    let boxed_slice = <Box<[i32]>>::from([0; 33]);
+    //~^ 15:42: 15:49: arrays only have std trait implementations for lengths 0..=32 [E0277]
 }
 
 pub fn no_rc() {
diff --git a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr
index ce1c9ae551e..5c01603ab88 100644
--- a/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr
+++ b/src/test/ui/const-generics/array-impls/alloc-types-no-impls-length-33.stderr
@@ -18,10 +18,23 @@ LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
              <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<&str>>
              <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::borrow::Cow<'a, str>>>
              <std::boxed::Box<(dyn std::error::Error + 'static)> as std::convert::From<std::string::String>>
-           and 21 others
+           and 22 others
    = note: required because of the requirements on the impl of `std::convert::Into<std::boxed::Box<[i32; 33]>>` for `std::boxed::Box<[i32]>`
    = note: required because of the requirements on the impl of `std::convert::TryFrom<std::boxed::Box<[i32]>>` for `std::boxed::Box<[i32; 33]>`
 
+error[E0277]: arrays only have std trait implementations for lengths 0..=32
+  --> $DIR/alloc-types-no-impls-length-33.rs:15:42
+   |
+LL |     let boxed_slice = <Box<[i32]>>::from([0; 33]);
+   |                                          ^^^^^^^
+   |                                          |
+   |                                          expected an implementor of trait `std::convert::From<[{integer}; 33]>`
+   |                                          help: consider borrowing here: `&[0; 33]`
+   |
+   = note: the trait bound `[i32; 33]: std::convert::From<[{integer}; 33]>` is not satisfied
+   = note: required because of the requirements on the impl of `std::convert::From<[i32; 33]>` for `std::boxed::Box<[i32]>`
+   = note: required by `std::convert::From::from`
+
 error[E0277]: the trait bound `std::boxed::Box<[i32; 33]>: std::convert::TryFrom<std::boxed::Box<[i32]>>` is not satisfied
   --> $DIR/alloc-types-no-impls-length-33.rs:12:23
    |
@@ -32,7 +45,7 @@ LL |     let boxed_array = <Box<[i32; 33]>>::try_from(boxed_slice);
              <std::boxed::Box<[T; N]> as std::convert::TryFrom<std::boxed::Box<[T]>>>
 
 error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::From<std::rc::Rc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:19:23
+  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
    |
 LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
@@ -47,7 +60,7 @@ LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
    = note: required because of the requirements on the impl of `std::convert::TryFrom<std::rc::Rc<[i32]>>` for `std::rc::Rc<[i32; 33]>`
 
 error[E0277]: the trait bound `std::rc::Rc<[i32; 33]>: std::convert::TryFrom<std::rc::Rc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:19:23
+  --> $DIR/alloc-types-no-impls-length-33.rs:21:23
    |
 LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::rc::Rc<[i32]>>` is not implemented for `std::rc::Rc<[i32; 33]>`
@@ -56,7 +69,7 @@ LL |     let boxed_array = <Rc<[i32; 33]>>::try_from(boxed_slice);
              <std::rc::Rc<[T; N]> as std::convert::TryFrom<std::rc::Rc<[T]>>>
 
 error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::From<std::sync::Arc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:26:23
+  --> $DIR/alloc-types-no-impls-length-33.rs:28:23
    |
 LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::From<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
@@ -71,7 +84,7 @@ LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
    = note: required because of the requirements on the impl of `std::convert::TryFrom<std::sync::Arc<[i32]>>` for `std::sync::Arc<[i32; 33]>`
 
 error[E0277]: the trait bound `std::sync::Arc<[i32; 33]>: std::convert::TryFrom<std::sync::Arc<[i32]>>` is not satisfied
-  --> $DIR/alloc-types-no-impls-length-33.rs:26:23
+  --> $DIR/alloc-types-no-impls-length-33.rs:28:23
    |
 LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `std::convert::TryFrom<std::sync::Arc<[i32]>>` is not implemented for `std::sync::Arc<[i32; 33]>`
@@ -79,6 +92,6 @@ LL |     let boxed_array = <Arc<[i32; 33]>>::try_from(boxed_slice);
    = help: the following implementations were found:
              <std::sync::Arc<[T; N]> as std::convert::TryFrom<std::sync::Arc<[T]>>>
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.rs b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
index 81985f9f625..65fc49c0b27 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.rs
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.rs
@@ -2,8 +2,7 @@
 #![feature(core_intrinsics)]
 #![allow(const_err)]
 
-// A test demonstrating that we prevent doing even trivial
-// pointer arithmetic or comparison during CTFE.
+// During CTFE, we prevent pointer comparison and pointer-to-int casts.
 
 static CMP: () = {
     let x = &0 as *const _;
@@ -19,11 +18,4 @@ static INT_PTR_ARITH: () = unsafe {
     //~| NOTE pointer-to-integer cast
 };
 
-static PTR_ARITH: () = unsafe {
-    let x = &0 as *const _;
-    let _v = core::intrinsics::offset(x, 0);
-    //~^ ERROR could not evaluate static initializer
-    //~| NOTE calling intrinsic `offset`
-};
-
 fn main() {}
diff --git a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
index 5bd534a16b8..805ba9c6b03 100644
--- a/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
+++ b/src/test/ui/consts/miri_unleashed/ptr_arith.stderr
@@ -1,39 +1,28 @@
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:10:14
+  --> $DIR/ptr_arith.rs:9:14
    |
 LL |     let _v = x == x;
    |              ^^^^^^ "pointer arithmetic or comparison" needs an rfc before being allowed inside constants
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:17:14
+  --> $DIR/ptr_arith.rs:16:14
    |
 LL |     let _v = x + 0;
    |              ^^^^^ "pointer-to-integer cast" needs an rfc before being allowed inside constants
 
-error[E0080]: could not evaluate static initializer
-  --> $DIR/ptr_arith.rs:24:14
-   |
-LL |     let _v = core::intrinsics::offset(x, 0);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ "calling intrinsic `offset`" needs an rfc before being allowed inside constants
-
 warning: skipping const checks
    |
 help: skipping check for `const_compare_raw_pointers` feature
-  --> $DIR/ptr_arith.rs:10:14
+  --> $DIR/ptr_arith.rs:9:14
    |
 LL |     let _v = x == x;
    |              ^^^^^^
 help: skipping check that does not even have a feature gate
-  --> $DIR/ptr_arith.rs:16:20
+  --> $DIR/ptr_arith.rs:15:20
    |
 LL |     let x: usize = std::mem::transmute(&0);
    |                    ^^^^^^^^^^^^^^^^^^^^^^^
-help: skipping check that does not even have a feature gate
-  --> $DIR/ptr_arith.rs:24:14
-   |
-LL |     let _v = core::intrinsics::offset(x, 0);
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 3 previous errors; 1 warning emitted
+error: aborting due to 2 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/src/test/ui/consts/offset.rs b/src/test/ui/consts/offset.rs
new file mode 100644
index 00000000000..f64242d568e
--- /dev/null
+++ b/src/test/ui/consts/offset.rs
@@ -0,0 +1,115 @@
+// run-pass
+#![feature(const_ptr_offset)]
+#![feature(const_ptr_offset_from)]
+#![feature(ptr_offset_from)]
+use std::ptr;
+
+#[repr(C)]
+struct Struct {
+    a: u32,
+    b: u32,
+    c: u32,
+}
+static S: Struct = Struct { a: 0, b: 0, c: 0 };
+
+// For these tests we use offset_from to check that two pointers are equal.
+// Rust doesn't currently support comparing pointers in const fn.
+
+static OFFSET_NO_CHANGE: bool = unsafe {
+    let p1 = &S.b as *const u32;
+    let p2 = p1.offset(2).offset(-2);
+    p1.offset_from(p2) == 0
+};
+static OFFSET_MIDDLE: bool = unsafe {
+    let p1 = (&S.a as *const u32).offset(1);
+    let p2 = (&S.c as *const u32).offset(-1);
+    p1.offset_from(p2) == 0
+};
+// Pointing to the end of the allocation is OK
+static OFFSET_END: bool = unsafe {
+    let p1 = (&S.a as *const u32).offset(3);
+    let p2 = (&S.c as *const u32).offset(1);
+    p1.offset_from(p2) == 0
+};
+// Casting though a differently sized type is OK
+static OFFSET_U8_PTR: bool = unsafe {
+    let p1 = (&S.a as *const u32 as *const u8).offset(5);
+    let p2 = (&S.c as *const u32 as *const u8).offset(-3);
+    p1.offset_from(p2) == 0
+};
+// Any offset with a ZST does nothing
+const OFFSET_ZST: bool = unsafe {
+    let pz = &() as *const ();
+    // offset_from can't work with ZSTs, so cast to u8 ptr
+    let p1 = pz.offset(5) as *const u8;
+    let p2 = pz.offset(isize::MIN) as *const u8;
+    p1.offset_from(p2) == 0
+};
+const OFFSET_ZERO: bool = unsafe {
+    let p = [0u8; 0].as_ptr();
+    p.offset(0).offset_from(p) == 0
+};
+const OFFSET_ONE: bool = unsafe {
+    let p = &42u32 as *const u32;
+    p.offset(1).offset_from(p) == 1
+};
+const OFFSET_DANGLING: bool = unsafe {
+    let p = ptr::NonNull::<u8>::dangling().as_ptr();
+    p.offset(0).offset_from(p) == 0
+};
+const OFFSET_UNALIGNED: bool = unsafe {
+    let arr = [0u8; 32];
+    let p1 = arr.as_ptr();
+    let p2 = (p1.offset(2) as *const u32).offset(1);
+    (p2 as *const u8).offset_from(p1) == 6
+};
+
+const WRAP_OFFSET_NO_CHANGE: bool = unsafe {
+    let p1 = &42u32 as *const u32;
+    let p2 = p1.wrapping_offset(1000).wrapping_offset(-1000);
+    let p3 = p1.wrapping_offset(-1000).wrapping_offset(1000);
+    (p1.offset_from(p2) == 0) & (p1.offset_from(p3) == 0)
+};
+const WRAP_ADDRESS_SPACE: bool = unsafe {
+    let p1 = &42u8 as *const u8;
+    let p2 = p1.wrapping_offset(isize::MIN).wrapping_offset(isize::MIN);
+    p1.offset_from(p2) == 0
+};
+// Wrap on the count*size_of::<T>() calculation.
+const WRAP_SIZE_OF: bool = unsafe {
+    // Make sure that if p1 moves backwards, we are still in range
+    let arr = [0u32; 2];
+    let p = &arr[1] as *const u32;
+    // With wrapping arithmetic, isize::MAX * 4 == -4
+    let wrapped = p.wrapping_offset(isize::MAX);
+    let backward = p.wrapping_offset(-1);
+    wrapped.offset_from(backward) == 0
+};
+const WRAP_INTEGER_POINTER: bool = unsafe {
+    let p1 = (0x42 as *const u32).wrapping_offset(4);
+    let p2 = 0x52 as *const u32;
+    p1.offset_from(p2) == 0
+};
+const WRAP_NULL: bool = unsafe {
+    let p1 = ptr::null::<u32>().wrapping_offset(1);
+    let p2 = 0x4 as *const u32;
+    p1.offset_from(p2) == 0
+};
+
+fn main() {
+    assert!(OFFSET_NO_CHANGE);
+    assert!(OFFSET_MIDDLE);
+    assert!(OFFSET_END);
+    assert!(OFFSET_U8_PTR);
+    assert!(OFFSET_ZST);
+    assert!(OFFSET_ZERO);
+    assert!(OFFSET_ONE);
+    assert!(OFFSET_DANGLING);
+    assert!(OFFSET_UNALIGNED);
+
+    assert!(WRAP_OFFSET_NO_CHANGE);
+    assert!(WRAP_ADDRESS_SPACE);
+    assert!(WRAP_SIZE_OF);
+    assert!(WRAP_INTEGER_POINTER);
+    assert!(WRAP_NULL);
+}
diff --git a/src/test/ui/consts/offset_ub.rs b/src/test/ui/consts/offset_ub.rs
new file mode 100644
index 00000000000..4f943ed9ad1
--- /dev/null
+++ b/src/test/ui/consts/offset_ub.rs
@@ -0,0 +1,25 @@
+// ignore-tidy-linelength
+#![feature(const_ptr_offset)]
+use std::ptr;
+
+// normalize-stderr-test "alloc\d+" -> "allocN"
+
+pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) }; //~NOTE
+pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) }; //~NOTE
+pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) }; //~NOTE
+
+pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) }; //~NOTE
+pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) }; //~NOTE
+pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) }; //~NOTE
+pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) }; //~NOTE
+
+pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) }; //~NOTE
+pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) }; //~NOTE
+
+// Right now, a zero offset from null is UB
+pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) }; //~NOTE
+
+// Make sure that we don't panic when computing abs(offset*size_of::<T>())
+pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) }; //~NOTE
+
+fn main() {}
diff --git a/src/test/ui/consts/offset_ub.stderr b/src/test/ui/consts/offset_ub.stderr
new file mode 100644
index 00000000000..0ab81cc0c5b
--- /dev/null
+++ b/src/test/ui/consts/offset_ub.stderr
@@ -0,0 +1,169 @@
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         overflowing in-bounds pointer arithmetic
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `BEFORE_START` at $DIR/offset_ub.rs:7:46
+   | 
+  ::: $DIR/offset_ub.rs:7:1
+   |
+LL | pub const BEFORE_START: *const u8 = unsafe { (&0u8 as *const u8).offset(-1) };
+   | ------------------------------------------------------------------------------
+   |
+   = note: `#[deny(const_err)]` on by default
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         inbounds test failed: pointer must be in-bounds at offset 2, but is outside bounds of allocN which has size 1
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `AFTER_END` at $DIR/offset_ub.rs:8:43
+   | 
+  ::: $DIR/offset_ub.rs:8:1
+   |
+LL | pub const AFTER_END: *const u8 = unsafe { (&0u8 as *const u8).offset(2) };
+   | --------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         inbounds test failed: pointer must be in-bounds at offset 101, but is outside bounds of allocN which has size 100
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `AFTER_ARRAY` at $DIR/offset_ub.rs:9:45
+   | 
+  ::: $DIR/offset_ub.rs:9:1
+   |
+LL | pub const AFTER_ARRAY: *const u8 = unsafe { [0u8; 100].as_ptr().offset(101) };
+   | ------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         overflowing in-bounds pointer arithmetic
+   |         inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `OVERFLOW` at $DIR/offset_ub.rs:11:43
+   | 
+  ::: $DIR/offset_ub.rs:11:1
+   |
+LL | pub const OVERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MAX) };
+   | ----------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         overflowing in-bounds pointer arithmetic
+   |         inside `std::ptr::const_ptr::<impl *const u16>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `UNDERFLOW` at $DIR/offset_ub.rs:12:44
+   | 
+  ::: $DIR/offset_ub.rs:12:1
+   |
+LL | pub const UNDERFLOW: *const u16 = unsafe { [0u16; 1].as_ptr().offset(isize::MIN) };
+   | -----------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         overflowing in-bounds pointer arithmetic
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `OVERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:13:56
+   | 
+  ::: $DIR/offset_ub.rs:13:1
+   |
+LL | pub const OVERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (usize::MAX as *const u8).offset(2) };
+   | ---------------------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         overflowing in-bounds pointer arithmetic
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `UNDERFLOW_ADDRESS_SPACE` at $DIR/offset_ub.rs:14:57
+   | 
+  ::: $DIR/offset_ub.rs:14:1
+   |
+LL | pub const UNDERFLOW_ADDRESS_SPACE: *const u8 = unsafe { (1 as *const u8).offset(-2) };
+   | --------------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         inbounds test failed: pointer must be in-bounds at offset 1, but is outside bounds of allocN which has size 0
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `ZERO_SIZED_ALLOC` at $DIR/offset_ub.rs:16:50
+   | 
+  ::: $DIR/offset_ub.rs:16:1
+   |
+LL | pub const ZERO_SIZED_ALLOC: *const u8 = unsafe { [0u8; 0].as_ptr().offset(1) };
+   | -------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/mut_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count) as *mut T
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unable to turn bytes into a pointer
+   |         inside `std::ptr::mut_ptr::<impl *mut u8>::offset` at $SRC_DIR/libcore/ptr/mut_ptr.rs:LL:COL
+   |         inside `DANGLING` at $DIR/offset_ub.rs:17:42
+   | 
+  ::: $DIR/offset_ub.rs:17:1
+   |
+LL | pub const DANGLING: *const u8 = unsafe { ptr::NonNull::<u8>::dangling().as_ptr().offset(4) };
+   | ---------------------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         inbounds test failed: 0x0 is not a valid pointer
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `NULL_OFFSET_ZERO` at $DIR/offset_ub.rs:20:50
+   | 
+  ::: $DIR/offset_ub.rs:20:1
+   |
+LL | pub const NULL_OFFSET_ZERO: *const u8 = unsafe { ptr::null::<u8>().offset(0) };
+   | -------------------------------------------------------------------------------
+
+error: any use of this value will cause an error
+  --> $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |
+LL |         intrinsics::offset(self, count)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |         |
+   |         unable to turn bytes into a pointer
+   |         inside `std::ptr::const_ptr::<impl *const u8>::offset` at $SRC_DIR/libcore/ptr/const_ptr.rs:LL:COL
+   |         inside `UNDERFLOW_ABS` at $DIR/offset_ub.rs:23:47
+   | 
+  ::: $DIR/offset_ub.rs:23:1
+   |
+LL | pub const UNDERFLOW_ABS: *const u8 = unsafe { (usize::MAX as *const u8).offset(isize::MIN) };
+   | ---------------------------------------------------------------------------------------------
+
+error: aborting due to 11 previous errors
+
diff --git a/src/test/ui/did_you_mean/recursion_limit.stderr b/src/test/ui/did_you_mean/recursion_limit.stderr
index 45cb054b80c..c9a6d42b5cc 100644
--- a/src/test/ui/did_you_mean/recursion_limit.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit.stderr
@@ -1,4 +1,4 @@
-error[E0275]: overflow evaluating the requirement `J: std::marker::Send`
+error[E0275]: overflow evaluating the requirement `K: std::marker::Send`
   --> $DIR/recursion_limit.rs:34:5
    |
 LL | fn is_send<T:Send>() { }
@@ -8,6 +8,7 @@ LL |     is_send::<A>();
    |     ^^^^^^^^^^^^
    |
    = help: consider adding a `#![recursion_limit="20"]` attribute to your crate (`recursion_limit`)
+   = note: required because it appears within the type `J`
    = note: required because it appears within the type `I`
    = note: required because it appears within the type `H`
    = note: required because it appears within the type `G`
diff --git a/src/test/ui/did_you_mean/recursion_limit_deref.stderr b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
index e8d11530b08..8339cc291cf 100644
--- a/src/test/ui/did_you_mean/recursion_limit_deref.stderr
+++ b/src/test/ui/did_you_mean/recursion_limit_deref.stderr
@@ -1,4 +1,4 @@
-error[E0055]: reached the recursion limit while auto-dereferencing `I`
+error[E0055]: reached the recursion limit while auto-dereferencing `J`
   --> $DIR/recursion_limit_deref.rs:50:22
    |
 LL |     let x: &Bottom = &t;
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
index dd0c438f421..5df69e4649d 100644
--- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
@@ -4,7 +4,7 @@ error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
 LL |     let ft =
    |         ^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
   --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9
@@ -12,7 +12,7 @@ error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
 LL |         FingerTree::Single(1);
    |         ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
index 769d5aed664..d34097d4010 100644
--- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_2.stderr
@@ -4,7 +4,7 @@ error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
 LL |     let ft =
    |         ^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
   --> $DIR/dropck_no_diverge_on_nonregular_2.rs:24:9
@@ -12,7 +12,7 @@ error[E0320]: overflow while adding drop-check rules for FingerTree<i32>
 LL |         FingerTree::Single(1);
    |         ^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
index de8afdcc7cd..1c810df2423 100644
--- a/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
+++ b/src/test/ui/dropck/dropck_no_diverge_on_nonregular_3.stderr
@@ -4,7 +4,7 @@ error[E0320]: overflow while adding drop-check rules for std::option::Option<Wra
 LL |     let w =
    |         ^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error[E0320]: overflow while adding drop-check rules for std::option::Option<Wrapper<u32>>
   --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:9
@@ -12,7 +12,7 @@ error[E0320]: overflow while adding drop-check rules for std::option::Option<Wra
 LL |         Some(Wrapper::Simple::<u32>);
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
   --> $DIR/dropck_no_diverge_on_nonregular_3.rs:33:14
@@ -20,7 +20,7 @@ error[E0320]: overflow while adding drop-check rules for Wrapper<u32>
 LL |         Some(Wrapper::Simple::<u32>);
    |              ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
+   = note: overflowed on FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<u32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/error-codes/E0040.stderr b/src/test/ui/error-codes/E0040.stderr
index 96645590281..69cf28b2970 100644
--- a/src/test/ui/error-codes/E0040.stderr
+++ b/src/test/ui/error-codes/E0040.stderr
@@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method
   --> $DIR/E0040.rs:13:7
    |
 LL |     x.drop();
-   |       ^^^^ explicit destructor calls not allowed
+   |       ^^^^
+   |       |
+   |       explicit destructor calls not allowed
+   |       help: consider using `drop` function: `drop(x)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0055.rs b/src/test/ui/error-codes/E0055.rs
index b525575d98d..fd5804bbc2a 100644
--- a/src/test/ui/error-codes/E0055.rs
+++ b/src/test/ui/error-codes/E0055.rs
@@ -1,4 +1,4 @@
-#![recursion_limit="5"]
+#![recursion_limit="4"]
 struct Foo;
 
 impl Foo {
diff --git a/src/test/ui/error-codes/E0055.stderr b/src/test/ui/error-codes/E0055.stderr
index 01411e585ab..1b8c5760e65 100644
--- a/src/test/ui/error-codes/E0055.stderr
+++ b/src/test/ui/error-codes/E0055.stderr
@@ -4,7 +4,7 @@ error[E0055]: reached the recursion limit while auto-dereferencing `Foo`
 LL |     ref_foo.foo();
    |             ^^^ deref recursion limit reached
    |
-   = help: consider adding a `#![recursion_limit="10"]` attribute to your crate (`E0055`)
+   = help: consider adding a `#![recursion_limit="8"]` attribute to your crate (`E0055`)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0275.stderr b/src/test/ui/error-codes/E0275.stderr
index a9fd0564ff5..2692fe6945e 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -1,4 +1,4 @@
-error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/E0275.rs:5:33
    |
 LL | trait Foo {}
@@ -8,6 +8,7 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`E0275`)
+   = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/error-codes/E0490.stderr b/src/test/ui/error-codes/E0490.stderr
index 03fce213605..9ba5bc330ea 100644
--- a/src/test/ui/error-codes/E0490.stderr
+++ b/src/test/ui/error-codes/E0490.stderr
@@ -58,8 +58,8 @@ note: ...so that the expression is assignable
    |
 LL |     let x: &'a _ = &y;
    |                    ^^
-   = note: expected  `&'a &()`
-              found  `&'a &'b ()`
+   = note: expected `&'a &()`
+              found `&'a &'b ()`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 1:6...
   --> $DIR/E0490.rs:1:6
    |
diff --git a/src/test/ui/explicit/explicit-call-to-dtor.stderr b/src/test/ui/explicit/explicit-call-to-dtor.stderr
index cbbe967179e..5ebe4ee4b90 100644
--- a/src/test/ui/explicit/explicit-call-to-dtor.stderr
+++ b/src/test/ui/explicit/explicit-call-to-dtor.stderr
@@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method
   --> $DIR/explicit-call-to-dtor.rs:13:7
    |
 LL |     x.drop();
-   |       ^^^^ explicit destructor calls not allowed
+   |       ^^^^
+   |       |
+   |       explicit destructor calls not allowed
+   |       help: consider using `drop` function: `drop(x)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr
index 0b302e30b64..cd3fb3119a5 100644
--- a/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr
+++ b/src/test/ui/explicit/explicit-call-to-supertrait-dtor.stderr
@@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method
   --> $DIR/explicit-call-to-supertrait-dtor.rs:17:14
    |
 LL |         self.drop();
-   |              ^^^^ explicit destructor calls not allowed
+   |              ^^^^
+   |              |
+   |              explicit destructor calls not allowed
+   |              help: consider using `drop` function: `drop(self)`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
index fbc4e8abc42..2beeba8184a 100644
--- a/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
+++ b/src/test/ui/feature-gates/feature-gate-infer_static_outlives_requirements.stderr
@@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough
 LL | struct Foo<U> {
    |            - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     bar: Bar<U>
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `U` will meet its required lifetime bounds
-  --> $DIR/feature-gate-infer_static_outlives_requirements.rs:5:5
-   |
-LL |     bar: Bar<U>
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs
new file mode 100644
index 00000000000..61e512a12a1
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.rs
@@ -0,0 +1,6 @@
+#![deny(unsafe_op_in_unsafe_fn)]
+//~^ ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
+//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
+//~| ERROR the `unsafe_op_in_unsafe_fn` lint is unstable
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr
new file mode 100644
index 00000000000..c5cad4a98d9
--- /dev/null
+++ b/src/test/ui/feature-gates/feature-gate-unsafe_block_in_unsafe_fn.stderr
@@ -0,0 +1,30 @@
+error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
+  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
+   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
+
+error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
+  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
+   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
+
+error[E0658]: the `unsafe_op_in_unsafe_fn` lint is unstable
+  --> $DIR/feature-gate-unsafe_block_in_unsafe_fn.rs:1:1
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #71668 <https://github.com/rust-lang/rust/issues/71668> for more information
+   = help: add `#![feature(unsafe_block_in_unsafe_fn)]` to the crate attributes to enable
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index d5560c81337..e06977ebbe3 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -5,11 +5,7 @@ LL |     type A<'a> where Self: 'static = (&'a ());
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `T: 'static`...
-note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
-  --> $DIR/impl_bounds.rs:15:5
-   |
-LL |     type A<'a> where Self: 'static = (&'a ());
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...so that the type `Fooy<T>` will meet its required lifetime bounds
 
 error[E0478]: lifetime bound not satisfied
   --> $DIR/impl_bounds.rs:17:5
diff --git a/src/test/ui/illegal-ufcs-drop.stderr b/src/test/ui/illegal-ufcs-drop.stderr
index d35d376962c..57c99739afd 100644
--- a/src/test/ui/illegal-ufcs-drop.stderr
+++ b/src/test/ui/illegal-ufcs-drop.stderr
@@ -2,7 +2,10 @@ error[E0040]: explicit use of destructor method
   --> $DIR/illegal-ufcs-drop.rs:8:5
    |
 LL |     Drop::drop(&mut Foo)
-   |     ^^^^^^^^^^ explicit destructor calls not allowed
+   |     ^^^^^^^^^^
+   |     |
+   |     explicit destructor calls not allowed
+   |     help: consider using `drop` function: `drop`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
index 3300293bb36..268008c2111 100644
--- a/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
+++ b/src/test/ui/impl-header-lifetime-elision/dyn-trait.stderr
@@ -14,16 +14,16 @@ note: ...so that the expression is assignable
    |
 LL |     static_val(x);
    |                ^
-   = note: expected  `std::boxed::Box<dyn std::fmt::Debug>`
-              found  `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
+   = note: expected `std::boxed::Box<dyn std::fmt::Debug>`
+              found `std::boxed::Box<(dyn std::fmt::Debug + 'a)>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the types are compatible
   --> $DIR/dyn-trait.rs:20:5
    |
 LL |     static_val(x);
    |     ^^^^^^^^^^
-   = note: expected  `StaticTrait`
-              found  `StaticTrait`
+   = note: expected `StaticTrait`
+              found `StaticTrait`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/impl-trait/issue-56445.rs b/src/test/ui/impl-trait/issue-56445.rs
new file mode 100644
index 00000000000..a34d7bae3a6
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-56445.rs
@@ -0,0 +1,26 @@
+// Regression test for https://github.com/rust-lang/rust/issues/56445#issuecomment-629426939
+// check-pass
+
+#![crate_type = "lib"]
+
+use std::marker::PhantomData;
+
+pub struct S<'a>
+{
+    pub m1: PhantomData<&'a u8>,
+    pub m2: [u8; S::size()],
+}
+
+impl<'a> S<'a>
+{
+    pub const fn size() -> usize { 1 }
+
+    pub fn new() -> Self
+    {
+        Self
+        {
+            m1: PhantomData,
+            m2: [0; Self::size()],
+        }
+    }
+}
diff --git a/src/test/ui/impl-trait/issue-68532.rs b/src/test/ui/impl-trait/issue-68532.rs
new file mode 100644
index 00000000000..01a7af0aee4
--- /dev/null
+++ b/src/test/ui/impl-trait/issue-68532.rs
@@ -0,0 +1,13 @@
+// check-pass
+
+pub struct A<'a>(&'a ());
+
+impl<'a> A<'a> {
+    const N: usize = 68;
+
+    pub fn foo(&self) {
+        let _b = [0; Self::N];
+    }
+}
+
+fn main() {}
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 cffa5ee8f14..d7dae6a08a7 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
@@ -2,55 +2,43 @@ error: cannot infer an appropriate lifetime
   --> $DIR/must_outlive_least_region_or_bound.rs:3:35
    |
 LL | fn elided(x: &i32) -> impl Copy { x }
-   |                       ---------   ^ ...but this borrow...
-   |                       |
-   |                       this return type evaluates to the `'static` lifetime...
+   |              ----     ---------   ^ ...and is captured here
+   |              |        |
+   |              |        ...is required to be `'static` by this...
+   |              data with this lifetime...
    |
-note: ...can't outlive the anonymous lifetime #1 defined on the function body at 3:1
-  --> $DIR/must_outlive_least_region_or_bound.rs:3:1
-   |
-LL | fn elided(x: &i32) -> impl Copy { x }
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the function body at 3:1
+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
    |
 LL | fn elided(x: &i32) -> impl Copy + '_ { x }
-   |                       ^^^^^^^^^^^^^^
+   |                                 ^^^^
 
 error: 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 }
-   |                                ---------   ^ ...but this borrow...
-   |                                |
-   |                                this return type evaluates to the `'static` lifetime...
+   |                    -------     ---------   ^ ...and is captured here
+   |                    |           |
+   |                    |           ...is required to be `'static` by this...
+   |                    data with this lifetime...
    |
-note: ...can't outlive the lifetime `'a` as defined on the function body at 6:13
-  --> $DIR/must_outlive_least_region_or_bound.rs:6:13
-   |
-LL | fn explicit<'a>(x: &'a i32) -> impl Copy { x }
-   |             ^^
-help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 6:13
+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
    |
 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
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |                                  --------------------------------   ^ ...but this borrow...
-   |                                  |
-   |                                  this return type evaluates to the `'static` lifetime...
-   |
-note: ...can't outlive the lifetime `'a` as defined on the function body at 12:15
-  --> $DIR/must_outlive_least_region_or_bound.rs:12:15
+   |                      -------     --------------------------------   ^ ...and is captured here
+   |                      |           |
+   |                      |           ...is required to be `'static` by this...
+   |                      data with this lifetime...
    |
-LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static { x }
-   |               ^^
-help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the function body at 12:15
+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
    |
 LL | fn with_bound<'a>(x: &'a i32) -> impl LifetimeTrait<'a> + 'static + 'a { x }
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                                   ^^^^
 
 error[E0623]: lifetime mismatch
   --> $DIR/must_outlive_least_region_or_bound.rs:17:61
@@ -65,15 +53,9 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/must_outlive_least_region_or_bound.rs:22: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 +`
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/must_outlive_least_region_or_bound.rs:22:51
-   |
-LL | fn ty_param_wont_outlive_static<T:Debug>(x: T) -> impl Debug + 'static {
-   |                                                   ^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 5 previous errors
 
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 e550be19174..1c3a5979ee5 100644
--- a/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
+++ b/src/test/ui/impl-trait/static-return-lifetime-infered.stderr
@@ -2,43 +2,35 @@ error: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:7:16
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-   |                                   ----------------------- this return type evaluates to the `'static` lifetime...
+   |                         -----     ----------------------- ...is required to be `'static` by this...
+   |                         |
+   |                         data with this lifetime...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...but this borrow...
+   |         ...and is captured here
    |
-note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5
-  --> $DIR/static-return-lifetime-infered.rs:6:5
-   |
-LL | /     fn iter_values_anon(&self) -> impl Iterator<Item=u32> {
-LL | |         self.x.iter().map(|a| a.0)
-LL | |     }
-   | |_____^
-help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
+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
    |
 LL |     fn iter_values_anon(&self) -> impl Iterator<Item=u32> + '_ {
-   |                                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                           ^^^^
 
 error: cannot infer an appropriate lifetime
   --> $DIR/static-return-lifetime-infered.rs:11:16
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                                     ----------------------- this return type evaluates to the `'static` lifetime...
+   |                        --------     ----------------------- ...is required to be `'static` by this...
+   |                        |
+   |                        data with this lifetime...
 LL |         self.x.iter().map(|a| a.0)
    |         ------ ^^^^
    |         |
-   |         ...but this borrow...
-   |
-note: ...can't outlive the lifetime `'a` as defined on the method body at 10:20
-  --> $DIR/static-return-lifetime-infered.rs:10:20
+   |         ...and is captured here
    |
-LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> {
-   |                    ^^
-help: you can add a bound to the return type to make it last less than `'static` and match the lifetime `'a` as defined on the method body at 10:20
+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
    |
 LL |     fn iter_values<'a>(&'a self) -> impl Iterator<Item=u32> + 'a {
-   |                                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                                                             ^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/impl-trait/type_parameters_captured.stderr b/src/test/ui/impl-trait/type_parameters_captured.stderr
index 34f0f7f1d73..40e50b9922f 100644
--- a/src/test/ui/impl-trait/type_parameters_captured.stderr
+++ b/src/test/ui/impl-trait/type_parameters_captured.stderr
@@ -2,15 +2,9 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/type_parameters_captured.rs:7:20
    |
 LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |        -           ^^^^^^^^^^^^^^^^^^
+   |        -           ^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
    |        |
    |        help: consider adding an explicit lifetime bound...: `T: 'static`
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/type_parameters_captured.rs:7:20
-   |
-LL | fn foo<T>(x: T) -> impl Any + 'static {
-   |                    ^^^^^^^^^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
index c1c4ec9ed7b..b93d98ca39f 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl-2.stderr
@@ -2,15 +2,17 @@ error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/mismatched_trait_impl-2.rs:8:5
    |
 LL |     fn deref(&self) -> &dyn Trait {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&Struct) -> &dyn Trait
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Struct) -> &dyn Trait`
    | 
   ::: $SRC_DIR/libcore/ops/deref.rs:LL:COL
    |
 LL |     fn deref(&self) -> &Self::Target;
-   |     --------------------------------- expected fn(&Struct) -> &(dyn Trait + 'static)
+   |     --------------------------------- expected `fn(&Struct) -> &(dyn Trait + 'static)`
    |
    = note: expected `fn(&Struct) -> &(dyn Trait + 'static)`
               found `fn(&Struct) -> &dyn Trait`
+   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
index c245d78ae82..149c2aeb958 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.nll.stderr
@@ -2,13 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/mismatched_trait_impl.rs:9:5
    |
 LL |     fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
-   |     ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
+   |     ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32`
 ...
 LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32`
    |
    = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
               found `fn(&i32, &u32, &u32) -> &u32`
+   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
index 15891c9e7a6..9a0bd827850 100644
--- a/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
+++ b/src/test/ui/in-band-lifetimes/mismatched_trait_impl.stderr
@@ -2,13 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/mismatched_trait_impl.rs:9:5
    |
 LL |     fn foo(&self, x: &'a u32, y: &u32) -> &'a u32;
-   |     ---------------------------------------------- expected fn(&i32, &'a u32, &u32) -> &'a u32
+   |     ---------------------------------------------- expected `fn(&i32, &'a u32, &u32) -> &'a u32`
 ...
 LL |     fn foo(&self, x: &u32, y: &'a u32) -> &'a u32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &u32, &u32) -> &u32
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &u32, &u32) -> &u32`
    |
    = note: expected `fn(&i32, &'a u32, &u32) -> &'a u32`
               found `fn(&i32, &u32, &u32) -> &u32`
+   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
 error[E0623]: lifetime mismatch
   --> $DIR/mismatched_trait_impl.rs:10:9
diff --git a/src/test/ui/issues/issue-11958.rs b/src/test/ui/issues/issue-11958.rs
index 8fe8a8c6061..a7af01e25b4 100644
--- a/src/test/ui/issues/issue-11958.rs
+++ b/src/test/ui/issues/issue-11958.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![forbid(warnings)]
 
 // We shouldn't need to rebind a moved upvar as mut if it's already
 // marked as mut
@@ -7,4 +6,6 @@
 pub fn main() {
     let mut x = 1;
     let _thunk = Box::new(move|| { x = 2; });
+    //~^ WARN value assigned to `x` is never read
+    //~| WARN unused variable: `x`
 }
diff --git a/src/test/ui/issues/issue-11958.stderr b/src/test/ui/issues/issue-11958.stderr
new file mode 100644
index 00000000000..25de6ff4c11
--- /dev/null
+++ b/src/test/ui/issues/issue-11958.stderr
@@ -0,0 +1,20 @@
+warning: value assigned to `x` is never read
+  --> $DIR/issue-11958.rs:8:36
+   |
+LL |     let _thunk = Box::new(move|| { x = 2; });
+   |                                    ^
+   |
+   = note: `#[warn(unused_assignments)]` on by default
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `x`
+  --> $DIR/issue-11958.rs:8:36
+   |
+LL |     let _thunk = Box::new(move|| { x = 2; });
+   |                                    ^
+   |
+   = note: `#[warn(unused_variables)]` on by default
+   = help: did you mean to capture by reference instead?
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/issues/issue-16683.stderr b/src/test/ui/issues/issue-16683.stderr
index 99700f2084e..4f658330758 100644
--- a/src/test/ui/issues/issue-16683.stderr
+++ b/src/test/ui/issues/issue-16683.stderr
@@ -26,8 +26,8 @@ note: ...so that the types are compatible
    |
 LL |         self.a();
    |              ^
-   = note: expected  `&'a Self`
-              found  `&Self`
+   = note: expected `&'a Self`
+              found `&Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-16922.nll.stderr b/src/test/ui/issues/issue-16922.nll.stderr
new file mode 100644
index 00000000000..7f4f5b22eb3
--- /dev/null
+++ b/src/test/ui/issues/issue-16922.nll.stderr
@@ -0,0 +1,10 @@
+error: lifetime may not live long enough
+  --> $DIR/issue-16922.rs:4:5
+   |
+LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
+   |                       - let's call the lifetime of this reference `'1`
+LL |     Box::new(value) as Box<dyn Any>
+   |     ^^^^^^^^^^^^^^^ cast requires that `'1` must outlive `'static`
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-16922.rs b/src/test/ui/issues/issue-16922.rs
index 10a5cccbcee..827163ef83c 100644
--- a/src/test/ui/issues/issue-16922.rs
+++ b/src/test/ui/issues/issue-16922.rs
@@ -2,7 +2,7 @@ use std::any::Any;
 
 fn foo<T: Any>(value: &T) -> Box<dyn Any> {
     Box::new(value) as Box<dyn Any>
-    //~^ ERROR explicit lifetime required in the type of `value` [E0621]
+    //~^ ERROR cannot infer an appropriate lifetime
 }
 
 fn main() {
diff --git a/src/test/ui/issues/issue-16922.stderr b/src/test/ui/issues/issue-16922.stderr
index 4e3d3ecb9c0..02d33aae023 100644
--- a/src/test/ui/issues/issue-16922.stderr
+++ b/src/test/ui/issues/issue-16922.stderr
@@ -1,11 +1,18 @@
-error[E0621]: explicit lifetime required in the type of `value`
-  --> $DIR/issue-16922.rs:4:5
+error: cannot infer an appropriate lifetime
+  --> $DIR/issue-16922.rs:4:14
    |
 LL | fn foo<T: Any>(value: &T) -> Box<dyn Any> {
-   |                       -- help: add explicit lifetime `'static` to the type of `value`: `&'static T`
+   |                       -- data with this lifetime...
 LL |     Box::new(value) as Box<dyn Any>
-   |     ^^^^^^^^^^^^^^^ lifetime `'static` required
+   |     ---------^^^^^-
+   |     |        |
+   |     |        ...and is captured here
+   |     ...is required to be `'static` by this...
+   |
+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
+   |
+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 E0621`.
diff --git a/src/test/ui/issues/issue-17758.stderr b/src/test/ui/issues/issue-17758.stderr
index adfc3f50858..31788cfa61c 100644
--- a/src/test/ui/issues/issue-17758.stderr
+++ b/src/test/ui/issues/issue-17758.stderr
@@ -27,8 +27,8 @@ note: ...so that the types are compatible
    |
 LL |         self.foo();
    |              ^^^
-   = note: expected  `&'a Self`
-              found  `&Self`
+   = note: expected `&'a Self`
+              found `&Self`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-18400.stderr b/src/test/ui/issues/issue-18400.stderr
index 57067ad5175..ed9137ce396 100644
--- a/src/test/ui/issues/issue-18400.stderr
+++ b/src/test/ui/issues/issue-18400.stderr
@@ -133,6 +133,7 @@ LL |     0.contains(bits);
    = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
    = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
    = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index ad33eef07cb..a3eb4fec70f 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -6,7 +6,7 @@ LL | struct NoData<T>;
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `std::marker::PhantomData`
 
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:8:36
    |
 LL | trait Foo {
@@ -16,6 +16,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
@@ -144,7 +145,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<T>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
 
-error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
+error[E0275]: overflow evaluating the requirement `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Foo`
   --> $DIR/issue-20413.rs:8:36
    |
 LL | trait Foo {
@@ -154,6 +155,7 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_20413`)
+   = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
    = note: required because of the requirements on the impl of `Foo` for `NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<NoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index a785a956ca9..e7c1dcc5d69 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -87,8 +87,8 @@ note: ...so that the types are compatible
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `Publisher<'_>`
-              found  `Publisher<'_>`
+   = note: expected `Publisher<'_>`
+              found `Publisher<'_>`
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/issue-20831-debruijn.rs:28:33
@@ -117,8 +117,8 @@ note: ...so that the types are compatible
    |
 LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
    |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `Publisher<'_>`
-              found  `Publisher<'_>`
+   = note: expected `Publisher<'_>`
+              found `Publisher<'_>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index 7625e30498a..c4032b27edc 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -1,20 +1,20 @@
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
   --> $DIR/issue-23122-2.rs:7:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |               ^^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
-   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
+   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
-error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
+error[E0275]: overflow evaluating the requirement `<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: std::marker::Sized`
   --> $DIR/issue-23122-2.rs:9:5
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding a `#![recursion_limit="256"]` attribute to your crate (`issue_23122_2`)
-   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
+   = note: required because of the requirements on the impl of `Next` for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-38940.rs b/src/test/ui/issues/issue-38940.rs
index 1c785949547..3f10fc017a7 100644
--- a/src/test/ui/issues/issue-38940.rs
+++ b/src/test/ui/issues/issue-38940.rs
@@ -42,5 +42,5 @@ fn main() {
     let t = Top::new();
     let x: &Bottom = &t;
     //~^ ERROR mismatched types
-    //~| ERROR reached the recursion limit while auto-dereferencing `I`
+    //~| ERROR reached the recursion limit while auto-dereferencing `J`
 }
diff --git a/src/test/ui/issues/issue-38940.stderr b/src/test/ui/issues/issue-38940.stderr
index 36117278fd8..0671cede73b 100644
--- a/src/test/ui/issues/issue-38940.stderr
+++ b/src/test/ui/issues/issue-38940.stderr
@@ -1,4 +1,4 @@
-error[E0055]: reached the recursion limit while auto-dereferencing `I`
+error[E0055]: reached the recursion limit while auto-dereferencing `J`
   --> $DIR/issue-38940.rs:43:22
    |
 LL |     let x: &Bottom = &t;
diff --git a/src/test/ui/issues/issue-52213.stderr b/src/test/ui/issues/issue-52213.stderr
index a8960f77563..7463af9332a 100644
--- a/src/test/ui/issues/issue-52213.stderr
+++ b/src/test/ui/issues/issue-52213.stderr
@@ -14,8 +14,8 @@ note: ...so that the types are compatible
    |
 LL |     match (&t,) {
    |           ^^^^^
-   = note: expected  `(&&(T,),)`
-              found  `(&&'a (T,),)`
+   = note: expected `(&&(T,),)`
+              found `(&&'a (T,),)`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 1:27...
   --> $DIR/issue-52213.rs:1:27
    |
diff --git a/src/test/ui/issues/issue-55796.stderr b/src/test/ui/issues/issue-55796.stderr
index b8cafdc5c14..6bfb7af5444 100644
--- a/src/test/ui/issues/issue-55796.stderr
+++ b/src/test/ui/issues/issue-55796.stderr
@@ -20,8 +20,8 @@ note: ...so that the expression is assignable
    |
 LL |         Box::new(self.out_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
-              found  `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
+   = note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+              found `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/issue-55796.rs:21:9
@@ -45,8 +45,8 @@ note: ...so that the expression is assignable
    |
 LL |         Box::new(self.in_edges(u).map(|e| e.target()))
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
-              found  `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
+   = note: expected `std::boxed::Box<(dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node> + 'static)>`
+              found `std::boxed::Box<dyn std::iter::Iterator<Item = <Self as Graph<'a>>::Node>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-67552.rs b/src/test/ui/issues/issue-67552.rs
new file mode 100644
index 00000000000..1400c6f97b6
--- /dev/null
+++ b/src/test/ui/issues/issue-67552.rs
@@ -0,0 +1,30 @@
+// build-fail
+
+fn main() {
+    rec(Empty);
+}
+
+struct Empty;
+
+impl Iterator for Empty {
+    type Item = ();
+    fn next<'a>(&'a mut self) -> core::option::Option<()> {
+        None
+    }
+}
+
+fn identity<T>(x: T) -> T {
+    x
+}
+
+fn rec<T>(mut it: T)
+//~^ ERROR reached the recursion limit while instantiating
+where
+    T: Iterator,
+{
+    if () == () {
+        T::count(it);
+    } else {
+        rec(identity(&mut it))
+    }
+}
diff --git a/src/test/ui/issues/issue-67552.stderr b/src/test/ui/issues/issue-67552.stderr
new file mode 100644
index 00000000000..881f9d221d6
--- /dev/null
+++ b/src/test/ui/issues/issue-67552.stderr
@@ -0,0 +1,14 @@
+error: reached the recursion limit while instantiating `rec::<&mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut &mut Empty>`
+  --> $DIR/issue-67552.rs:20:1
+   |
+LL | / fn rec<T>(mut it: T)
+LL | |
+LL | | where
+LL | |     T: Iterator,
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-72278.rs b/src/test/ui/issues/issue-72278.rs
new file mode 100644
index 00000000000..92fd1f73a93
--- /dev/null
+++ b/src/test/ui/issues/issue-72278.rs
@@ -0,0 +1,19 @@
+// run-pass
+
+#![allow(unused)]
+
+struct S;
+
+impl S {
+    fn func<'a, U>(&'a self) -> U {
+        todo!()
+    }
+}
+
+fn dont_crash<'a, U>() -> U {
+    S.func::<'a, U>()
+    //~^ WARN cannot specify lifetime arguments explicitly
+    //~| WARN this was previously accepted
+}
+
+fn main() {}
diff --git a/src/test/ui/issues/issue-72278.stderr b/src/test/ui/issues/issue-72278.stderr
new file mode 100644
index 00000000000..41dff686bc4
--- /dev/null
+++ b/src/test/ui/issues/issue-72278.stderr
@@ -0,0 +1,15 @@
+warning: cannot specify lifetime arguments explicitly if late bound lifetime parameters are present
+  --> $DIR/issue-72278.rs:14:14
+   |
+LL |     fn func<'a, U>(&'a self) -> U {
+   |             -- the late bound lifetime parameter is introduced here
+...
+LL |     S.func::<'a, U>()
+   |              ^^
+   |
+   = note: `#[warn(late_bound_lifetime_arguments)]` on by default
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #42868 <https://github.com/rust-lang/rust/issues/42868>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/issues/issue-72574-1.rs b/src/test/ui/issues/issue-72574-1.rs
new file mode 100644
index 00000000000..efbb0bfb150
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-1.rs
@@ -0,0 +1,8 @@
+fn main() {
+    let x = (1, 2, 3);
+    match x {
+        (_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple
diff --git a/src/test/ui/issues/issue-72574-1.stderr b/src/test/ui/issues/issue-72574-1.stderr
new file mode 100644
index 00000000000..329f7d008d4
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-1.stderr
@@ -0,0 +1,14 @@
+error: `_x @` is not allowed in a tuple
+  --> $DIR/issue-72574-1.rs:4:14
+   |
+LL |         (_a, _x @ ..) => {}
+   |              ^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+   |
+LL |         (_a, ..) => {}
+   |              ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/issues/issue-72574-2.rs b/src/test/ui/issues/issue-72574-2.rs
new file mode 100644
index 00000000000..0c8f6fcc508
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-2.rs
@@ -0,0 +1,10 @@
+struct Binder(i32, i32, i32);
+
+fn main() {
+    let x = Binder(1, 2, 3);
+    match x {
+        Binder(_a, _x @ ..) => {}
+        _ => {}
+    }
+}
+//~^^^^ ERROR `_x @` is not allowed in a tuple struct
diff --git a/src/test/ui/issues/issue-72574-2.stderr b/src/test/ui/issues/issue-72574-2.stderr
new file mode 100644
index 00000000000..6faa57bcca6
--- /dev/null
+++ b/src/test/ui/issues/issue-72574-2.stderr
@@ -0,0 +1,14 @@
+error: `_x @` is not allowed in a tuple struct
+  --> $DIR/issue-72574-2.rs:6:20
+   |
+LL |         Binder(_a, _x @ ..) => {}
+   |                    ^^^^^^^ this is only allowed in slice patterns
+   |
+   = help: remove this and bind each tuple field independently
+help: if you don't need to use the contents of _x, discard the tuple's remaining fields
+   |
+LL |         Binder(_a, ..) => {}
+   |                    ^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
index e60c461743c..d682478db0e 100644
--- a/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
+++ b/src/test/ui/lifetimes/lifetime-doesnt-live-long-enough.stderr
@@ -4,13 +4,7 @@ error[E0310]: the parameter type `T` may not live long enough
 LL | struct Foo<T> {
    |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     foo: &'static T
-   |     ^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'static T` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:19:5
-   |
-LL |     foo: &'static T
-   |     ^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
 
 error[E0309]: the parameter type `K` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
@@ -18,13 +12,7 @@ error[E0309]: the parameter type `K` may not live long enough
 LL | trait X<K>: Sized {
    |         - help: consider adding an explicit lifetime bound...: `K: 'a`
 LL |     fn foo<'a, L: X<&'a Nested<K>>>();
-   |                   ^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:24:19
-   |
-LL |     fn foo<'a, L: X<&'a Nested<K>>>();
-   |                   ^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
 
 error[E0309]: the parameter type `Self` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
@@ -33,25 +21,15 @@ LL |     fn bar<'a, L: X<&'a Nested<Self>>>();
    |                   ^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `Self: 'a`...
-note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:28:19
-   |
-LL |     fn bar<'a, L: X<&'a Nested<Self>>>();
-   |                   ^^^^^^^^^^^^^^^^^^^
+   = note: ...so that the reference type `&'a Nested<Self>` does not outlive the data it points at
 
 error[E0309]: the parameter type `L` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22
    |
 LL |     fn baz<'a, L, M: X<&'a Nested<L>>>() {
-   |                -     ^^^^^^^^^^^^^^^^
+   |                -     ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
    |                |
    |                help: consider adding an explicit lifetime bound...: `L: 'a`
-   |
-note: ...so that the reference type `&'a Nested<L>` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:32:22
-   |
-LL |     fn baz<'a, L, M: X<&'a Nested<L>>>() {
-   |                      ^^^^^^^^^^^^^^^^
 
 error[E0309]: the parameter type `K` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
@@ -59,25 +37,15 @@ error[E0309]: the parameter type `K` may not live long enough
 LL | impl<K> Nested<K> {
    |      - help: consider adding an explicit lifetime bound...: `K: 'a`
 LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
-   |                                 ^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:41:33
-   |
-LL |     fn generic_in_parent<'a, L: X<&'a Nested<K>>>() {
-   |                                 ^^^^^^^^^^^^^^^^
+   |                                 ^^^^^^^^^^^^^^^^ ...so that the reference type `&'a Nested<K>` does not outlive the data it points at
 
 error[E0309]: the parameter type `M` may not live long enough
   --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
    |
 LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
    |                                    ^^^^^^^^^^^^^^^^  -- help: consider adding an explicit lifetime bound...: `M: 'a +`
-   |
-note: ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
-  --> $DIR/lifetime-doesnt-live-long-enough.rs:44:36
-   |
-LL |     fn generic_in_child<'a, 'b, L: X<&'a Nested<M>>, M: 'b>() {
-   |                                    ^^^^^^^^^^^^^^^^
+   |                                    |
+   |                                    ...so that the reference type `&'a Nested<M>` does not outlive the data it points at
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
index d07f305954b..060e6954403 100644
--- a/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
+++ b/src/test/ui/lifetimes/lifetime-mismatch-between-trait-and-impl.stderr
@@ -2,13 +2,15 @@ error: `impl` item signature doesn't match `trait` item signature
   --> $DIR/lifetime-mismatch-between-trait-and-impl.rs:6:5
    |
 LL |     fn foo<'a>(x: &i32, y: &'a i32) -> &'a i32;
-   |     ------------------------------------------- expected fn(&i32, &'a i32) -> &'a i32
+   |     ------------------------------------------- expected `fn(&i32, &'a i32) -> &'a i32`
 ...
 LL |     fn foo<'a>(x: &'a i32, y: &'a i32) -> &'a i32 {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found fn(&i32, &i32) -> &i32
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&i32, &i32) -> &i32`
    |
    = note: expected `fn(&i32, &'a i32) -> &'a i32`
               found `fn(&i32, &i32) -> &i32`
+   = help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+   = help: verify the lifetime relationships in the `trait` and `impl` between the `self` argument, the other inputs and its output
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/liveness/liveness-upvars.rs b/src/test/ui/liveness/liveness-upvars.rs
new file mode 100644
index 00000000000..b2837e74b8c
--- /dev/null
+++ b/src/test/ui/liveness/liveness-upvars.rs
@@ -0,0 +1,108 @@
+// edition:2018
+// check-pass
+#![warn(unused)]
+#![allow(unreachable_code)]
+
+pub fn unintentional_copy_one() {
+    let mut last = None;
+    let mut f = move |s| {
+        last = Some(s); //~  WARN value assigned to `last` is never read
+                        //~| WARN unused variable: `last`
+    };
+    f("a");
+    f("b");
+    f("c");
+    dbg!(last.unwrap());
+}
+
+pub fn unintentional_copy_two() {
+    let mut sum = 0;
+    (1..10).for_each(move |x| {
+        sum += x; //~ WARN unused variable: `sum`
+    });
+    dbg!(sum);
+}
+
+pub fn f() {
+    let mut c = 0;
+
+    // Captured by value, but variable is dead on entry.
+    move || {
+        c = 1; //~ WARN value captured by `c` is never read
+        println!("{}", c);
+    };
+    let _ = async move {
+        c = 1; //~ WARN value captured by `c` is never read
+        println!("{}", c);
+    };
+
+    // Read and written to, but never actually used.
+    move || {
+        c += 1; //~ WARN unused variable: `c`
+    };
+    let _ = async move {
+        c += 1; //~  WARN value assigned to `c` is never read
+                //~| WARN unused variable: `c`
+    };
+
+    move || {
+        println!("{}", c);
+        // Value is read by closure itself on later invocations.
+        c += 1;
+    };
+    let b = Box::new(42);
+    move || {
+        println!("{}", c);
+        // Never read because this is FnOnce closure.
+        c += 1; //~  WARN value assigned to `c` is never read
+        drop(b);
+    };
+    let _ = async move {
+        println!("{}", c);
+        // Never read because this is a generator.
+        c += 1; //~  WARN value assigned to `c` is never read
+    };
+}
+
+pub fn nested() {
+    let mut d = None;
+    let mut e = None;
+    || {
+        || {
+            d = Some("d1"); //~ WARN value assigned to `d` is never read
+            d = Some("d2");
+        };
+        move || {
+            e = Some("e1"); //~  WARN value assigned to `e` is never read
+                            //~| WARN unused variable: `e`
+            e = Some("e2"); //~  WARN value assigned to `e` is never read
+        };
+    };
+}
+
+pub fn g<T: Default>(mut v: T) {
+    |r| {
+        if r {
+            v = T::default(); //~ WARN value assigned to `v` is never read
+        } else {
+            drop(v);
+        }
+    };
+}
+
+pub fn h<T: Copy + Default + std::fmt::Debug>() {
+    let mut z = T::default();
+    move |b| {
+        loop {
+            if b {
+                z = T::default(); //~  WARN value assigned to `z` is never read
+                                  //~| WARN unused variable: `z`
+            } else {
+                return;
+            }
+        }
+        dbg!(z);
+    };
+}
+
+fn main() {}
diff --git a/src/test/ui/liveness/liveness-upvars.stderr b/src/test/ui/liveness/liveness-upvars.stderr
new file mode 100644
index 00000000000..14fed917864
--- /dev/null
+++ b/src/test/ui/liveness/liveness-upvars.stderr
@@ -0,0 +1,150 @@
+warning: value assigned to `last` is never read
+  --> $DIR/liveness-upvars.rs:9:9
+   |
+LL |         last = Some(s);
+   |         ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/liveness-upvars.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_assignments)]` implied by `#[warn(unused)]`
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `last`
+  --> $DIR/liveness-upvars.rs:9:9
+   |
+LL |         last = Some(s);
+   |         ^^^^
+   |
+note: the lint level is defined here
+  --> $DIR/liveness-upvars.rs:3:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_variables)]` implied by `#[warn(unused)]`
+   = help: did you mean to capture by reference instead?
+
+warning: unused variable: `sum`
+  --> $DIR/liveness-upvars.rs:21:9
+   |
+LL |         sum += x;
+   |         ^^^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value captured by `c` is never read
+  --> $DIR/liveness-upvars.rs:31:9
+   |
+LL |         c = 1;
+   |         ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value captured by `c` is never read
+  --> $DIR/liveness-upvars.rs:35:9
+   |
+LL |         c = 1;
+   |         ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: unused variable: `c`
+  --> $DIR/liveness-upvars.rs:41:9
+   |
+LL |         c += 1;
+   |         ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value assigned to `c` is never read
+  --> $DIR/liveness-upvars.rs:44:9
+   |
+LL |         c += 1;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `c`
+  --> $DIR/liveness-upvars.rs:44:9
+   |
+LL |         c += 1;
+   |         ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value assigned to `c` is never read
+  --> $DIR/liveness-upvars.rs:57:9
+   |
+LL |         c += 1;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `c` is never read
+  --> $DIR/liveness-upvars.rs:63:9
+   |
+LL |         c += 1;
+   |         ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `d` is never read
+  --> $DIR/liveness-upvars.rs:72:13
+   |
+LL |             d = Some("d1");
+   |             ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `e` is never read
+  --> $DIR/liveness-upvars.rs:76:13
+   |
+LL |             e = Some("e1");
+   |             ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `e` is never read
+  --> $DIR/liveness-upvars.rs:78:13
+   |
+LL |             e = Some("e2");
+   |             ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `e`
+  --> $DIR/liveness-upvars.rs:76:13
+   |
+LL |             e = Some("e1");
+   |             ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: value assigned to `v` is never read
+  --> $DIR/liveness-upvars.rs:86:13
+   |
+LL |             v = T::default();
+   |             ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: value assigned to `z` is never read
+  --> $DIR/liveness-upvars.rs:98:17
+   |
+LL |                 z = T::default();
+   |                 ^
+   |
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `z`
+  --> $DIR/liveness-upvars.rs:98:17
+   |
+LL |                 z = T::default();
+   |                 ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: 17 warnings emitted
+
diff --git a/src/test/ui/nll/issue-55394.stderr b/src/test/ui/nll/issue-55394.stderr
index 69a6ab004fd..ba8d91b8455 100644
--- a/src/test/ui/nll/issue-55394.stderr
+++ b/src/test/ui/nll/issue-55394.stderr
@@ -26,8 +26,8 @@ note: ...so that the expression is assignable
    |
 LL |         Foo { bar }
    |         ^^^^^^^^^^^
-   = note: expected  `Foo<'_>`
-              found  `Foo<'_>`
+   = note: expected `Foo<'_>`
+              found `Foo<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
index 58f206742f4..d003acd879a 100644
--- a/src/test/ui/nll/normalization-bounds-error.stderr
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -19,8 +19,8 @@ note: ...so that the types are compatible
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `Visitor<'d>`
-              found  `Visitor<'_>`
+   = note: expected `Visitor<'d>`
+              found `Visitor<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
index 1a5a3719fd8..eba00c5a945 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-bound.stderr
@@ -5,11 +5,7 @@ LL |     bar::<T::Output>()
    |     ^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as MyTrait<'a>>::Output: 'a`...
-note: ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
-  --> $DIR/projection-where-clause-env-wrong-bound.rs:15:5
-   |
-LL |     bar::<T::Output>()
-   |     ^^^^^^^^^^^^^^^^
+   = note: ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr
index d6ade2a603e..34b83859a6b 100644
--- a/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr
+++ b/src/test/ui/nll/ty-outlives/projection-where-clause-env-wrong-lifetime.stderr
@@ -5,11 +5,7 @@ LL |     bar::<<T as MyTrait<'a>>::Output>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as MyTrait<'a>>::Output: 'a`...
-note: ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
-  --> $DIR/projection-where-clause-env-wrong-lifetime.rs:14:5
-   |
-LL |     bar::<<T as MyTrait<'a>>::Output>()
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...so that the type `<T as MyTrait<'a>>::Output` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/nll/type-alias-free-regions.stderr b/src/test/ui/nll/type-alias-free-regions.stderr
index 5191deca281..3317aae83bb 100644
--- a/src/test/ui/nll/type-alias-free-regions.stderr
+++ b/src/test/ui/nll/type-alias-free-regions.stderr
@@ -16,8 +16,8 @@ note: ...so that the expression is assignable
    |
 LL |         C { f: b }
    |                ^
-   = note: expected  `std::boxed::Box<std::boxed::Box<&isize>>`
-              found  `std::boxed::Box<std::boxed::Box<&isize>>`
+   = note: expected `std::boxed::Box<std::boxed::Box<&isize>>`
+              found `std::boxed::Box<std::boxed::Box<&isize>>`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 15:6...
   --> $DIR/type-alias-free-regions.rs:15:6
    |
@@ -28,8 +28,8 @@ note: ...so that the expression is assignable
    |
 LL |         C { f: b }
    |         ^^^^^^^^^^
-   = note: expected  `C<'a>`
-              found  `C<'_>`
+   = note: expected `C<'a>`
+              found `C<'_>`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/type-alias-free-regions.rs:27:16
@@ -49,8 +49,8 @@ note: ...so that the expression is assignable
    |
 LL |         C { f: Box::new(b.0) }
    |                         ^^^
-   = note: expected  `std::boxed::Box<&isize>`
-              found  `std::boxed::Box<&isize>`
+   = note: expected `std::boxed::Box<&isize>`
+              found `std::boxed::Box<&isize>`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the impl at 25:6...
   --> $DIR/type-alias-free-regions.rs:25:6
    |
@@ -61,8 +61,8 @@ note: ...so that the expression is assignable
    |
 LL |         C { f: Box::new(b.0) }
    |         ^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `C<'a>`
-              found  `C<'_>`
+   = note: expected `C<'a>`
+              found `C<'_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
index 37be450fd0a..8421dc1d0c1 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-inherent-1.stderr
@@ -14,8 +14,8 @@ note: ...so that the types are compatible
    |
 LL |     <Foo<'a>>::C
    |     ^^^^^^^^^^^^
-   = note: expected  `Foo<'_>`
-              found  `Foo<'a>`
+   = note: expected `Foo<'_>`
+              found `Foo<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that reference does not outlive borrowed content
   --> $DIR/constant-in-expr-inherent-1.rs:8:5
diff --git a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
index 4ee32847c5e..ba0a1748c5e 100644
--- a/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
+++ b/src/test/ui/nll/user-annotations/constant-in-expr-trait-item-3.stderr
@@ -14,8 +14,8 @@ note: ...so that the types are compatible
    |
 LL |     T::C
    |     ^^^^
-   = note: expected  `Foo<'_>`
-              found  `Foo<'a>`
+   = note: expected `Foo<'_>`
+              found `Foo<'a>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that reference does not outlive borrowed content
   --> $DIR/constant-in-expr-trait-item-3.rs:10:5
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
index 1952ee8269d..79ded5fc875 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-elision.stderr
@@ -24,8 +24,8 @@ note: ...so that the expression is assignable
    |
 LL |     ss
    |     ^^
-   = note: expected  `&'b (dyn SomeTrait + 'b)`
-              found  `&dyn SomeTrait`
+   = note: expected `&'b (dyn SomeTrait + 'b)`
+              found `&dyn SomeTrait`
 
 error[E0495]: cannot infer an appropriate lifetime due to conflicting requirements
   --> $DIR/object-lifetime-default-elision.rs:71:5
@@ -53,8 +53,8 @@ note: ...so that the expression is assignable
    |
 LL |     ss
    |     ^^
-   = note: expected  `&'b (dyn SomeTrait + 'b)`
-              found  `&dyn SomeTrait`
+   = note: expected `&'b (dyn SomeTrait + 'b)`
+              found `&dyn SomeTrait`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr
index f6252f4ed79..9563c0dff36 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.nll.stderr
@@ -1,11 +1,11 @@
-error[E0621]: explicit lifetime required in the type of `ss`
+error: lifetime may not live long enough
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
-   |             --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
+   |         -- has type `&mut SomeStruct<'1>`
 ...
 LL |     ss.r
-   |     ^^^^ lifetime `'static` required
+   |     ^^^^ returning this value requires that `'1` must outlive `'static`
 
 error[E0507]: cannot move out of `ss.r` which is behind a mutable reference
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
diff --git a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
index 587aab1edce..708ab1cf382 100644
--- a/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
+++ b/src/test/ui/object-lifetime/object-lifetime-default-from-box-error.rs
@@ -15,7 +15,7 @@ fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
     // `Box<SomeTrait>` defaults to a `'static` bound, so this return
     // is illegal.
 
-    ss.r //~ ERROR explicit lifetime required in the type of `ss` [E0621]
+    ss.r //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn store(ss: &mut SomeStruct, b: Box<dyn SomeTrait>) {
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 78e4bdd374d..70a9bf22b8d 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,11 +1,16 @@
-error[E0621]: explicit lifetime required in the type of `ss`
+error: cannot infer an appropriate lifetime
   --> $DIR/object-lifetime-default-from-box-error.rs:18:5
    |
 LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait> {
-   |             --------------- help: add explicit lifetime `'static` to the type of `ss`: `&mut SomeStruct<'static>`
+   |             --------------- data with this lifetime...
 ...
 LL |     ss.r
-   |     ^^^^ lifetime `'static` required
+   |     ^^^^ ...is captured and required to be `'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
+   |
+LL | fn load(ss: &mut SomeStruct) -> Box<dyn SomeTrait + '_> {
+   |                                                   ^^^^
 
 error[E0621]: explicit lifetime required in the type of `ss`
   --> $DIR/object-lifetime-default-from-box-error.rs:31:12
diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs
new file mode 100644
index 00000000000..c5e4a72fb9f
--- /dev/null
+++ b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.rs
@@ -0,0 +1,9 @@
+#![feature(impl_trait_in_bindings)]
+#![allow(incomplete_features)]
+
+fn main() {
+    const C: impl Copy = 0;
+    match C {
+        C | _ => {} //~ ERROR: opaque types cannot be used in patterns
+    }
+}
diff --git a/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr
new file mode 100644
index 00000000000..7695223f2cf
--- /dev/null
+++ b/src/test/ui/pattern/issue-71042-opaquely-typed-constant-used-in-pattern.stderr
@@ -0,0 +1,8 @@
+error: opaque types cannot be used in patterns
+  --> $DIR/issue-71042-opaquely-typed-constant-used-in-pattern.rs:7:9
+   |
+LL |         C | _ => {}
+   |         ^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/proc-macro/macro-rules-capture.rs b/src/test/ui/proc-macro/macro-rules-capture.rs
deleted file mode 100644
index 37436567d70..00000000000
--- a/src/test/ui/proc-macro/macro-rules-capture.rs
+++ /dev/null
@@ -1,18 +0,0 @@
-// aux-build: test-macros.rs
-
-extern crate test_macros;
-use test_macros::recollect_attr;
-
-macro_rules! reemit {
-    ($name:ident => $($token:expr)*) => {
-
-        #[recollect_attr]
-        pub fn $name() {
-            $($token)*;
-        }
-    }
-}
-
-reemit! { foo => 45u32.into() } //~ ERROR type annotations
-
-fn main() {}
diff --git a/src/test/ui/proc-macro/macro-rules-capture.stderr b/src/test/ui/proc-macro/macro-rules-capture.stderr
deleted file mode 100644
index 6d512846ff7..00000000000
--- a/src/test/ui/proc-macro/macro-rules-capture.stderr
+++ /dev/null
@@ -1,12 +0,0 @@
-error[E0282]: type annotations needed
-  --> $DIR/macro-rules-capture.rs:16:24
-   |
-LL | reemit! { foo => 45u32.into() }
-   |                  ------^^^^--
-   |                  |     |
-   |                  |     cannot infer type for type parameter `T` declared on the trait `Into`
-   |                  this method call resolves to `T`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0282`.
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 767853d8148..bf02ba8eb91 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
@@ -14,17 +14,17 @@ LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
 LL |     Box::new(v)
    |     ^^^^^^^^^^^ lifetime `'static` required
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:21:5
+error: lifetime may not live long enough
+  --> $DIR/region-object-lifetime-in-coercion.rs:20:5
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
-   |         ----- 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:26:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
    |
 LL | fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
    |      -- -- lifetime `'b` defined here
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 2dc67599913..d56eaf77b66 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.rs
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.rs
@@ -11,20 +11,17 @@ fn a(v: &[u8]) -> Box<dyn Foo + 'static> {
 }
 
 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 explicit lifetime required in the type of `v` [E0621]
 }
 
 fn c(v: &[u8]) -> Box<dyn Foo> {
     // same as previous case due to RFC 599
 
-    Box::new(v)
-        //~^ ERROR explicit lifetime required in the type of `v` [E0621]
+    Box::new(v) //~ ERROR cannot infer an appropriate lifetime
 }
 
 fn d<'a,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
-    Box::new(v)
-        //~^ ERROR cannot infer an appropriate lifetime due to conflicting
+    Box::new(v) //~ ERROR cannot infer an appropriate lifetime due to conflicting
 }
 
 fn e<'a:'b,'b>(v: &'a [u8]) -> Box<dyn Foo+'b> {
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 e8896516470..1462af44cb1 100644
--- a/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
+++ b/src/test/ui/regions/region-object-lifetime-in-coercion.stderr
@@ -14,45 +14,53 @@ LL | fn b(v: &[u8]) -> Box<dyn Foo + 'static> {
 LL |     Box::new(v)
    |     ^^^^^^^^^^^ lifetime `'static` required
 
-error[E0621]: explicit lifetime required in the type of `v`
-  --> $DIR/region-object-lifetime-in-coercion.rs:21:5
+error: cannot infer an appropriate lifetime
+  --> $DIR/region-object-lifetime-in-coercion.rs:20:14
    |
 LL | fn c(v: &[u8]) -> Box<dyn Foo> {
-   |         ----- help: add explicit lifetime `'static` to the type of `v`: `&'static [u8]`
+   |         ----- data with this lifetime...
 ...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^ lifetime `'static` required
+   |     ---------^-
+   |     |        |
+   |     |        ...and is captured here
+   |     ...is required to be `'static` by this...
+   |
+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
+   |
+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:26:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:24:14
    |
 LL |     Box::new(v)
    |              ^
    |
-note: first, the lifetime cannot outlive the lifetime `'a` as defined on the function body at 25:6...
-  --> $DIR/region-object-lifetime-in-coercion.rs:25:6
+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
    |
 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:26:14
+  --> $DIR/region-object-lifetime-in-coercion.rs:24: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 25:9...
-  --> $DIR/region-object-lifetime-in-coercion.rs:25:9
+   = 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
    |
 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:26:5
+  --> $DIR/region-object-lifetime-in-coercion.rs:24:5
    |
 LL |     Box::new(v)
    |     ^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn Foo + 'b)>`
-              found  `std::boxed::Box<dyn Foo>`
+   = note: expected `std::boxed::Box<(dyn Foo + 'b)>`
+              found `std::boxed::Box<dyn Foo>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
index 865e967fba3..c134b3b3ed5 100644
--- a/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-region-bound-in-trait-not-met.stderr
@@ -14,8 +14,8 @@ note: ...so that the types are compatible
    |
 LL | impl<'a> Foo<'static> for &'a i32 {
    |          ^^^^^^^^^^^^
-   = note: expected  `Foo<'static>`
-              found  `Foo<'static>`
+   = note: expected `Foo<'static>`
+              found `Foo<'static>`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the type `&i32` will meet its required lifetime bounds
   --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:14:10
@@ -39,8 +39,8 @@ note: ...so that the types are compatible
    |
 LL | impl<'a,'b> Foo<'b> for &'a i64 {
    |             ^^^^^^^
-   = note: expected  `Foo<'b>`
-              found  `Foo<'_>`
+   = note: expected `Foo<'b>`
+              found `Foo<'_>`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the impl at 19:9...
   --> $DIR/regions-assoc-type-region-bound-in-trait-not-met.rs:19:9
    |
diff --git a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
index 6a34871c07e..ac8c55ccc8f 100644
--- a/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
+++ b/src/test/ui/regions/regions-assoc-type-static-bound-in-trait-not-met.stderr
@@ -14,8 +14,8 @@ note: ...so that the types are compatible
    |
 LL | impl<'a> Foo for &'a i32 {
    |          ^^^
-   = note: expected  `Foo`
-              found  `Foo`
+   = note: expected `Foo`
+              found `Foo`
    = note: but, the lifetime must be valid for the static lifetime...
 note: ...so that the type `&i32` will meet its required lifetime bounds
   --> $DIR/regions-assoc-type-static-bound-in-trait-not-met.rs:9:10
diff --git a/src/test/ui/regions/regions-close-associated-type-into-object.stderr b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
index 2401f549a56..9303e0f8e66 100644
--- a/src/test/ui/regions/regions-close-associated-type-into-object.stderr
+++ b/src/test/ui/regions/regions-close-associated-type-into-object.stderr
@@ -5,11 +5,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
-note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
-  --> $DIR/regions-close-associated-type-into-object.rs:15:5
-   |
-LL |     Box::new(item)
-   |     ^^^^^^^^^^^^^^
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error[E0310]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:22:5
@@ -18,11 +14,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'static`...
-note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
-  --> $DIR/regions-close-associated-type-into-object.rs:22:5
-   |
-LL |     Box::new(item)
-   |     ^^^^^^^^^^^^^^
+   = note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
 
 error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:28:5
@@ -31,11 +23,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
-note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
-  --> $DIR/regions-close-associated-type-into-object.rs:28:5
-   |
-LL |     Box::new(item)
-   |     ^^^^^^^^^^^^^^
+   = note: ...so that the type `<T as Iter>::Item` will meet its required lifetime bounds
 
 error[E0309]: the associated type `<T as Iter>::Item` may not live long enough
   --> $DIR/regions-close-associated-type-into-object.rs:35:5
@@ -44,11 +32,7 @@ LL |     Box::new(item)
    |     ^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<T as Iter>::Item: 'a`...
-note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
-  --> $DIR/regions-close-associated-type-into-object.rs:35:5
-   |
-LL |     Box::new(item)
-   |     ^^^^^^^^^^^^^^
+   = note: ...so that the type `std::boxed::Box<<T as Iter>::Item>` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
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 28873ab807f..147f7f35418 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
@@ -20,8 +20,8 @@ note: ...so that the expression is assignable
    |
 LL |     box B(&*v) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn X + 'static)>`
-              found  `std::boxed::Box<dyn X>`
+   = note: expected `std::boxed::Box<(dyn X + 'static)>`
+              found `std::boxed::Box<dyn X>`
 
 error: aborting due to previous error
 
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 449a5b5fdd4..6e7d6152cd0 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
@@ -20,8 +20,8 @@ note: ...so that the expression is assignable
    |
 LL |     box B(&*v) as Box<dyn X>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn X + 'static)>`
-              found  `std::boxed::Box<dyn X>`
+   = note: expected `std::boxed::Box<(dyn X + 'static)>`
+              found `std::boxed::Box<dyn X>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-close-object-into-object-5.stderr b/src/test/ui/regions/regions-close-object-into-object-5.stderr
index 2bcdcd1864e..e5a80cbd547 100644
--- a/src/test/ui/regions/regions-close-object-into-object-5.stderr
+++ b/src/test/ui/regions/regions-close-object-into-object-5.stderr
@@ -5,13 +5,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |     ^^^^^^^^^^
-   |
-note: ...so that the type `B<'_, T>` will meet its required lifetime bounds
-  --> $DIR/regions-close-object-into-object-5.rs:17:5
-   |
-LL |     box B(&*v) as Box<X>
-   |     ^^^^^^^^^^
+   |     ^^^^^^^^^^ ...so that the type `B<'_, T>` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:9
@@ -20,13 +14,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |         ^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-close-object-into-object-5.rs:17:9
-   |
-LL |     box B(&*v) as Box<X>
-   |         ^
+   |         ^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:9
@@ -35,13 +23,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |         ^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-close-object-into-object-5.rs:17:9
-   |
-LL |     box B(&*v) as Box<X>
-   |         ^^^^^^
+   |         ^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:11
@@ -50,13 +32,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |           ^^^
-   |
-note: ...so that the reference type `&dyn A<T>` does not outlive the data it points at
-  --> $DIR/regions-close-object-into-object-5.rs:17:11
-   |
-LL |     box B(&*v) as Box<X>
-   |           ^^^
+   |           ^^^ ...so that the reference type `&dyn A<T>` does not outlive the data it points at
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:11
@@ -65,13 +41,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |           ^^^
-   |
-note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-5.rs:17:11
-   |
-LL |     box B(&*v) as Box<X>
-   |           ^^^
+   |           ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-object-into-object-5.rs:17:11
@@ -80,13 +50,7 @@ LL | fn f<'a, T, U>(v: Box<A<T> + 'static>) -> Box<X + 'static> {
    |          - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // oh dear!
 LL |     box B(&*v) as Box<X>
-   |           ^^^
-   |
-note: ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
-  --> $DIR/regions-close-object-into-object-5.rs:17:11
-   |
-LL |     box B(&*v) as Box<X>
-   |           ^^^
+   |           ^^^ ...so that the type `(dyn A<T> + 'static)` is not borrowed for too long
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
index a7509cb608c..50274b066df 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-1.stderr
@@ -4,13 +4,7 @@ error[E0310]: the parameter type `A` may not live long enough
 LL | fn make_object1<A: SomeTrait>(v: A) -> Box<dyn SomeTrait + 'static> {
    |                 -- help: consider adding an explicit lifetime bound...: `A: 'static +`
 LL |     box v as Box<dyn SomeTrait + 'static>
-   |     ^^^^^
-   |
-note: ...so that the type `A` will meet its required lifetime bounds
-  --> $DIR/regions-close-over-type-parameter-1.rs:12:5
-   |
-LL |     box v as Box<dyn SomeTrait + 'static>
-   |     ^^^^^
+   |     ^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-close-over-type-parameter-1.rs:21:5
@@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough
 LL | fn make_object3<'a, 'b, A: SomeTrait + 'a>(v: A) -> Box<dyn SomeTrait + 'b> {
    |                         -- help: consider adding an explicit lifetime bound...: `A: 'b +`
 LL |     box v as Box<dyn SomeTrait + 'b>
-   |     ^^^^^
-   |
-note: ...so that the type `A` will meet its required lifetime bounds
-  --> $DIR/regions-close-over-type-parameter-1.rs:21:5
-   |
-LL |     box v as Box<dyn SomeTrait + 'b>
-   |     ^^^^^
+   |     ^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
index b2a7afaf1b4..2070ce257b1 100644
--- a/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
+++ b/src/test/ui/regions/regions-close-over-type-parameter-multiple.stderr
@@ -24,8 +24,8 @@ note: ...so that the expression is assignable
    |
 LL |     box v as Box<dyn SomeTrait + 'a>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn SomeTrait + 'c)>`
-              found  `std::boxed::Box<dyn SomeTrait>`
+   = note: expected `std::boxed::Box<(dyn SomeTrait + 'c)>`
+              found `std::boxed::Box<dyn SomeTrait>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-close-param-into-object.stderr b/src/test/ui/regions/regions-close-param-into-object.stderr
index 3b1a89d9ced..705d21078ec 100644
--- a/src/test/ui/regions/regions-close-param-into-object.stderr
+++ b/src/test/ui/regions/regions-close-param-into-object.stderr
@@ -5,13 +5,7 @@ LL | fn p1<T>(v: T) -> Box<dyn X + 'static>
    |       - help: consider adding an explicit lifetime bound...: `T: 'static`
 ...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-close-param-into-object.rs:6:5
-   |
-LL |     Box::new(v)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:12:5
@@ -20,13 +14,7 @@ LL | fn p2<T>(v: Box<T>) -> Box<dyn X + 'static>
    |       - help: consider adding an explicit lifetime bound...: `T: 'static`
 ...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
-  --> $DIR/regions-close-param-into-object.rs:12:5
-   |
-LL |     Box::new(v)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:18:5
@@ -35,13 +23,7 @@ LL | fn p3<'a,T>(v: T) -> Box<dyn X + 'a>
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 ...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-close-param-into-object.rs:18:5
-   |
-LL |     Box::new(v)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-close-param-into-object.rs:24:5
@@ -50,13 +32,7 @@ LL | fn p4<'a,T>(v: Box<T>) -> Box<dyn X + 'a>
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 ...
 LL |     Box::new(v)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
-  --> $DIR/regions-close-param-into-object.rs:24:5
-   |
-LL |     Box::new(v)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `std::boxed::Box<T>` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-creating-enums4.stderr b/src/test/ui/regions/regions-creating-enums4.stderr
index 58f74e4ee14..b24db1df18b 100644
--- a/src/test/ui/regions/regions-creating-enums4.stderr
+++ b/src/test/ui/regions/regions-creating-enums4.stderr
@@ -14,8 +14,8 @@ note: ...so that the expression is assignable
    |
 LL |     Ast::Add(x, y)
    |              ^
-   = note: expected  `&Ast<'_>`
-              found  `&Ast<'a>`
+   = note: expected `&Ast<'_>`
+              found `&Ast<'a>`
 note: but, the lifetime must be valid for the lifetime `'b` as defined on the function body at 6:19...
   --> $DIR/regions-creating-enums4.rs:6:19
    |
@@ -26,8 +26,8 @@ note: ...so that the expression is assignable
    |
 LL |     Ast::Add(x, y)
    |     ^^^^^^^^^^^^^^
-   = note: expected  `Ast<'b>`
-              found  `Ast<'_>`
+   = note: expected `Ast<'b>`
+              found `Ast<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-enum-not-wf.stderr b/src/test/ui/regions/regions-enum-not-wf.stderr
index 297fcb088d2..e32a36f72cd 100644
--- a/src/test/ui/regions/regions-enum-not-wf.stderr
+++ b/src/test/ui/regions/regions-enum-not-wf.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref1Variant1(RequireOutlives<'a, T>)
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:18:18
-   |
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:23:25
@@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref2Variant1,
 LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:23:25
-   |
-LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:35:1
@@ -37,16 +25,7 @@ LL |   enum RefDouble<'a, 'b, T> {
 LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
 LL | |
 LL | | }
-   | |_^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL | / enum RefDouble<'a, 'b, T> {
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^
+   | |_^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:36:23
@@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
 LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:36:23
-   |
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
index 2f1a4cea8e9..ea59ea11a14 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-1.stderr
@@ -5,13 +5,7 @@ LL | fn func<'x, T:Trait1<'x>>(t: &'x T::Foo)
    |             -- help: consider adding an explicit lifetime bound...: `T: 'x +`
 LL | {
 LL |     wf::<&'x T>();
-   |          ^^^^^
-   |
-note: ...so that the reference type `&'x T` does not outlive the data it points at
-  --> $DIR/regions-implied-bounds-projection-gap-1.rs:16:10
-   |
-LL |     wf::<&'x T>();
-   |          ^^^^^
+   |          ^^^^^ ...so that the reference type `&'x T` does not outlive the data it points at
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
index bcdadd7a73d..4ca5ac291d5 100644
--- a/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
+++ b/src/test/ui/regions/regions-infer-bound-from-trait-self.stderr
@@ -5,11 +5,7 @@ LL |         check_bound(x, self)
    |         ^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `Self: 'a`...
-note: ...so that the type `Self` will meet its required lifetime bounds
-  --> $DIR/regions-infer-bound-from-trait-self.rs:46:9
-   |
-LL |         check_bound(x, self)
-   |         ^^^^^^^^^^^
+   = note: ...so that the type `Self` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/regions/regions-infer-bound-from-trait.stderr b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
index a5a0ff52fac..196ee8ca7c0 100644
--- a/src/test/ui/regions/regions-infer-bound-from-trait.stderr
+++ b/src/test/ui/regions/regions-infer-bound-from-trait.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `A` may not live long enough
 LL | fn bar1<'a,A>(x: Inv<'a>, a: A) {
    |            - help: consider adding an explicit lifetime bound...: `A: 'a`
 LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `A` will meet its required lifetime bounds
-  --> $DIR/regions-infer-bound-from-trait.rs:33:5
-   |
-LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `A` may not live long enough
   --> $DIR/regions-infer-bound-from-trait.rs:37:5
@@ -18,13 +12,7 @@ error[E0309]: the parameter type `A` may not live long enough
 LL | fn bar2<'a,'b,A:Is<'b>>(x: Inv<'a>, y: Inv<'b>, a: A) {
    |               -- help: consider adding an explicit lifetime bound...: `A: 'a +`
 LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `A` will meet its required lifetime bounds
-  --> $DIR/regions-infer-bound-from-trait.rs:37:5
-   |
-LL |     check_bound(x, a)
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `A` will meet its required lifetime bounds
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/regions/regions-nested-fns.stderr b/src/test/ui/regions/regions-nested-fns.stderr
index 8fce1609d78..9e405d83140 100644
--- a/src/test/ui/regions/regions-nested-fns.stderr
+++ b/src/test/ui/regions/regions-nested-fns.stderr
@@ -39,8 +39,8 @@ LL | |         if false { return ay; }
 LL | |         return z;
 LL | |     }));
    | |_____^
-   = note: expected  `&isize`
-              found  `&isize`
+   = note: expected `&isize`
+              found `&isize`
 
 error[E0312]: lifetime of reference outlives lifetime of borrowed content...
   --> $DIR/regions-nested-fns.rs:14:27
diff --git a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
index c35516d2c08..dc93d620ca6 100644
--- a/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
+++ b/src/test/ui/regions/regions-normalize-in-where-clause-list.stderr
@@ -29,8 +29,8 @@ LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
    | |_^
-   = note: expected  `Project<'a, 'b>`
-              found  `Project<'_, '_>`
+   = note: expected `Project<'a, 'b>`
+              found `Project<'_, '_>`
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:1
@@ -63,8 +63,8 @@ LL | |     where <() as Project<'a, 'b>>::Item : Eq
 LL | | {
 LL | | }
    | |_^
-   = note: expected  `Project<'a, 'b>`
-              found  `Project<'_, '_>`
+   = note: expected `Project<'a, 'b>`
+              found `Project<'_, '_>`
 
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
   --> $DIR/regions-normalize-in-where-clause-list.rs:22:4
@@ -87,8 +87,8 @@ note: ...so that the types are compatible
    |
 LL | fn bar<'a, 'b>()
    |    ^^^
-   = note: expected  `Project<'a, 'b>`
-              found  `Project<'_, '_>`
+   = note: expected `Project<'a, 'b>`
+              found `Project<'_, '_>`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/regions/regions-ret-borrowed-1.stderr b/src/test/ui/regions/regions-ret-borrowed-1.stderr
index 2895a0ccdee..2c4769d8e37 100644
--- a/src/test/ui/regions/regions-ret-borrowed-1.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed-1.stderr
@@ -14,8 +14,8 @@ note: ...so that the expression is assignable
    |
 LL |     with(|o| o)
    |              ^
-   = note: expected  `&isize`
-              found  `&isize`
+   = note: expected `&isize`
+              found `&isize`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 9:14...
   --> $DIR/regions-ret-borrowed-1.rs:9:14
    |
diff --git a/src/test/ui/regions/regions-ret-borrowed.stderr b/src/test/ui/regions/regions-ret-borrowed.stderr
index b74f10f5075..da560107cea 100644
--- a/src/test/ui/regions/regions-ret-borrowed.stderr
+++ b/src/test/ui/regions/regions-ret-borrowed.stderr
@@ -14,8 +14,8 @@ note: ...so that the expression is assignable
    |
 LL |     with(|o| o)
    |              ^
-   = note: expected  `&isize`
-              found  `&isize`
+   = note: expected `&isize`
+              found `&isize`
 note: but, the lifetime must be valid for the lifetime `'a` as defined on the function body at 12:14...
   --> $DIR/regions-ret-borrowed.rs:12:14
    |
diff --git a/src/test/ui/regions/regions-trait-object-subtyping.stderr b/src/test/ui/regions/regions-trait-object-subtyping.stderr
index 58b79d21270..7478b53bd3c 100644
--- a/src/test/ui/regions/regions-trait-object-subtyping.stderr
+++ b/src/test/ui/regions/regions-trait-object-subtyping.stderr
@@ -41,8 +41,8 @@ note: ...so that the expression is assignable
    |
 LL |     x
    |     ^
-   = note: expected  `&'b mut (dyn Dummy + 'b)`
-              found  `&mut (dyn Dummy + 'b)`
+   = note: expected `&'b mut (dyn Dummy + 'b)`
+              found `&mut (dyn Dummy + 'b)`
 
 error[E0308]: mismatched types
   --> $DIR/regions-trait-object-subtyping.rs:22:5
diff --git a/src/test/ui/reject-specialized-drops-8142.stderr b/src/test/ui/reject-specialized-drops-8142.stderr
index c09418de518..f819faa2789 100644
--- a/src/test/ui/reject-specialized-drops-8142.stderr
+++ b/src/test/ui/reject-specialized-drops-8142.stderr
@@ -118,8 +118,8 @@ note: ...so that the types are compatible
    |
 LL | impl<'lw>         Drop for W<'lw,'lw>     { fn drop(&mut self) { } } // REJECT
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `W<'l1, 'l2>`
-              found  `W<'_, '_>`
+   = note: expected `W<'l1, 'l2>`
+              found `W<'_, '_>`
 
 error[E0367]: `Drop` impl requires `AddsBnd: Bound` but the enum it is implemented for does not
   --> $DIR/reject-specialized-drops-8142.rs:61:14
diff --git a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
index c3cfc5a4d97..2bb51731583 100644
--- a/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/dont-infer-static.stderr
@@ -4,13 +4,7 @@ error[E0310]: the parameter type `U` may not live long enough
 LL | struct Foo<U> {
    |            - help: consider adding an explicit lifetime bound...: `U: 'static`
 LL |     bar: Bar<U>
-   |     ^^^^^^^^^^^
-   |
-note: ...so that the type `U` will meet its required lifetime bounds
-  --> $DIR/dont-infer-static.rs:8:5
-   |
-LL |     bar: Bar<U>
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^ ...so that the type `U` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
index 297fcb088d2..e32a36f72cd 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-enum-not-wf.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | enum Ref1<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref1Variant1(RequireOutlives<'a, T>)
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:18:18
-   |
-LL |     Ref1Variant1(RequireOutlives<'a, T>)
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
+   |                  ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:23:25
@@ -19,13 +13,7 @@ LL | enum Ref2<'a, T> {
    |               - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     Ref2Variant1,
 LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:23:25
-   |
-LL |     Ref2Variant2(isize, RequireOutlives<'a, T>),
-   |                         ^^^^^^^^^^^^^^^^^^^^^^
+   |                         ^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:35:1
@@ -37,16 +25,7 @@ LL |   enum RefDouble<'a, 'b, T> {
 LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
 LL | |
 LL | | }
-   | |_^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:35:1
-   |
-LL | / enum RefDouble<'a, 'b, T> {
-LL | |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-LL | |
-LL | | }
-   | |_^
+   | |_^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-enum-not-wf.rs:36:23
@@ -54,13 +33,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | enum RefDouble<'a, 'b, T> {
    |                        - help: consider adding an explicit lifetime bound...: `T: 'b`
 LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-enum-not-wf.rs:36:23
-   |
-LL |     RefDoubleVariant1(&'a RequireOutlives<'b, T>)
-   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
index f6658891fa6..44812a51778 100644
--- a/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
+++ b/src/test/ui/rfc-2093-infer-outlives/regions-struct-not-wf.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | impl<'a, T> Trait<'a, T> for usize {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a T;
-   |     ^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a T` does not outlive the data it points at
-  --> $DIR/regions-struct-not-wf.rs:13:5
-   |
-LL |     type Out = &'a T;
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/regions-struct-not-wf.rs:21:5
@@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | impl<'a, T> Trait<'a, T> for u32 {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = RefOk<'a, T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/regions-struct-not-wf.rs:21:5
-   |
-LL |     type Out = RefOk<'a, T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 
 error[E0491]: in type `&'a &'b T`, reference has a longer lifetime than the data it references
   --> $DIR/regions-struct-not-wf.rs:25:5
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 91075ffbdb6..1aeabce5e8a 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
@@ -2,15 +2,10 @@ error: 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 }
-   |                ^^^^                 ---------- this return type evaluates to the `'static` lifetime...
-   |                |
-   |                ...but this borrow...
-   |
-note: ...can't outlive the lifetime `'_` as defined on the method body at 8:26
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait-async.rs:8:26
-   |
-LL |     async fn f(self: Pin<&Self>) -> impl Clone { self }
-   |                          ^
+   |                ^^^^  ----------     ---------- ...and required to be `'static` by this
+   |                |     |
+   |                |     data with this lifetime...
+   |                ...is captured here...
 
 error: aborting due to previous error
 
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 47ab6fff838..04c475be787 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
@@ -2,19 +2,15 @@ error: 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 }
-   |                               ----------   ^^^^ ...but this borrow...
-   |                               |
-   |                               this return type evaluates to the `'static` lifetime...
+   |                ----------     ----------   ^^^^ ...and is captured here
+   |                |              |
+   |                |              ...is required to be `'static` by this...
+   |                data with this lifetime...
    |
-note: ...can't outlive the anonymous lifetime #1 defined on the method body at 6:5
-  --> $DIR/arbitrary_self_types_pin_lifetime_impl_trait.rs:6:5
-   |
-LL |     fn f(self: Pin<&Self>) -> impl Clone { self }
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-help: you can add a bound to the return type to make it last less than `'static` and match the anonymous lifetime #1 defined on the method body at 6:5
+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
    |
 LL |     fn f(self: Pin<&Self>) -> impl Clone + '_ { self }
-   |                               ^^^^^^^^^^^^^^^
+   |                                          ^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
new file mode 100644
index 00000000000..2072b00f7b2
--- /dev/null
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.nll.stderr
@@ -0,0 +1,115 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/missing-lifetimes-in-signature.rs:37:11
+   |
+LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |        -  ^^ undeclared lifetime
+   |        |
+   |        help: consider introducing lifetime `'a` here: `'a,`
+
+error: lifetime may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:15:37
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+   |                          -          ^^^^^^^^^^^^^ opaque type requires that `'1` must outlive `'static`
+   |                          |
+   |                          let's call the lifetime of this reference `'1`
+   |
+help: to allow this `impl Trait` to capture borrowed data with lifetime `'1`, add `'_` as a bound
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:25:37
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1...
+  --> $DIR/missing-lifetimes-in-signature.rs:25:1
+   |
+LL | / fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL | |
+LL | | where
+LL | |     G: Get<T>
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:47:45
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                             ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1...
+  --> $DIR/missing-lifetimes-in-signature.rs:47:1
+   |
+LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL | |
+LL | | where
+LL | |     G: Get<T>
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:59:58
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                                          ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
+  --> $DIR/missing-lifetimes-in-signature.rs:59:5
+   |
+LL | /     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+LL | |
+LL | |         move || {
+LL | |             *dest = g.get();
+LL | |         }
+LL | |     }
+   | |_____^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:68:45
+   |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                             ^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 68:1...
+  --> $DIR/missing-lifetimes-in-signature.rs:68:1
+   |
+LL | / fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+LL | |
+LL | | where
+LL | |     G: Get<T>
+...  |
+LL | |     }
+LL | | }
+   | |_^
+
+error[E0621]: explicit lifetime required in the type of `dest`
+  --> $DIR/missing-lifetimes-in-signature.rs:73:5
+   |
+LL |   fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                    ------ help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^ lifetime `'a` required
+
+error[E0309]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:79:44
+   |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+   |                                            ^^^^^^^^^^^^^^^^^^
+   |
+   = help: consider adding an explicit lifetime bound `G: 'a`...
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0261, E0309, E0621.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
new file mode 100644
index 00000000000..d3853445dfd
--- /dev/null
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.rs
@@ -0,0 +1,110 @@
+pub trait Get<T> {
+    fn get(self) -> T;
+}
+
+struct Foo {
+    x: usize,
+}
+
+impl Get<usize> for Foo {
+    fn get(self) -> usize {
+        self.x
+    }
+}
+
+fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce()
+where
+    G: Get<T>
+{
+    move || { //~ ERROR cannot infer an appropriate lifetime
+        *dest = g.get();
+    }
+}
+
+// After applying suggestion for `foo`:
+fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+
+// After applying suggestion for `bar`:
+fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ //~ ERROR undeclared lifetime
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+// After applying suggestion for `baz`:
+fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+//~^ ERROR the parameter type `G` may not live long enough
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+// Same as above, but show that we pay attention to lifetime names from parent item
+impl<'a> Foo {
+    fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+        //~^ ERROR the parameter type `G` may not live long enough
+        move || {
+            *dest = g.get();
+        }
+    }
+}
+
+// After applying suggestion for `qux`:
+fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+//~^ ERROR explicit lifetime required in the type of `dest`
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+// Potential incorrect attempt:
+fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+//~^ ERROR the parameter type `G` may not live long enough
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+
+// We need to tie the lifetime of `G` with the lifetime of `&mut T` and the returned closure:
+fn ok<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+// This also works. The `'_` isn't necessary but it's where we arrive to following the suggestions:
+fn ok2<'a, G: 'a, T>(g: G, dest: &'a mut T) -> impl FnOnce() + '_ + 'a
+where
+    G: Get<T>
+{
+    move || {
+        *dest = g.get();
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
new file mode 100644
index 00000000000..5cf170d566c
--- /dev/null
+++ b/src/test/ui/suggestions/lifetimes/missing-lifetimes-in-signature.stderr
@@ -0,0 +1,126 @@
+error[E0261]: use of undeclared lifetime name `'a`
+  --> $DIR/missing-lifetimes-in-signature.rs:37:11
+   |
+LL | fn baz<G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |        -  ^^ undeclared lifetime
+   |        |
+   |        help: consider introducing lifetime `'a` here: `'a,`
+
+error: 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...
+...
+LL | /     move || {
+LL | |         *dest = g.get();
+LL | |     }
+   | |_____^ ...and 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
+   |
+LL | fn foo<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                                   ^^^^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:25:37
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 25:1...
+  --> $DIR/missing-lifetimes-in-signature.rs:25:1
+   |
+LL | / fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL | |
+LL | | where
+LL | |     G: Get<T>
+...  |
+LL | |     }
+LL | | }
+   | |_^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:30:5: 32:6 g:G, dest:&mut T]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:25:37
+   |
+LL | fn bar<G, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                     ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL | fn bar<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |        ^^^^^                                                   ^^^^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:47:45
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                             ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the function body at 47:1...
+  --> $DIR/missing-lifetimes-in-signature.rs:47:1
+   |
+LL | / fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+LL | |
+LL | | where
+LL | |     G: Get<T>
+...  |
+LL | |     }
+LL | | }
+   | |_^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:52:5: 54:6 g:G, dest:&mut T]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:47:45
+   |
+LL | fn qux<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_
+   |                                             ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL | fn qux<'b, 'a, G: 'b + 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'b
+   |        ^^^     ^^^^^^^                                                  ^^^^
+
+error[E0311]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:59:58
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                                          ^^^^^^^^^^^^^^^^^^
+   |
+note: the parameter type `G` must be valid for the anonymous lifetime #1 defined on the method body at 59:5...
+  --> $DIR/missing-lifetimes-in-signature.rs:59:5
+   |
+LL | /     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+LL | |
+LL | |         move || {
+LL | |             *dest = g.get();
+LL | |         }
+LL | |     }
+   | |_____^
+note: ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:61:9: 63:10 g:G, dest:&mut T]` will meet its required lifetime bounds
+  --> $DIR/missing-lifetimes-in-signature.rs:59:58
+   |
+LL |     fn qux<'b, G: Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ {
+   |                                                          ^^^^^^^^^^^^^^^^^^
+help: consider introducing an explicit lifetime bound
+   |
+LL |     fn qux<'c, 'b, G: 'c + Get<T> + 'b, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'c {
+   |            ^^^     ^^^^^^^                                                           ^^^^
+
+error[E0621]: explicit lifetime required in the type of `dest`
+  --> $DIR/missing-lifetimes-in-signature.rs:68:45
+   |
+LL | fn bat<'a, G: 'a, T>(g: G, dest: &mut T) -> impl FnOnce() + '_ + 'a
+   |                                  ------     ^^^^^^^^^^^^^^^^^^^^^^^ lifetime `'a` required
+   |                                  |
+   |                                  help: add explicit lifetime `'a` to the type of `dest`: `&'a mut T`
+
+error[E0309]: the parameter type `G` may not live long enough
+  --> $DIR/missing-lifetimes-in-signature.rs:79:44
+   |
+LL | fn bak<'a, G, T>(g: G, dest: &'a mut T) -> impl FnOnce() + 'a
+   |            -                               ^^^^^^^^^^^^^^^^^^ ...so that the type `[closure@$DIR/missing-lifetimes-in-signature.rs:84:5: 86:6 g:G, dest:&mut T]` will meet its required lifetime bounds
+   |            |
+   |            help: consider adding an explicit lifetime bound...: `G: 'a`
+
+error: aborting due to 7 previous errors
+
+Some errors have detailed explanations: E0261, E0309, E0621.
+For more information about an error, try `rustc --explain E0261`.
diff --git a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
index b6e6c0bbf32..643dac25724 100644
--- a/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
+++ b/src/test/ui/suggestions/suggest-impl-trait-lifetime.stderr
@@ -5,13 +5,7 @@ LL | fn foo(d: impl Debug) {
    |           ---------- help: consider adding an explicit lifetime bound...: `impl Debug + 'static`
 LL |
 LL |     bar(d);
-   |     ^^^
-   |
-note: ...so that the type `impl Debug` will meet its required lifetime bounds
-  --> $DIR/suggest-impl-trait-lifetime.rs:7:5
-   |
-LL |     bar(d);
-   |     ^^^
+   |     ^^^ ...so that the type `impl Debug` will meet its required lifetime bounds
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/self-without-lifetime-constraint.rs b/src/test/ui/traits/self-without-lifetime-constraint.rs
new file mode 100644
index 00000000000..99013d32ab8
--- /dev/null
+++ b/src/test/ui/traits/self-without-lifetime-constraint.rs
@@ -0,0 +1,53 @@
+use std::error::Error;
+use std::fmt;
+
+#[derive(Copy, Clone, Debug, PartialEq)]
+pub enum ValueRef<'a> {
+    Null,
+    Integer(i64),
+    Real(f64),
+    Text(&'a [u8]),
+    Blob(&'a [u8]),
+}
+
+impl<'a> ValueRef<'a> {
+    pub fn as_str(&self) -> FromSqlResult<&'a str, &'a &'a str> {
+        match *self {
+            ValueRef::Text(t) => {
+                std::str::from_utf8(t).map_err(|_| FromSqlError::InvalidType).map(|x| (x, &x))
+            }
+            _ => Err(FromSqlError::InvalidType),
+        }
+    }
+}
+
+#[derive(Debug)]
+#[non_exhaustive]
+pub enum FromSqlError {
+    InvalidType
+}
+
+impl fmt::Display for FromSqlError {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "InvalidType")
+    }
+}
+
+impl Error for FromSqlError {}
+
+pub type FromSqlResult<T, K> = Result<(T, K), FromSqlError>;
+
+pub trait FromSql: Sized {
+    fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+}
+
+impl FromSql for &str {
+    fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
+    //~^ ERROR `impl` item signature doesn't match `trait` item signature
+        value.as_str()
+    }
+}
+
+pub fn main() {
+    println!("{}", "Hello World");
+}
diff --git a/src/test/ui/traits/self-without-lifetime-constraint.stderr b/src/test/ui/traits/self-without-lifetime-constraint.stderr
new file mode 100644
index 00000000000..6c7abe753e2
--- /dev/null
+++ b/src/test/ui/traits/self-without-lifetime-constraint.stderr
@@ -0,0 +1,19 @@
+error: `impl` item signature doesn't match `trait` item signature
+  --> $DIR/self-without-lifetime-constraint.rs:45:5
+   |
+LL |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+   |     -------------------------------------------------------------------- expected `fn(ValueRef<'_>) -> std::result::Result<(&str, &&str), FromSqlError>`
+...
+LL |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<&str, &&str> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(ValueRef<'_>) -> std::result::Result<(&str, &&str), FromSqlError>`
+   |
+   = note: expected `fn(ValueRef<'_>) -> std::result::Result<(&str, &&str), _>`
+              found `fn(ValueRef<'_>) -> std::result::Result<(&str, &&str), _>`
+help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+  --> $DIR/self-without-lifetime-constraint.rs:41:60
+   |
+LL |     fn column_result(value: ValueRef<'_>) -> FromSqlResult<Self, &Self>;
+   |                                                            ^^^^ consider borrowing this type parameter in the trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
index 9fdcd4de495..46aa7db967a 100644
--- a/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
+++ b/src/test/ui/traits/trait-impl-of-supertrait-has-wrong-lifetime-parameters.stderr
@@ -19,8 +19,8 @@ note: ...so that the types are compatible
    |
 LL | impl<'a,'b> T2<'a, 'b> for S<'a, 'b> {
    |             ^^^^^^^^^^
-   = note: expected  `T1<'a>`
-              found  `T1<'_>`
+   = note: expected `T1<'a>`
+              found `T1<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/trait-param-without-lifetime-constraint.rs b/src/test/ui/traits/trait-param-without-lifetime-constraint.rs
new file mode 100644
index 00000000000..a79b74dcdde
--- /dev/null
+++ b/src/test/ui/traits/trait-param-without-lifetime-constraint.rs
@@ -0,0 +1,20 @@
+struct Article {
+    proof_reader: ProofReader,
+}
+
+struct ProofReader {
+    name: String,
+}
+
+pub trait HaveRelationship<To> {
+    fn get_relation(&self) -> To;
+}
+
+impl HaveRelationship<&ProofReader> for Article {
+    fn get_relation(&self) -> &ProofReader {
+    //~^ ERROR `impl` item signature doesn't match `trait` item signature
+        &self.proof_reader
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/traits/trait-param-without-lifetime-constraint.stderr b/src/test/ui/traits/trait-param-without-lifetime-constraint.stderr
new file mode 100644
index 00000000000..4942dbe480b
--- /dev/null
+++ b/src/test/ui/traits/trait-param-without-lifetime-constraint.stderr
@@ -0,0 +1,19 @@
+error: `impl` item signature doesn't match `trait` item signature
+  --> $DIR/trait-param-without-lifetime-constraint.rs:14:5
+   |
+LL |     fn get_relation(&self) -> To;
+   |     ----------------------------- expected `fn(&Article) -> &ProofReader`
+...
+LL |     fn get_relation(&self) -> &ProofReader {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ found `fn(&Article) -> &ProofReader`
+   |
+   = note: expected `fn(&Article) -> &ProofReader`
+              found `fn(&Article) -> &ProofReader`
+help: the lifetime requirements from the `impl` do not correspond to the requirements in the `trait`
+  --> $DIR/trait-param-without-lifetime-constraint.rs:10:31
+   |
+LL |     fn get_relation(&self) -> To;
+   |                               ^^ consider borrowing this type parameter in the trait
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index 22e2391f838..e2540e424cb 100644
--- a/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -22,16 +22,10 @@ error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
    |
 LL | type WrongGeneric<T> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `T` will meet its required lifetime bounds
 ...
 LL | fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
    |                  - help: consider adding an explicit lifetime bound...: `T: 'static`
-   |
-note: ...so that the type `T` will meet its required lifetime bounds
-  --> $DIR/generic_type_does_not_live_long_enough.rs:9:1
-   |
-LL | type WrongGeneric<T> = impl 'static;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/type-alias-impl-trait/issue-70121.rs b/src/test/ui/type-alias-impl-trait/issue-70121.rs
new file mode 100644
index 00000000000..dff0d89d465
--- /dev/null
+++ b/src/test/ui/type-alias-impl-trait/issue-70121.rs
@@ -0,0 +1,23 @@
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+pub type Successors<'a> = impl Iterator<Item = &'a ()>;
+
+pub fn f<'a>() -> Successors<'a> {
+    None.into_iter()
+}
+
+pub trait Tr {
+    type Item;
+}
+
+impl<'a> Tr for &'a () {
+    type Item = Successors<'a>;
+}
+
+pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
+    None.into_iter()
+}
+
+fn main() {}
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs
index fb24df3c24e..390386e57fa 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.rs
@@ -1,5 +1,4 @@
 // run-pass
-#![allow(unused_variables)]
 // Test that we mutate a counter on the stack only when we expect to.
 
 fn call<F>(f: F) where F : FnOnce() {
@@ -13,7 +12,7 @@ fn main() {
     call(|| {
         // Move `y`, but do not move `counter`, even though it is read
         // by value (note that it is also mutated).
-        for item in y {
+        for item in y { //~ WARN unused variable: `item`
             let v = counter;
             counter += v;
         }
@@ -22,7 +21,8 @@ fn main() {
 
     call(move || {
         // this mutates a moved copy, and hence doesn't affect original
-        counter += 1;
+        counter += 1; //~  WARN value assigned to `counter` is never read
+                      //~| WARN unused variable: `counter`
     });
     assert_eq!(counter, 88);
 }
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr
new file mode 100644
index 00000000000..ba4b3dac670
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-counter-not-moved.stderr
@@ -0,0 +1,27 @@
+warning: unused variable: `item`
+  --> $DIR/unboxed-closures-counter-not-moved.rs:15:13
+   |
+LL |         for item in y {
+   |             ^^^^ help: if this is intentional, prefix it with an underscore: `_item`
+   |
+   = note: `#[warn(unused_variables)]` on by default
+
+warning: value assigned to `counter` is never read
+  --> $DIR/unboxed-closures-counter-not-moved.rs:24:9
+   |
+LL |         counter += 1;
+   |         ^^^^^^^
+   |
+   = note: `#[warn(unused_assignments)]` on by default
+   = help: maybe it is overwritten before being read?
+
+warning: unused variable: `counter`
+  --> $DIR/unboxed-closures-counter-not-moved.rs:24:9
+   |
+LL |         counter += 1;
+   |         ^^^^^^^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: 3 warnings emitted
+
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
index 9b519e63a95..e5b19db7822 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
+++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.rs
@@ -13,11 +13,11 @@ fn set(x: &mut usize) { *x = 42; }
 fn main() {
     {
         let mut x = 0_usize;
-        move || x += 1;
+        move || x += 1; //~ WARN unused variable: `x`
     }
     {
         let mut x = 0_usize;
-        move || x += 1;
+        move || x += 1; //~ WARN unused variable: `x`
     }
     {
         let mut x = 0_usize;
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
new file mode 100644
index 00000000000..4dfd1bb3075
--- /dev/null
+++ b/src/test/ui/unboxed-closures/unboxed-closures-move-mutable.stderr
@@ -0,0 +1,19 @@
+warning: unused variable: `x`
+  --> $DIR/unboxed-closures-move-mutable.rs:16:17
+   |
+LL |         move || x += 1;
+   |                 ^
+   |
+   = note: `#[warn(unused_variables)]` on by default
+   = help: did you mean to capture by reference instead?
+
+warning: unused variable: `x`
+  --> $DIR/unboxed-closures-move-mutable.rs:20:17
+   |
+LL |         move || x += 1;
+   |                 ^
+   |
+   = help: did you mean to capture by reference instead?
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
index e6029e0d462..3577dd59289 100644
--- a/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
+++ b/src/test/ui/underscore-lifetime/dyn-trait-underscore.stderr
@@ -1,31 +1,16 @@
-error[E0495]: cannot infer an appropriate lifetime for autoref due to conflicting requirements
+error: 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...
+LL |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
 LL |     Box::new(items.iter())
-   |                    ^^^^
+   |     ---------------^^^^--- ...is captured and required to be `'static` here
    |
-note: first, the lifetime cannot outlive the anonymous lifetime #1 defined on the function body at 6:1...
-  --> $DIR/dyn-trait-underscore.rs:6:1
+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
    |
-LL | / fn a<T>(items: &[T]) -> Box<dyn Iterator<Item=&T>> {
-LL | |     //                      ^^^^^^^^^^^^^^^^^^^^^ bound *here* defaults to `'static`
-LL | |     Box::new(items.iter())
-LL | | }
-   | |_^
-note: ...so that reference does not outlive borrowed content
-  --> $DIR/dyn-trait-underscore.rs:8:14
-   |
-LL |     Box::new(items.iter())
-   |              ^^^^^
-   = note: but, the lifetime must be valid for the static lifetime...
-note: ...so that the expression is assignable
-  --> $DIR/dyn-trait-underscore.rs:8:5
-   |
-LL |     Box::new(items.iter())
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected  `std::boxed::Box<(dyn std::iter::Iterator<Item = &T> + 'static)>`
-              found  `std::boxed::Box<dyn std::iter::Iterator<Item = &T>>`
+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 E0495`.
diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs
new file mode 100644
index 00000000000..540612a7dce
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs
@@ -0,0 +1,67 @@
+#![feature(unsafe_block_in_unsafe_fn)]
+
+#[repr(packed)]
+pub struct Packed {
+    data: &'static u32,
+}
+
+const PACKED: Packed = Packed { data: &0 };
+
+#[allow(safe_packed_borrows)]
+#[allow(unsafe_op_in_unsafe_fn)]
+unsafe fn allow_allow() {
+    &PACKED.data; // allowed
+}
+
+#[allow(safe_packed_borrows)]
+#[warn(unsafe_op_in_unsafe_fn)]
+unsafe fn allow_warn() {
+    &PACKED.data; // allowed
+}
+
+#[allow(safe_packed_borrows)]
+#[deny(unsafe_op_in_unsafe_fn)]
+unsafe fn allow_deny() {
+    &PACKED.data; // allowed
+}
+
+#[warn(safe_packed_borrows)]
+#[allow(unsafe_op_in_unsafe_fn)]
+unsafe fn warn_allow() {
+    &PACKED.data; // allowed
+}
+
+#[warn(safe_packed_borrows)]
+#[warn(unsafe_op_in_unsafe_fn)]
+unsafe fn warn_warn() {
+    &PACKED.data; //~ WARN
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
+
+#[warn(safe_packed_borrows)]
+#[deny(unsafe_op_in_unsafe_fn)]
+unsafe fn warn_deny() {
+    &PACKED.data; //~ WARN
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
+
+#[deny(safe_packed_borrows)]
+#[allow(unsafe_op_in_unsafe_fn)]
+unsafe fn deny_allow() {
+    &PACKED.data; // allowed
+}
+
+#[deny(safe_packed_borrows)]
+#[warn(unsafe_op_in_unsafe_fn)]
+unsafe fn deny_warn() {
+    &PACKED.data; //~ WARN
+}
+
+#[deny(safe_packed_borrows)]
+#[deny(unsafe_op_in_unsafe_fn)]
+unsafe fn deny_deny() {
+    &PACKED.data; //~ ERROR
+    //~| WARNING this was previously accepted by the compiler but is being phased out
+}
+
+fn main() {}
diff --git a/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr
new file mode 100644
index 00000000000..fda15159643
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-safe_packed_borrows-in-unsafe-fn.stderr
@@ -0,0 +1,60 @@
+warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:37:5
+   |
+LL |     &PACKED.data;
+   |     ^^^^^^^^^^^^ borrow of packed field
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:34:8
+   |
+LL | #[warn(safe_packed_borrows)]
+   |        ^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:44:5
+   |
+LL |     &PACKED.data;
+   |     ^^^^^^^^^^^^ borrow of packed field
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:41:8
+   |
+LL | #[warn(safe_packed_borrows)]
+   |        ^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+warning: borrow of packed field is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:57:5
+   |
+LL |     &PACKED.data;
+   |     ^^^^^^^^^^^^ borrow of packed field
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:55:8
+   |
+LL | #[warn(unsafe_op_in_unsafe_fn)]
+   |        ^^^^^^^^^^^^^^^^^^^^^^
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+error: borrow of packed field is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:63:5
+   |
+LL |     &PACKED.data;
+   |     ^^^^^^^^^^^^ borrow of packed field
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-safe_packed_borrows-in-unsafe-fn.rs:60:8
+   |
+LL | #[deny(safe_packed_borrows)]
+   |        ^^^^^^^^^^^^^^^^^^^
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #46043 <https://github.com/rust-lang/rust/issues/46043>
+   = note: fields of packed structs might be misaligned: dereferencing a misaligned pointer or even just creating a misaligned reference is undefined behavior
+
+error: aborting due to previous error; 3 warnings emitted
+
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
new file mode 100644
index 00000000000..1e57b03ced4
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs
@@ -0,0 +1,76 @@
+#![feature(unsafe_block_in_unsafe_fn)]
+#![deny(unsafe_op_in_unsafe_fn)]
+#![deny(unused_unsafe)]
+
+unsafe fn unsf() {}
+const PTR: *const () = std::ptr::null();
+static mut VOID: () = ();
+
+unsafe fn deny_level() {
+    unsf();
+    //~^ ERROR call to unsafe function is unsafe and requires unsafe block
+    *PTR;
+    //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    VOID = ();
+    //~^ ERROR use of mutable static is unsafe and requires unsafe block
+}
+
+// Check that `unsafe_op_in_unsafe_fn` works starting from the `warn` level.
+#[warn(unsafe_op_in_unsafe_fn)]
+#[deny(warnings)]
+unsafe fn warning_level() {
+    unsf();
+    //~^ ERROR call to unsafe function is unsafe and requires unsafe block
+    *PTR;
+    //~^ ERROR dereference of raw pointer is unsafe and requires unsafe block
+    VOID = ();
+    //~^ ERROR use of mutable static is unsafe and requires unsafe block
+}
+
+unsafe fn explicit_block() {
+    // no error
+    unsafe {
+        unsf();
+        *PTR;
+        VOID = ();
+    }
+}
+
+unsafe fn two_explicit_blocks() {
+    unsafe { unsafe { unsf() } }
+    //~^ ERROR unnecessary `unsafe` block
+}
+
+#[allow(unsafe_op_in_unsafe_fn)]
+unsafe fn allow_level() {
+    // lint allowed -> no error
+    unsf();
+    *PTR;
+    VOID = ();
+
+    unsafe { unsf() }
+    //~^ ERROR unnecessary `unsafe` block
+}
+
+unsafe fn nested_allow_level() {
+    #[allow(unsafe_op_in_unsafe_fn)]
+    {
+        // lint allowed -> no error
+        unsf();
+        *PTR;
+        VOID = ();
+
+        unsafe { unsf() }
+        //~^ ERROR unnecessary `unsafe` block
+    }
+}
+
+fn main() {
+    unsf();
+    //~^ ERROR call to unsafe function is unsafe and requires unsafe block
+    #[allow(unsafe_op_in_unsafe_fn)]
+    {
+        unsf();
+        //~^ ERROR call to unsafe function is unsafe and requires unsafe function or block
+    }
+}
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
new file mode 100644
index 00000000000..cc595df12cc
--- /dev/null
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.stderr
@@ -0,0 +1,104 @@
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:10:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:2:9
+   |
+LL | #![deny(unsafe_op_in_unsafe_fn)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:12:5
+   |
+LL |     *PTR;
+   |     ^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:14:5
+   |
+LL |     VOID = ();
+   |     ^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: call to unsafe function is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:22:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:20:8
+   |
+LL | #[deny(warnings)]
+   |        ^^^^^^^^
+   = note: `#[deny(unsafe_op_in_unsafe_fn)]` implied by `#[deny(warnings)]`
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: dereference of raw pointer is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:24:5
+   |
+LL |     *PTR;
+   |     ^^^^ dereference of raw pointer
+   |
+   = note: raw pointers may be NULL, dangling or unaligned; they can violate aliasing rules and cause data races: all of these are undefined behavior
+
+error: use of mutable static is unsafe and requires unsafe block (error E0133)
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:26:5
+   |
+LL |     VOID = ();
+   |     ^^^^^^^^^ use of mutable static
+   |
+   = note: mutable statics can be mutated by multiple threads: aliasing violations or data races will cause undefined behavior
+
+error: unnecessary `unsafe` block
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:40:14
+   |
+LL |     unsafe { unsafe { unsf() } }
+   |     ------   ^^^^^^ unnecessary `unsafe` block
+   |     |
+   |     because it's nested under this `unsafe` block
+   |
+note: the lint level is defined here
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:3:9
+   |
+LL | #![deny(unused_unsafe)]
+   |         ^^^^^^^^^^^^^
+
+error: unnecessary `unsafe` block
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:51:5
+   |
+LL |     unsafe { unsf() }
+   |     ^^^^^^ unnecessary `unsafe` block
+
+error: unnecessary `unsafe` block
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:63:9
+   |
+LL |         unsafe { unsf() }
+   |         ^^^^^^ unnecessary `unsafe` block
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe block
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:69:5
+   |
+LL |     unsf();
+   |     ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error[E0133]: call to unsafe function is unsafe and requires unsafe function or block
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:73:9
+   |
+LL |         unsf();
+   |         ^^^^^^ call to unsafe function
+   |
+   = note: consult the function's documentation for information on how to avoid undefined behavior
+
+error: aborting due to 11 previous errors
+
+For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unused-crate-deps/test-use-ok.rs b/src/test/ui/unused-crate-deps/test-use-ok.rs
new file mode 100644
index 00000000000..66d6440c9cb
--- /dev/null
+++ b/src/test/ui/unused-crate-deps/test-use-ok.rs
@@ -0,0 +1,15 @@
+// Test-only use OK
+
+// edition:2018
+// check-pass
+// aux-crate:bar=bar.rs
+// compile-flags:--test
+
+#![deny(unused_crate_dependencies)]
+
+fn main() {}
+
+#[test]
+fn test_bar() {
+    assert_eq!(bar::BAR, "bar");
+}
diff --git a/src/test/ui/wf/wf-impl-associated-type-region.stderr b/src/test/ui/wf/wf-impl-associated-type-region.stderr
index 9942c80effe..f3b32ad3f7e 100644
--- a/src/test/ui/wf/wf-impl-associated-type-region.stderr
+++ b/src/test/ui/wf/wf-impl-associated-type-region.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | impl<'a, T> Foo<'a> for T {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Bar = &'a T;
-   |     ^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a T` does not outlive the data it points at
-  --> $DIR/wf-impl-associated-type-region.rs:10:5
-   |
-LL |     type Bar = &'a T;
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a T` does not outlive the data it points at
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-in-fn-type-static.stderr b/src/test/ui/wf/wf-in-fn-type-static.stderr
index 7dc8f5a9661..a79c4462477 100644
--- a/src/test/ui/wf/wf-in-fn-type-static.stderr
+++ b/src/test/ui/wf/wf-in-fn-type-static.stderr
@@ -5,13 +5,7 @@ LL | struct Foo<T> {
    |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: 'static
 LL |     x: fn() -> &'static T
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'static T` does not outlive the data it points at
-  --> $DIR/wf-in-fn-type-static.rs:13:5
-   |
-LL |     x: fn() -> &'static T
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
 
 error[E0310]: the parameter type `T` may not live long enough
   --> $DIR/wf-in-fn-type-static.rs:18:5
@@ -20,13 +14,7 @@ LL | struct Bar<T> {
    |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: Copy
 LL |     x: fn(&'static T)
-   |     ^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'static T` does not outlive the data it points at
-  --> $DIR/wf-in-fn-type-static.rs:18:5
-   |
-LL |     x: fn(&'static T)
-   |     ^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-in-obj-type-static.stderr b/src/test/ui/wf/wf-in-obj-type-static.stderr
index 32c3198d55b..c0057f3c829 100644
--- a/src/test/ui/wf/wf-in-obj-type-static.stderr
+++ b/src/test/ui/wf/wf-in-obj-type-static.stderr
@@ -5,13 +5,7 @@ LL | struct Foo<T> {
    |            - help: consider adding an explicit lifetime bound...: `T: 'static`
 LL |     // needs T: 'static
 LL |     x: dyn Object<&'static T>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'static T` does not outlive the data it points at
-  --> $DIR/wf-in-obj-type-static.rs:14:5
-   |
-LL |     x: dyn Object<&'static T>
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'static T` does not outlive the data it points at
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
index 52786fb3bca..4c25ab95939 100644
--- a/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
+++ b/src/test/ui/wf/wf-outlives-ty-in-fn-or-trait.stderr
@@ -4,13 +4,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | impl<'a, T> Trait<'a, T> for usize {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a fn(T);
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a fn(T)` does not outlive the data it points at
-  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:9:5
-   |
-LL |     type Out = &'a fn(T);
-   |     ^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a fn(T)` does not outlive the data it points at
 
 error[E0309]: the parameter type `T` may not live long enough
   --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
@@ -18,13 +12,7 @@ error[E0309]: the parameter type `T` may not live long enough
 LL | impl<'a, T> Trait<'a, T> for u32 {
    |          - help: consider adding an explicit lifetime bound...: `T: 'a`
 LL |     type Out = &'a dyn Baz<T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
-  --> $DIR/wf-outlives-ty-in-fn-or-trait.rs:19:5
-   |
-LL |     type Out = &'a dyn Baz<T>;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the reference type `&'a (dyn Baz<T> + 'a)` does not outlive the data it points at
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/wf/wf-trait-associated-type-region.stderr b/src/test/ui/wf/wf-trait-associated-type-region.stderr
index 9bbfad90cdb..ae681ba6c9b 100644
--- a/src/test/ui/wf/wf-trait-associated-type-region.stderr
+++ b/src/test/ui/wf/wf-trait-associated-type-region.stderr
@@ -5,11 +5,7 @@ LL |     type Type2 = &'a Self::Type1;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider adding an explicit lifetime bound `<Self as SomeTrait<'a>>::Type1: 'a`...
-note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
-  --> $DIR/wf-trait-associated-type-region.rs:9:5
-   |
-LL |     type Type2 = &'a Self::Type1;
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: ...so that the reference type `&'a <Self as SomeTrait<'a>>::Type1` does not outlive the data it points at
 
 error: aborting due to previous error