about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/bootstrap/builder.rs1
-rw-r--r--src/bootstrap/lib.rs36
-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/str/mod.rs7
-rw-r--r--src/libcore/tests/iter.rs36
-rw-r--r--src/libcore/tests/lib.rs1
-rw-r--r--src/libfmt_macros/lib.rs24
-rw-r--r--src/librustc_ast/ast.rs3
-rw-r--r--src/librustc_ast/token.rs56
-rw-r--r--src/librustc_ast/tokenstream.rs125
-rw-r--r--src/librustc_ast_lowering/expr.rs73
-rw-r--r--src/librustc_ast_lowering/item.rs11
-rw-r--r--src/librustc_ast_lowering/pat.rs33
-rw-r--r--src/librustc_builtin_macros/asm.rs10
-rw-r--r--src/librustc_builtin_macros/env.rs1
-rw-r--r--src/librustc_codegen_llvm/asm.rs40
-rw-r--r--src/librustc_codegen_llvm/back/write.rs51
-rw-r--r--src/librustc_codegen_llvm/debuginfo/metadata.rs8
-rw-r--r--src/librustc_codegen_llvm/llvm/ffi.rs9
-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/back/write.rs39
-rw-r--r--src/librustc_codegen_ssa/mir/block.rs15
-rw-r--r--src/librustc_codegen_ssa/traits/asm.rs2
-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_hir/hir.rs1
-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/interface.rs9
-rw-r--r--src/librustc_interface/passes.rs2
-rw-r--r--src/librustc_interface/tests.rs13
-rw-r--r--src/librustc_interface/util.rs8
-rw-r--r--src/librustc_lexer/src/lib.rs37
-rw-r--r--src/librustc_lint/levels.rs21
-rw-r--r--src/librustc_middle/arena.rs2
-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.rs11
-rw-r--r--src/librustc_middle/mir/query.rs14
-rw-r--r--src/librustc_middle/mir/tcx.rs13
-rw-r--r--src/librustc_middle/mir/type_foldable.rs10
-rw-r--r--src/librustc_middle/mir/visit.rs1
-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/invalidation.rs8
-rw-r--r--src/librustc_mir/borrow_check/mod.rs24
-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/dataflow/framework/direction.rs2
-rw-r--r--src/librustc_mir/dataflow/move_paths/builder.rs8
-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.rs4
-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/expr/into.rs3
-rw-r--r--src/librustc_mir_build/build/mod.rs4
-rw-r--r--src/librustc_mir_build/hair/cx/expr.rs3
-rw-r--r--src/librustc_mir_build/hair/mod.rs1
-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.rs10
-rw-r--r--src/librustc_session/lint/builtin.rs7
-rw-r--r--src/librustc_session/options.rs3
-rw-r--r--src/librustc_session/parse.rs4
-rw-r--r--src/librustc_session/session.rs109
-rw-r--r--src/librustc_span/lib.rs12
-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/fuchsia_base.rs7
-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.rs321
-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/clean/inline.rs8
-rw-r--r--src/librustdoc/clean/mod.rs6
-rw-r--r--src/librustdoc/core.rs13
-rw-r--r--src/librustdoc/html/render.rs63
-rw-r--r--src/librustdoc/test.rs2
-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/rustllvm/RustWrapper.cpp31
-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/run-make-fulldeps/profile/Makefile3
-rw-r--r--src/test/ui-fulldeps/lint-pass-macros.rs26
-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/srcloc.rs41
-rw-r--r--src/test/ui/asm/srcloc.stderr74
-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/const-eval/ub-enum.stderr2
-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/extenv/extenv-not-defined-custom.stderr2
-rw-r--r--src/test/ui/extenv/extenv-not-defined-default.stderr2
-rw-r--r--src/test/ui/extenv/issue-55897.stderr2
-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-23458.stderr15
-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/llvm-asm/issue-69092.rs2
-rw-r--r--src/test/ui/llvm-asm/issue-69092.stderr13
-rw-r--r--src/test/ui/macros/macros-nonfatal-errors.stderr2
-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/parser/shebang/shebang-doc-comment.rs6
-rw-r--r--src/test/ui/parser/shebang/shebang-doc-comment.stderr8
-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/fn-trait-notation.fixed19
-rw-r--r--src/test/ui/suggestions/fn-trait-notation.rs19
-rw-r--r--src/test/ui/suggestions/fn-trait-notation.stderr30
-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
322 files changed, 5982 insertions, 2136 deletions
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 5489b1bc66b..c8a85eae252 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -648,6 +648,7 @@ impl<'a> Builder<'a> {
     pub fn sysroot_libdir_relative(&self, compiler: Compiler) -> &Path {
         match self.config.libdir_relative() {
             Some(relative_libdir) if compiler.stage >= 1 => relative_libdir,
+            _ if compiler.stage == 0 => &self.build.initial_libdir,
             _ => Path::new("lib"),
         }
     }
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 15bf831a148..c46c68e4d56 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -243,6 +243,7 @@ pub struct Build {
     initial_rustc: PathBuf,
     initial_cargo: PathBuf,
     initial_lld: PathBuf,
+    initial_libdir: PathBuf,
 
     // Runtime state filled in later on
     // C/C++ compilers and archiver for all targets
@@ -344,18 +345,39 @@ impl Build {
         // we always try to use git for LLVM builds
         let in_tree_llvm_info = channel::GitInfo::new(false, &src.join("src/llvm-project"));
 
-        let initial_sysroot = config.initial_rustc.parent().unwrap().parent().unwrap();
-        let initial_lld = initial_sysroot
-            .join("lib")
-            .join("rustlib")
-            .join(config.build)
-            .join("bin")
-            .join("rust-lld");
+        let initial_target_libdir_str = if config.dry_run {
+            "/dummy/lib/path/to/lib/".to_string()
+        } else {
+            output(
+                Command::new(&config.initial_rustc)
+                    .arg("--target")
+                    .arg(config.build)
+                    .arg("--print")
+                    .arg("target-libdir"),
+            )
+        };
+        let initial_target_dir = Path::new(&initial_target_libdir_str).parent().unwrap();
+        let initial_lld = initial_target_dir.join("bin").join("rust-lld");
+
+        let initial_sysroot = if config.dry_run {
+            "/dummy".to_string()
+        } else {
+            output(Command::new(&config.initial_rustc).arg("--print").arg("sysroot"))
+        };
+        let initial_libdir = initial_target_dir
+            .parent()
+            .unwrap()
+            .parent()
+            .unwrap()
+            .strip_prefix(initial_sysroot.trim())
+            .unwrap()
+            .to_path_buf();
 
         let mut build = Build {
             initial_rustc: config.initial_rustc.clone(),
             initial_cargo: config.initial_cargo.clone(),
             initial_lld,
+            initial_libdir,
             local_rebuild: config.local_rebuild,
             fail_fast: config.cmd.fail_fast(),
             doc_tests: config.cmd.doc_tests(),
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/str/mod.rs b/src/libcore/str/mod.rs
index b514e0f6d9c..316c2cd55ac 100644
--- a/src/libcore/str/mod.rs
+++ b/src/libcore/str/mod.rs
@@ -2270,12 +2270,11 @@ impl str {
         self.len() == 0
     }
 
-    /// Checks that `index`-th byte lies at the start and/or end of a
-    /// UTF-8 code point sequence.
+    /// Checks that `index`-th byte is the first byte in a UTF-8 code point
+    /// sequence or the end of the string.
     ///
     /// The start and end of the string (when `index == self.len()`) are
-    /// considered to be
-    /// boundaries.
+    /// considered to be boundaries.
     ///
     /// Returns `false` if `index` is greater than `self.len()`.
     ///
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/libfmt_macros/lib.rs b/src/libfmt_macros/lib.rs
index 677c027f17b..23bf7b35419 100644
--- a/src/libfmt_macros/lib.rs
+++ b/src/libfmt_macros/lib.rs
@@ -191,6 +191,11 @@ pub struct Parser<'a> {
     append_newline: bool,
     /// Whether this formatting string is a literal or it comes from a macro.
     is_literal: bool,
+    /// Start position of the current line.
+    cur_line_start: usize,
+    /// Start and end byte offset of every line of the format string. Excludes
+    /// newline characters and leading whitespace.
+    pub line_spans: Vec<InnerSpan>,
 }
 
 impl<'a> Iterator for Parser<'a> {
@@ -235,10 +240,15 @@ impl<'a> Iterator for Parser<'a> {
                         None
                     }
                 }
-                '\n' => Some(String(self.string(pos))),
                 _ => Some(String(self.string(pos))),
             }
         } else {
+            if self.is_literal && self.cur_line_start != self.input.len() {
+                let start = self.to_span_index(self.cur_line_start);
+                let end = self.to_span_index(self.input.len());
+                self.line_spans.push(start.to(end));
+                self.cur_line_start = self.input.len();
+            }
             None
         }
     }
@@ -266,6 +276,8 @@ impl<'a> Parser<'a> {
             last_opening_brace: None,
             append_newline,
             is_literal,
+            cur_line_start: 0,
+            line_spans: vec![],
         }
     }
 
@@ -433,7 +445,17 @@ impl<'a> Parser<'a> {
                 '{' | '}' => {
                     return &self.input[start..pos];
                 }
+                '\n' if self.is_literal => {
+                    let start = self.to_span_index(self.cur_line_start);
+                    let end = self.to_span_index(pos);
+                    self.line_spans.push(start.to(end));
+                    self.cur_line_start = pos + 1;
+                    self.cur.next();
+                }
                 _ => {
+                    if self.is_literal && pos == self.cur_line_start && c.is_whitespace() {
+                        self.cur_line_start = pos + c.len_utf8();
+                    }
                     self.cur.next();
                 }
             }
diff --git a/src/librustc_ast/ast.rs b/src/librustc_ast/ast.rs
index 30bb5c0bffa..efcf95ec706 100644
--- a/src/librustc_ast/ast.rs
+++ b/src/librustc_ast/ast.rs
@@ -1252,7 +1252,7 @@ pub enum ExprKind {
     Ret(Option<P<Expr>>),
 
     /// Output of the `asm!()` macro.
-    InlineAsm(InlineAsm),
+    InlineAsm(P<InlineAsm>),
     /// Output of the `llvm_asm!()` macro.
     LlvmInlineAsm(P<LlvmInlineAsm>),
 
@@ -1971,6 +1971,7 @@ pub struct InlineAsm {
     pub template: Vec<InlineAsmTemplatePiece>,
     pub operands: Vec<(InlineAsmOperand, Span)>,
     pub options: InlineAsmOptions,
+    pub line_spans: Vec<Span>,
 }
 
 /// Inline assembly dialect.
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 5bcd111706f..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,
@@ -1265,7 +1267,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
 
         let operands = self.arena.alloc_from_iter(operands);
         let template = self.arena.alloc_from_iter(asm.template.iter().cloned());
-        let hir_asm = hir::InlineAsm { template, operands, options: asm.options };
+        let line_spans = self.arena.alloc_slice(&asm.line_spans[..]);
+        let hir_asm = hir::InlineAsm { template, operands, options: asm.options, line_spans };
         hir::ExprKind::InlineAsm(self.arena.alloc(hir_asm))
     }
 
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_builtin_macros/asm.rs b/src/librustc_builtin_macros/asm.rs
index 224b52b239f..19fae635572 100644
--- a/src/librustc_builtin_macros/asm.rs
+++ b/src/librustc_builtin_macros/asm.rs
@@ -513,10 +513,16 @@ fn expand_preparsed_asm(ecx: &mut ExtCtxt<'_>, sp: Span, args: AsmArgs) -> P<ast
         }
     }
 
-    let inline_asm = ast::InlineAsm { template, operands, options: args.options };
+    let line_spans = if parser.line_spans.is_empty() {
+        vec![template_sp]
+    } else {
+        parser.line_spans.iter().map(|span| template_span.from_inner(*span)).collect()
+    };
+
+    let inline_asm = ast::InlineAsm { template, operands, options: args.options, line_spans };
     P(ast::Expr {
         id: ast::DUMMY_NODE_ID,
-        kind: ast::ExprKind::InlineAsm(inline_asm),
+        kind: ast::ExprKind::InlineAsm(P(inline_asm)),
         span: sp,
         attrs: ast::AttrVec::new(),
         tokens: None,
diff --git a/src/librustc_builtin_macros/env.rs b/src/librustc_builtin_macros/env.rs
index 21e1889513b..d769ebb1f55 100644
--- a/src/librustc_builtin_macros/env.rs
+++ b/src/librustc_builtin_macros/env.rs
@@ -77,6 +77,7 @@ pub fn expand_env<'cx>(
         return DummyResult::any(sp);
     }
 
+    let sp = cx.with_def_site_ctxt(sp);
     let e = match env::var(&*var.as_str()) {
         Err(_) => {
             cx.span_err(sp, &msg.as_str());
diff --git a/src/librustc_codegen_llvm/asm.rs b/src/librustc_codegen_llvm/asm.rs
index 8986ab322c0..9d4a30f23a2 100644
--- a/src/librustc_codegen_llvm/asm.rs
+++ b/src/librustc_codegen_llvm/asm.rs
@@ -14,7 +14,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_hir as hir;
 use rustc_middle::span_bug;
 use rustc_middle::ty::layout::TyAndLayout;
-use rustc_span::Span;
+use rustc_span::{Pos, Span};
 use rustc_target::abi::*;
 use rustc_target::asm::*;
 
@@ -97,7 +97,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             ia.volatile,
             ia.alignstack,
             ia.dialect,
-            span,
+            &[span],
         );
         if r.is_none() {
             return false;
@@ -119,7 +119,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
         template: &[InlineAsmTemplatePiece],
         operands: &[InlineAsmOperandRef<'tcx, Self>],
         options: InlineAsmOptions,
-        span: Span,
+        line_spans: &[Span],
     ) {
         let asm_arch = self.tcx.sess.asm_arch.unwrap();
 
@@ -254,6 +254,7 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
                     ]);
                 }
                 InlineAsmArch::RiscV32 | InlineAsmArch::RiscV64 => {}
+                InlineAsmArch::Nvptx64 => {}
             }
         }
         if !options.contains(InlineAsmOptions::NOMEM) {
@@ -286,9 +287,9 @@ impl AsmBuilderMethods<'tcx> for Builder<'a, 'll, 'tcx> {
             volatile,
             alignstack,
             dialect,
-            span,
+            line_spans,
         )
-        .unwrap_or_else(|| span_bug!(span, "LLVM asm constraint validation failed"));
+        .unwrap_or_else(|| span_bug!(line_spans[0], "LLVM asm constraint validation failed"));
 
         if options.contains(InlineAsmOptions::PURE) {
             if options.contains(InlineAsmOptions::NOMEM) {
@@ -340,7 +341,7 @@ fn inline_asm_call(
     volatile: bool,
     alignstack: bool,
     dia: LlvmAsmDialect,
-    span: Span,
+    line_spans: &[Span],
 ) -> Option<&'ll Value> {
     let volatile = if volatile { llvm::True } else { llvm::False };
     let alignstack = if alignstack { llvm::True } else { llvm::False };
@@ -381,8 +382,24 @@ fn inline_asm_call(
                 key.len() as c_uint,
             );
 
-            let val: &'ll Value = bx.const_i32(span.ctxt().outer_expn().as_u32() as i32);
-            llvm::LLVMSetMetadata(call, kind, llvm::LLVMMDNodeInContext(bx.llcx, &val, 1));
+            // srcloc contains one integer for each line of assembly code.
+            // Unfortunately this isn't enough to encode a full span so instead
+            // we just encode the start position of each line.
+            // FIXME: Figure out a way to pass the entire line spans.
+            let mut srcloc = vec![];
+            if dia == LlvmAsmDialect::Intel && line_spans.len() > 1 {
+                // LLVM inserts an extra line to add the ".intel_syntax", so add
+                // a dummy srcloc entry for it.
+                //
+                // Don't do this if we only have 1 line span since that may be
+                // due to the asm template string coming from a macro. LLVM will
+                // default to the first srcloc for lines that don't have an
+                // associated srcloc.
+                srcloc.push(bx.const_i32(0));
+            }
+            srcloc.extend(line_spans.iter().map(|span| bx.const_i32(span.lo().to_u32() as i32)));
+            let md = llvm::LLVMMDNodeInContext(bx.llcx, srcloc.as_ptr(), srcloc.len() as u32);
+            llvm::LLVMSetMetadata(call, kind, md);
 
             Some(call)
         } else {
@@ -410,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",
@@ -452,6 +472,7 @@ fn modifier_to_llvm(
                 modifier
             }
         }
+        InlineAsmRegClass::Nvptx(_) => None,
         InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::reg)
         | InlineAsmRegClass::RiscV(RiscVInlineAsmRegClass::freg) => None,
         InlineAsmRegClass::X86(X86InlineAsmRegClass::reg)
@@ -502,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_llvm/back/write.rs b/src/librustc_codegen_llvm/back/write.rs
index 57e018bba6a..02a9294930d 100644
--- a/src/librustc_codegen_llvm/back/write.rs
+++ b/src/librustc_codegen_llvm/back/write.rs
@@ -23,6 +23,7 @@ use rustc_middle::bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::config::{self, Lto, OutputType, Passes, Sanitizer, SwitchWithOptPath};
 use rustc_session::Session;
+use rustc_span::InnerSpan;
 use rustc_target::spec::{CodeModel, RelocModel};
 
 use libc::{c_char, c_int, c_uint, c_void, size_t};
@@ -238,12 +239,19 @@ impl<'a> Drop for DiagnosticHandlers<'a> {
     }
 }
 
-unsafe extern "C" fn report_inline_asm(
+fn report_inline_asm(
     cgcx: &CodegenContext<LlvmCodegenBackend>,
-    msg: &str,
-    cookie: c_uint,
+    msg: String,
+    mut cookie: c_uint,
+    source: Option<(String, Vec<InnerSpan>)>,
 ) {
-    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg.to_owned());
+    // In LTO build we may get srcloc values from other crates which are invalid
+    // since they use a different source map. To be safe we just suppress these
+    // in LTO builds.
+    if matches!(cgcx.lto, Lto::Fat | Lto::Thin) {
+        cookie = 0;
+    }
+    cgcx.diag_emitter.inline_asm_error(cookie as u32, msg, source);
 }
 
 unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void, cookie: c_uint) {
@@ -252,10 +260,37 @@ unsafe extern "C" fn inline_asm_handler(diag: &SMDiagnostic, user: *const c_void
     }
     let (cgcx, _) = *(user as *const (&CodegenContext<LlvmCodegenBackend>, &Handler));
 
-    let msg = llvm::build_string(|s| llvm::LLVMRustWriteSMDiagnosticToString(diag, s))
-        .expect("non-UTF8 SMDiagnostic");
+    // Recover the post-substitution assembly code from LLVM for better
+    // diagnostics.
+    let mut have_source = false;
+    let mut buffer = String::new();
+    let mut loc = 0;
+    let mut ranges = [0; 8];
+    let mut num_ranges = ranges.len() / 2;
+    let msg = llvm::build_string(|msg| {
+        buffer = llvm::build_string(|buffer| {
+            have_source = llvm::LLVMRustUnpackSMDiagnostic(
+                diag,
+                msg,
+                buffer,
+                &mut loc,
+                ranges.as_mut_ptr(),
+                &mut num_ranges,
+            );
+        })
+        .expect("non-UTF8 inline asm");
+    })
+    .expect("non-UTF8 SMDiagnostic");
+
+    let source = have_source.then(|| {
+        let mut spans = vec![InnerSpan::new(loc as usize, loc as usize)];
+        for i in 0..num_ranges {
+            spans.push(InnerSpan::new(ranges[i * 2] as usize, ranges[i * 2 + 1] as usize));
+        }
+        (buffer, spans)
+    });
 
-    report_inline_asm(cgcx, &msg, cookie);
+    report_inline_asm(cgcx, msg, cookie, source);
 }
 
 unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void) {
@@ -266,7 +301,7 @@ unsafe extern "C" fn diagnostic_handler(info: &DiagnosticInfo, user: *mut c_void
 
     match llvm::diagnostic::Diagnostic::unpack(info) {
         llvm::diagnostic::InlineAsm(inline) => {
-            report_inline_asm(cgcx, &llvm::twine_to_string(inline.message), inline.cookie);
+            report_inline_asm(cgcx, llvm::twine_to_string(inline.message), inline.cookie, None);
         }
 
         llvm::diagnostic::Optimization(opt) => {
diff --git a/src/librustc_codegen_llvm/debuginfo/metadata.rs b/src/librustc_codegen_llvm/debuginfo/metadata.rs
index 0cce0b25e58..333eb805221 100644
--- a/src/librustc_codegen_llvm/debuginfo/metadata.rs
+++ b/src/librustc_codegen_llvm/debuginfo/metadata.rs
@@ -959,16 +959,16 @@ pub fn compile_unit_metadata(
         if tcx.sess.opts.debugging_opts.profile {
             let cu_desc_metadata =
                 llvm::LLVMRustMetadataAsValue(debug_context.llcontext, unit_metadata);
+            let default_gcda_path = &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda");
+            let gcda_path =
+                tcx.sess.opts.debugging_opts.profile_emit.as_ref().unwrap_or(default_gcda_path);
 
             let gcov_cu_info = [
                 path_to_mdstring(
                     debug_context.llcontext,
                     &tcx.output_filenames(LOCAL_CRATE).with_extension("gcno"),
                 ),
-                path_to_mdstring(
-                    debug_context.llcontext,
-                    &tcx.output_filenames(LOCAL_CRATE).with_extension("gcda"),
-                ),
+                path_to_mdstring(debug_context.llcontext, &gcda_path),
                 cu_desc_metadata,
             ];
             let gcov_metadata = llvm::LLVMMDNodeInContext(
diff --git a/src/librustc_codegen_llvm/llvm/ffi.rs b/src/librustc_codegen_llvm/llvm/ffi.rs
index 3fb7ff3cb8d..759c2bf1b85 100644
--- a/src/librustc_codegen_llvm/llvm/ffi.rs
+++ b/src/librustc_codegen_llvm/llvm/ffi.rs
@@ -2070,7 +2070,14 @@ extern "C" {
     );
 
     #[allow(improper_ctypes)]
-    pub fn LLVMRustWriteSMDiagnosticToString(d: &SMDiagnostic, s: &RustString);
+    pub fn LLVMRustUnpackSMDiagnostic(
+        d: &SMDiagnostic,
+        message_out: &RustString,
+        buffer_out: &RustString,
+        loc_out: &mut c_uint,
+        ranges_out: *mut c_uint,
+        num_ranges: &mut usize,
+    ) -> bool;
 
     pub fn LLVMRustWriteArchive(
         Dst: *const c_char,
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/back/write.rs b/src/librustc_codegen_ssa/back/write.rs
index 9e03c283cfb..cb5c95c11fa 100644
--- a/src/librustc_codegen_ssa/back/write.rs
+++ b/src/librustc_codegen_ssa/back/write.rs
@@ -31,9 +31,9 @@ use rustc_session::cgu_reuse_tracker::CguReuseTracker;
 use rustc_session::config::{self, CrateType, Lto, OutputFilenames, OutputType};
 use rustc_session::config::{Passes, Sanitizer, SwitchWithOptPath};
 use rustc_session::Session;
-use rustc_span::hygiene::ExpnId;
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{sym, Symbol};
+use rustc_span::{BytePos, FileName, InnerSpan, Pos, Span};
 use rustc_target::spec::{MergeFunctions, PanicStrategy};
 
 use std::any::Any;
@@ -1551,7 +1551,7 @@ fn spawn_work<B: ExtraBackendMethods>(cgcx: CodegenContext<B>, work: WorkItem<B>
 
 enum SharedEmitterMessage {
     Diagnostic(Diagnostic),
-    InlineAsmError(u32, String),
+    InlineAsmError(u32, String, Option<(String, Vec<InnerSpan>)>),
     AbortIfErrors,
     Fatal(String),
 }
@@ -1572,8 +1572,13 @@ impl SharedEmitter {
         (SharedEmitter { sender }, SharedEmitterMain { receiver })
     }
 
-    pub fn inline_asm_error(&self, cookie: u32, msg: String) {
-        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg)));
+    pub fn inline_asm_error(
+        &self,
+        cookie: u32,
+        msg: String,
+        source: Option<(String, Vec<InnerSpan>)>,
+    ) {
+        drop(self.sender.send(SharedEmitterMessage::InlineAsmError(cookie, msg, source)));
     }
 
     pub fn fatal(&self, msg: &str) {
@@ -1626,8 +1631,30 @@ impl SharedEmitterMain {
                     }
                     handler.emit_diagnostic(&d);
                 }
-                Ok(SharedEmitterMessage::InlineAsmError(cookie, msg)) => {
-                    sess.span_err(ExpnId::from_u32(cookie).expn_data().call_site, &msg)
+                Ok(SharedEmitterMessage::InlineAsmError(cookie, msg, source)) => {
+                    let msg = msg.strip_prefix("error: ").unwrap_or(&msg);
+
+                    // If the cookie is 0 then we don't have span information.
+                    let mut err = if cookie == 0 {
+                        sess.struct_err(&msg)
+                    } else {
+                        let pos = BytePos::from_u32(cookie);
+                        let span = Span::with_root_ctxt(pos, pos);
+                        sess.struct_span_err(span, &msg)
+                    };
+
+                    // Point to the generated assembly if it is available.
+                    if let Some((buffer, spans)) = source {
+                        let source = sess
+                            .source_map()
+                            .new_source_file(FileName::inline_asm_source_code(&buffer), buffer);
+                        let source_span = Span::with_root_ctxt(source.start_pos, source.end_pos);
+                        let spans: Vec<_> =
+                            spans.iter().map(|sp| source_span.from_inner(*sp)).collect();
+                        err.span_note(spans, "instantiated into assembly here");
+                    }
+
+                    err.emit();
                 }
                 Ok(SharedEmitterMessage::AbortIfErrors) => {
                     sess.abort_if_errors();
diff --git a/src/librustc_codegen_ssa/mir/block.rs b/src/librustc_codegen_ssa/mir/block.rs
index b487ed8dea8..6c18e753d79 100644
--- a/src/librustc_codegen_ssa/mir/block.rs
+++ b/src/librustc_codegen_ssa/mir/block.rs
@@ -831,6 +831,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         template: &[ast::InlineAsmTemplatePiece],
         operands: &[mir::InlineAsmOperand<'tcx>],
         options: ast::InlineAsmOptions,
+        line_spans: &[Span],
         destination: Option<mir::BasicBlock>,
     ) {
         let span = terminator.source_info.span;
@@ -908,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 {
@@ -931,7 +931,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             })
             .collect();
 
-        bx.codegen_inline_asm(template, &operands, options, span);
+        bx.codegen_inline_asm(template, &operands, options, line_spans);
 
         if let Some(target) = destination {
             helper.funclet_br(self, &mut bx, target);
@@ -1034,7 +1034,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bug!("borrowck false edges in codegen")
             }
 
-            mir::TerminatorKind::InlineAsm { template, ref operands, options, destination } => {
+            mir::TerminatorKind::InlineAsm {
+                template,
+                ref operands,
+                options,
+                line_spans,
+                destination,
+            } => {
                 self.codegen_asm_terminator(
                     helper,
                     bx,
@@ -1042,6 +1048,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     template,
                     operands,
                     options,
+                    line_spans,
                     destination,
                 );
             }
diff --git a/src/librustc_codegen_ssa/traits/asm.rs b/src/librustc_codegen_ssa/traits/asm.rs
index 0abfdfde780..b6b57744f95 100644
--- a/src/librustc_codegen_ssa/traits/asm.rs
+++ b/src/librustc_codegen_ssa/traits/asm.rs
@@ -52,7 +52,7 @@ pub trait AsmBuilderMethods<'tcx>: BackendTypes {
         template: &[InlineAsmTemplatePiece],
         operands: &[InlineAsmOperandRef<'tcx, Self>],
         options: InlineAsmOptions,
-        span: Span,
+        line_spans: &[Span],
     );
 }
 
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_hir/hir.rs b/src/librustc_hir/hir.rs
index 35cff668581..0194dc9f90b 100644
--- a/src/librustc_hir/hir.rs
+++ b/src/librustc_hir/hir.rs
@@ -2106,6 +2106,7 @@ pub struct InlineAsm<'hir> {
     pub template: &'hir [InlineAsmTemplatePiece],
     pub operands: &'hir [InlineAsmOperand<'hir>],
     pub options: InlineAsmOptions,
+    pub line_spans: &'hir [Span],
 }
 
 #[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, HashStable_Generic, PartialEq)]
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/interface.rs b/src/librustc_interface/interface.rs
index 55f825e150e..f127a239eea 100644
--- a/src/librustc_interface/interface.rs
+++ b/src/librustc_interface/interface.rs
@@ -18,7 +18,7 @@ use rustc_session::lint;
 use rustc_session::parse::{CrateConfig, ParseSess};
 use rustc_session::{DiagnosticOutput, Session};
 use rustc_span::edition;
-use rustc_span::source_map::{FileLoader, FileName, SourceMap};
+use rustc_span::source_map::{FileLoader, FileName};
 use std::path::PathBuf;
 use std::result;
 use std::sync::{Arc, Mutex};
@@ -31,7 +31,6 @@ pub type Result<T> = result::Result<T, ErrorReported>;
 pub struct Compiler {
     pub(crate) sess: Lrc<Session>,
     codegen_backend: Lrc<Box<dyn CodegenBackend>>,
-    source_map: Lrc<SourceMap>,
     pub(crate) input: Input,
     pub(crate) input_path: Option<PathBuf>,
     pub(crate) output_dir: Option<PathBuf>,
@@ -49,9 +48,6 @@ impl Compiler {
     pub fn codegen_backend(&self) -> &Lrc<Box<dyn CodegenBackend>> {
         &self.codegen_backend
     }
-    pub fn source_map(&self) -> &Lrc<SourceMap> {
-        &self.source_map
-    }
     pub fn input(&self) -> &Input {
         &self.input
     }
@@ -168,7 +164,7 @@ pub fn run_compiler_in_existing_thread_pool<R>(
     f: impl FnOnce(&Compiler) -> R,
 ) -> R {
     let registry = &config.registry;
-    let (sess, codegen_backend, source_map) = util::create_session(
+    let (sess, codegen_backend) = util::create_session(
         config.opts,
         config.crate_cfg,
         config.diagnostic_output,
@@ -181,7 +177,6 @@ pub fn run_compiler_in_existing_thread_pool<R>(
     let compiler = Compiler {
         sess,
         codegen_backend,
-        source_map,
         input: config.input,
         input_path: config.input_path,
         output_dir: config.output_dir,
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_interface/tests.rs b/src/librustc_interface/tests.rs
index d573e11fc4b..18cbea858d4 100644
--- a/src/librustc_interface/tests.rs
+++ b/src/librustc_interface/tests.rs
@@ -7,11 +7,10 @@ use rustc_session::config::{build_configuration, build_session_options, to_crate
 use rustc_session::config::{rustc_optgroups, ErrorOutputType, ExternLocation, Options, Passes};
 use rustc_session::config::{CFGuard, ExternEntry, LinkerPluginLto, LtoCli, SwitchWithOptPath};
 use rustc_session::config::{Externs, OutputType, OutputTypes, Sanitizer, SymbolManglingVersion};
-use rustc_session::getopts;
 use rustc_session::lint::Level;
 use rustc_session::search_paths::SearchPath;
 use rustc_session::utils::NativeLibKind;
-use rustc_session::{build_session, Session};
+use rustc_session::{build_session, getopts, DiagnosticOutput, Session};
 use rustc_span::edition::{Edition, DEFAULT_EDITION};
 use rustc_span::symbol::sym;
 use rustc_span::SourceFileHashAlgorithm;
@@ -32,7 +31,14 @@ fn build_session_options_and_crate_config(matches: getopts::Matches) -> (Options
 fn mk_session(matches: getopts::Matches) -> (Session, CfgSpecs) {
     let registry = registry::Registry::new(&[]);
     let (sessopts, cfg) = build_session_options_and_crate_config(matches);
-    let sess = build_session(sessopts, None, registry);
+    let sess = build_session(
+        sessopts,
+        None,
+        registry,
+        DiagnosticOutput::Default,
+        Default::default(),
+        None,
+    );
     (sess, cfg)
 }
 
@@ -557,6 +563,7 @@ fn test_debugging_options_tracking_hash() {
     tracked!(plt, Some(true));
     tracked!(print_fuel, Some("abc".to_string()));
     tracked!(profile, true);
+    tracked!(profile_emit, Some(PathBuf::from("abc")));
     tracked!(relro_level, Some(RelroLevel::Full));
     tracked!(report_delayed_bugs, true);
     tracked!(run_dsymutil, false);
diff --git a/src/librustc_interface/util.rs b/src/librustc_interface/util.rs
index 7eaaff05fb5..924908e5724 100644
--- a/src/librustc_interface/util.rs
+++ b/src/librustc_interface/util.rs
@@ -23,7 +23,7 @@ use rustc_session::parse::CrateConfig;
 use rustc_session::CrateDisambiguator;
 use rustc_session::{early_error, filesearch, output, DiagnosticOutput, Session};
 use rustc_span::edition::Edition;
-use rustc_span::source_map::{FileLoader, SourceMap};
+use rustc_span::source_map::FileLoader;
 use rustc_span::symbol::{sym, Symbol};
 use smallvec::SmallVec;
 use std::env;
@@ -65,8 +65,8 @@ pub fn create_session(
     input_path: Option<PathBuf>,
     lint_caps: FxHashMap<lint::LintId, lint::Level>,
     descriptions: Registry,
-) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>, Lrc<SourceMap>) {
-    let (mut sess, source_map) = session::build_session_with_source_map(
+) -> (Lrc<Session>, Lrc<Box<dyn CodegenBackend>>) {
+    let mut sess = session::build_session(
         sopts,
         input_path,
         descriptions,
@@ -81,7 +81,7 @@ pub fn create_session(
     add_configuration(&mut cfg, &mut sess, &*codegen_backend);
     sess.parse_sess.config = cfg;
 
-    (Lrc::new(sess), Lrc::new(codegen_backend), source_map)
+    (Lrc::new(sess), Lrc::new(codegen_backend))
 }
 
 const STACK_SIZE: usize = 8 * 1024 * 1024;
diff --git a/src/librustc_lexer/src/lib.rs b/src/librustc_lexer/src/lib.rs
index fe6785de009..c2139d07f37 100644
--- a/src/librustc_lexer/src/lib.rs
+++ b/src/librustc_lexer/src/lib.rs
@@ -238,26 +238,25 @@ pub enum Base {
 /// `rustc` allows files to have a shebang, e.g. "#!/usr/bin/rustrun",
 /// but shebang isn't a part of rust syntax.
 pub fn strip_shebang(input: &str) -> Option<usize> {
-    let first_line = input.lines().next()?;
-    // A shebang is intentionally loosely defined as `#! [non whitespace]` on the first line.
-    let could_be_shebang =
-        first_line.starts_with("#!") && first_line[2..].contains(|c| !is_whitespace(c));
-    if !could_be_shebang {
-        return None;
-    }
-    let non_whitespace_tokens = tokenize(input).map(|tok| tok.kind).filter(|tok|
-        !matches!(tok, TokenKind::LineComment | TokenKind::BlockComment { .. } | TokenKind::Whitespace)
-    );
-    let prefix = [TokenKind::Pound, TokenKind::Not, TokenKind::OpenBracket];
-    let starts_with_attribute = non_whitespace_tokens.take(3).eq(prefix.iter().copied());
-    if starts_with_attribute {
-        // If the file starts with #![ then it's definitely not a shebang -- it couldn't be
-        // a rust program since a Rust program can't start with `[`
-        None
-    } else {
-        // It's a #!... and there isn't a `[` in sight, must be a shebang
-        Some(first_line.len())
+    // Shebang must start with `#!` literally, without any preceding whitespace.
+    if input.starts_with("#!") {
+        let input_tail = &input[2..];
+        // Shebang must have something non-whitespace after `#!` on the first line.
+        let first_line_tail = input_tail.lines().next()?;
+        if first_line_tail.contains(|c| !is_whitespace(c)) {
+            // Ok, this is a shebang but if the next non-whitespace token is `[` or maybe
+            // a doc comment (due to `TokenKind::(Line,Block)Comment` ambiguity at lexer level),
+            // then it may be valid Rust code, so consider it Rust code.
+            let next_non_whitespace_token = tokenize(input_tail).map(|tok| tok.kind).filter(|tok|
+                !matches!(tok, TokenKind::Whitespace | TokenKind::LineComment | TokenKind::BlockComment { .. })
+            ).next();
+            if next_non_whitespace_token != Some(TokenKind::OpenBracket) {
+                // No other choice than to consider this a shebang.
+                return Some(2 + first_line_tail.len());
+            }
+        }
     }
+    None
 }
 
 /// Parses the first token from the provided input string.
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/arena.rs b/src/librustc_middle/arena.rs
index 9b9207312e8..d5212ec5c30 100644
--- a/src/librustc_middle/arena.rs
+++ b/src/librustc_middle/arena.rs
@@ -82,6 +82,8 @@ macro_rules! arena_types {
             // (during lowering) and the `librustc_middle` arena (for decoding MIR)
             [decode] asm_template: rustc_ast::ast::InlineAsmTemplatePiece,
 
+            // This is used to decode the &'tcx [Span] for InlineAsm's line_spans.
+            [decode] span: rustc_span::Span,
         ], $tcx);
     )
 }
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 47cfa62abb1..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.
@@ -1193,6 +1194,10 @@ pub enum TerminatorKind<'tcx> {
         /// Miscellaneous options for the inline assembly.
         options: InlineAsmOptions,
 
+        /// Source spans for each line of the inline assembly code. These are
+        /// used to map assembler errors back to the line in the source code.
+        line_spans: &'tcx [Span],
+
         /// Destination block after the inline assembly returns, unless it is
         /// diverging (InlineAsmOptions::NORETURN).
         destination: Option<BasicBlock>,
@@ -1595,7 +1600,7 @@ impl<'tcx> TerminatorKind<'tcx> {
             }
             FalseEdges { .. } => write!(fmt, "falseEdges"),
             FalseUnwind { .. } => write!(fmt, "falseUnwind"),
-            InlineAsm { template, ref operands, options, destination: _ } => {
+            InlineAsm { template, ref operands, options, .. } => {
                 write!(fmt, "asm!(\"{}\"", InlineAsmTemplatePiece::to_string(template))?;
                 for op in operands {
                     write!(fmt, ", ")?;
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/mir/type_foldable.rs b/src/librustc_middle/mir/type_foldable.rs
index bb7001c1207..b0207b469fa 100644
--- a/src/librustc_middle/mir/type_foldable.rs
+++ b/src/librustc_middle/mir/type_foldable.rs
@@ -78,9 +78,13 @@ impl<'tcx> TypeFoldable<'tcx> for Terminator<'tcx> {
                 FalseEdges { real_target, imaginary_target }
             }
             FalseUnwind { real_target, unwind } => FalseUnwind { real_target, unwind },
-            InlineAsm { template, ref operands, options, destination } => {
-                InlineAsm { template, operands: operands.fold_with(folder), options, destination }
-            }
+            InlineAsm { template, ref operands, options, line_spans, destination } => InlineAsm {
+                template,
+                operands: operands.fold_with(folder),
+                options,
+                line_spans,
+                destination,
+            },
         };
         Terminator { source_info: self.source_info, kind }
     }
diff --git a/src/librustc_middle/mir/visit.rs b/src/librustc_middle/mir/visit.rs
index a29b7b75294..035e6e55a97 100644
--- a/src/librustc_middle/mir/visit.rs
+++ b/src/librustc_middle/mir/visit.rs
@@ -535,6 +535,7 @@ macro_rules! make_mir_visitor {
                         template: _,
                         operands,
                         options: _,
+                        line_spans: _,
                         destination: _,
                     } => {
                         for op in operands {
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/invalidation.rs b/src/librustc_mir/borrow_check/invalidation.rs
index 178e3db17cd..0b59e29b66c 100644
--- a/src/librustc_mir/borrow_check/invalidation.rs
+++ b/src/librustc_mir/borrow_check/invalidation.rs
@@ -183,7 +183,13 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                     }
                 }
             }
-            TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => {
+            TerminatorKind::InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination: _,
+            } => {
                 for op in operands {
                     match *op {
                         InlineAsmOperand::In { reg: _, ref value }
diff --git a/src/librustc_mir/borrow_check/mod.rs b/src/librustc_mir/borrow_check/mod.rs
index a0c1d96bb47..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
@@ -724,7 +722,13 @@ impl<'cx, 'tcx> dataflow::ResultsVisitor<'cx, 'tcx> for MirBorrowckCtxt<'cx, 'tc
                 self.mutate_place(loc, (resume_arg, span), Deep, JustWrite, flow_state);
             }
 
-            TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => {
+            TerminatorKind::InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination: _,
+            } => {
                 for op in operands {
                     match *op {
                         InlineAsmOperand::In { reg: _, ref value }
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/dataflow/framework/direction.rs b/src/librustc_mir/dataflow/framework/direction.rs
index 97b14ea771b..9e2a28853e1 100644
--- a/src/librustc_mir/dataflow/framework/direction.rs
+++ b/src/librustc_mir/dataflow/framework/direction.rs
@@ -482,7 +482,7 @@ impl Direction for Forward {
                 }
             }
 
-            InlineAsm { template: _, operands: _, options: _, destination } => {
+            InlineAsm { template: _, operands: _, options: _, line_spans: _, destination } => {
                 if let Some(target) = destination {
                     propagate(target, exit_state);
                 }
diff --git a/src/librustc_mir/dataflow/move_paths/builder.rs b/src/librustc_mir/dataflow/move_paths/builder.rs
index 427ab1ca5cd..e35d853c928 100644
--- a/src/librustc_mir/dataflow/move_paths/builder.rs
+++ b/src/librustc_mir/dataflow/move_paths/builder.rs
@@ -411,7 +411,13 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
                     self.gather_init(destination.as_ref(), InitKind::NonPanicPathOnly);
                 }
             }
-            TerminatorKind::InlineAsm { template: _, ref operands, options: _, destination: _ } => {
+            TerminatorKind::InlineAsm {
+                template: _,
+                ref operands,
+                options: _,
+                line_spans: _,
+                destination: _
+            } => {
                 for op in operands {
                     match *op {
                         InlineAsmOperand::In { reg: _, ref value }
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..d5f4a63baaa 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) {
@@ -485,7 +485,7 @@ impl<'rt, 'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> ValidityVisitor<'rt, 'mir, '
                 try_validation!(
                     value.to_char(),
                     self.path,
-                    err_ub!(InvalidChar(..)) => { "{}", value } expected { "a valid unicode codepoint" },
+                    err_ub!(InvalidChar(..)) => { "{}", value } expected { "a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)" },
                 );
                 Ok(true)
             }
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/expr/into.rs b/src/librustc_mir_build/build/expr/into.rs
index ff3c7ee3ee8..e7733deee4d 100644
--- a/src/librustc_mir_build/build/expr/into.rs
+++ b/src/librustc_mir_build/build/expr/into.rs
@@ -310,7 +310,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 );
                 block.unit()
             }
-            ExprKind::InlineAsm { template, operands, options } => {
+            ExprKind::InlineAsm { template, operands, options, line_spans } => {
                 use crate::hair;
                 use rustc_middle::mir;
                 let operands = operands
@@ -368,6 +368,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                         template,
                         operands,
                         options,
+                        line_spans,
                         destination: if options.contains(InlineAsmOptions::NORETURN) {
                             None
                         } else {
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 114bf571040..969bb4f7259 100644
--- a/src/librustc_mir_build/hair/cx/expr.rs
+++ b/src/librustc_mir_build/hair/cx/expr.rs
@@ -513,6 +513,7 @@ fn make_mirror_unadjusted<'a, 'tcx>(
                 })
                 .collect(),
             options: asm.options,
+            line_spans: asm.line_spans,
         },
 
         hir::ExprKind::LlvmInlineAsm(ref asm) => ExprKind::LlvmInlineAsm {
@@ -884,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_mir_build/hair/mod.rs b/src/librustc_mir_build/hair/mod.rs
index aba7a7a1b42..0a1c68e83a9 100644
--- a/src/librustc_mir_build/hair/mod.rs
+++ b/src/librustc_mir_build/hair/mod.rs
@@ -283,6 +283,7 @@ crate enum ExprKind<'tcx> {
         template: &'tcx [InlineAsmTemplatePiece],
         operands: Vec<InlineAsmOperand<'tcx>>,
         options: InlineAsmOptions,
+        line_spans: &'tcx [Span],
     },
     LlvmInlineAsm {
         asm: &'tcx hir::LlvmInlineAsmInner,
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.rs b/src/librustc_session/lint.rs
index b16d513d923..8a66fac1e36 100644
--- a/src/librustc_session/lint.rs
+++ b/src/librustc_session/lint.rs
@@ -347,14 +347,14 @@ pub trait LintPass {
     fn name(&self) -> &'static str;
 }
 
-/// Implements `LintPass for $name` with the given list of `Lint` statics.
+/// Implements `LintPass for $ty` with the given list of `Lint` statics.
 #[macro_export]
 macro_rules! impl_lint_pass {
-    ($name:ident => [$($lint:expr),* $(,)?]) => {
-        impl $crate::lint::LintPass for $name {
-            fn name(&self) -> &'static str { stringify!($name) }
+    ($ty:ty => [$($lint:expr),* $(,)?]) => {
+        impl $crate::lint::LintPass for $ty {
+            fn name(&self) -> &'static str { stringify!($ty) }
         }
-        impl $name {
+        impl $ty {
             pub fn get_lints() -> $crate::lint::LintArray { $crate::lint_array!($($lint),*) }
         }
     };
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/options.rs b/src/librustc_session/options.rs
index 95f9ff00fb8..a38e7f063d7 100644
--- a/src/librustc_session/options.rs
+++ b/src/librustc_session/options.rs
@@ -955,6 +955,9 @@ options! {DebuggingOptions, DebuggingSetter, basic_debugging_options,
         "print layout information for each type encountered (default: no)"),
     profile: bool = (false, parse_bool, [TRACKED],
         "insert profiling code (default: no)"),
+    profile_emit: Option<PathBuf> = (None, parse_opt_pathbuf, [TRACKED],
+        "file path to emit profiling data at runtime when using 'profile' \
+        (default based on relative source path)"),
     query_dep_graph: bool = (false, parse_bool, [UNTRACKED],
         "enable queries of the dependency graph for regression testing (default: no)"),
     query_stats: bool = (false, parse_bool, [UNTRACKED],
diff --git a/src/librustc_session/parse.rs b/src/librustc_session/parse.rs
index 746e3536ce9..233761dbed7 100644
--- a/src/librustc_session/parse.rs
+++ b/src/librustc_session/parse.rs
@@ -174,6 +174,10 @@ impl ParseSess {
         &self.source_map
     }
 
+    pub fn clone_source_map(&self) -> Lrc<SourceMap> {
+        self.source_map.clone()
+    }
+
     pub fn buffer_lint(
         &self,
         lint: &'static Lint,
diff --git a/src/librustc_session/session.rs b/src/librustc_session/session.rs
index f2f02cb6494..048033846a1 100644
--- a/src/librustc_session/session.rs
+++ b/src/librustc_session/session.rs
@@ -21,7 +21,7 @@ use rustc_errors::json::JsonEmitter;
 use rustc_errors::registry::Registry;
 use rustc_errors::{Applicability, DiagnosticBuilder, DiagnosticId, ErrorReported};
 use rustc_span::edition::Edition;
-use rustc_span::source_map::{self, FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
+use rustc_span::source_map::{FileLoader, MultiSpan, RealFileLoader, SourceMap, Span};
 use rustc_span::{SourceFileHashAlgorithm, Symbol};
 use rustc_target::asm::InlineAsmArch;
 use rustc_target::spec::{CodeModel, PanicStrategy, RelocModel, RelroLevel};
@@ -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()
     }
 
@@ -481,7 +523,7 @@ impl Session {
     }
 
     #[inline]
-    pub fn source_map(&self) -> &source_map::SourceMap {
+    pub fn source_map(&self) -> &SourceMap {
         self.parse_sess.source_map()
     }
     pub fn verbose(&self) -> bool {
@@ -984,26 +1026,10 @@ impl Session {
     }
 }
 
-pub fn build_session(
-    sopts: config::Options,
-    local_crate_source_file: Option<PathBuf>,
-    registry: rustc_errors::registry::Registry,
-) -> Session {
-    build_session_with_source_map(
-        sopts,
-        local_crate_source_file,
-        registry,
-        DiagnosticOutput::Default,
-        Default::default(),
-        None,
-    )
-    .0
-}
-
 fn default_emitter(
     sopts: &config::Options,
     registry: rustc_errors::registry::Registry,
-    source_map: &Lrc<source_map::SourceMap>,
+    source_map: Lrc<SourceMap>,
     emitter_dest: Option<Box<dyn Write + Send>>,
 ) -> Box<dyn Emitter + sync::Send> {
     let macro_backtrace = sopts.debugging_opts.macro_backtrace;
@@ -1012,17 +1038,14 @@ fn default_emitter(
             let (short, color_config) = kind.unzip();
 
             if let HumanReadableErrorType::AnnotateSnippet(_) = kind {
-                let emitter = AnnotateSnippetEmitterWriter::new(
-                    Some(source_map.clone()),
-                    short,
-                    macro_backtrace,
-                );
+                let emitter =
+                    AnnotateSnippetEmitterWriter::new(Some(source_map), short, macro_backtrace);
                 Box::new(emitter.ui_testing(sopts.debugging_opts.ui_testing))
             } else {
                 let emitter = match dst {
                     None => EmitterWriter::stderr(
                         color_config,
-                        Some(source_map.clone()),
+                        Some(source_map),
                         short,
                         sopts.debugging_opts.teach,
                         sopts.debugging_opts.terminal_width,
@@ -1030,7 +1053,7 @@ fn default_emitter(
                     ),
                     Some(dst) => EmitterWriter::new(
                         dst,
-                        Some(source_map.clone()),
+                        Some(source_map),
                         short,
                         false, // no teach messages when writing to a buffer
                         false, // no colors when writing to a buffer
@@ -1042,20 +1065,14 @@ fn default_emitter(
             }
         }
         (config::ErrorOutputType::Json { pretty, json_rendered }, None) => Box::new(
-            JsonEmitter::stderr(
-                Some(registry),
-                source_map.clone(),
-                pretty,
-                json_rendered,
-                macro_backtrace,
-            )
-            .ui_testing(sopts.debugging_opts.ui_testing),
+            JsonEmitter::stderr(Some(registry), source_map, pretty, json_rendered, macro_backtrace)
+                .ui_testing(sopts.debugging_opts.ui_testing),
         ),
         (config::ErrorOutputType::Json { pretty, json_rendered }, Some(dst)) => Box::new(
             JsonEmitter::new(
                 dst,
                 Some(registry),
-                source_map.clone(),
+                source_map,
                 pretty,
                 json_rendered,
                 macro_backtrace,
@@ -1070,14 +1087,14 @@ pub enum DiagnosticOutput {
     Raw(Box<dyn Write + Send>),
 }
 
-pub fn build_session_with_source_map(
+pub fn build_session(
     sopts: config::Options,
     local_crate_source_file: Option<PathBuf>,
     registry: rustc_errors::registry::Registry,
     diagnostics_output: DiagnosticOutput,
     driver_lint_caps: FxHashMap<lint::LintId, lint::Level>,
     file_loader: Option<Box<dyn FileLoader + Send + Sync + 'static>>,
-) -> (Session, Lrc<SourceMap>) {
+) -> Session {
     // FIXME: This is not general enough to make the warning lint completely override
     // normal diagnostic warnings, since the warning lint can also be denied and changed
     // later via the source code.
@@ -1115,7 +1132,7 @@ pub fn build_session_with_source_map(
         sopts.file_path_mapping(),
         hash_kind,
     ));
-    let emitter = default_emitter(&sopts, registry, &source_map, write_dest);
+    let emitter = default_emitter(&sopts, registry, source_map.clone(), write_dest);
 
     let span_diagnostic = rustc_errors::Handler::with_emitter_and_flags(
         emitter,
@@ -1143,7 +1160,7 @@ pub fn build_session_with_source_map(
         None
     };
 
-    let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map.clone());
+    let parse_sess = ParseSess::with_span_handler(span_diagnostic, source_map);
     let sysroot = match &sopts.maybe_sysroot {
         Some(sysroot) => sysroot.clone(),
         None => filesearch::get_or_default_sysroot(),
@@ -1266,7 +1283,7 @@ pub fn build_session_with_source_map(
 
     validate_commandline_args_with_session_available(&sess);
 
-    (sess, source_map)
+    sess
 }
 
 // If it is useful to have a Session available already for validating a
diff --git a/src/librustc_span/lib.rs b/src/librustc_span/lib.rs
index 58cdb87158a..616876d4b02 100644
--- a/src/librustc_span/lib.rs
+++ b/src/librustc_span/lib.rs
@@ -101,6 +101,8 @@ pub enum FileName {
     /// Custom sources for explicit parser calls from plugins and drivers.
     Custom(String),
     DocTest(PathBuf, isize),
+    /// Post-substitution inline assembly from LLVM
+    InlineAsm(u64),
 }
 
 impl std::fmt::Display for FileName {
@@ -116,6 +118,7 @@ impl std::fmt::Display for FileName {
             CliCrateAttr(_) => write!(fmt, "<crate attribute>"),
             Custom(ref s) => write!(fmt, "<{}>", s),
             DocTest(ref path, _) => write!(fmt, "{}", path.display()),
+            InlineAsm(_) => write!(fmt, "<inline asm>"),
         }
     }
 }
@@ -139,7 +142,8 @@ impl FileName {
             | CliCrateAttr(_)
             | Custom(_)
             | QuoteExpansion(_)
-            | DocTest(_, _) => false,
+            | DocTest(_, _)
+            | InlineAsm(_) => false,
         }
     }
 
@@ -182,6 +186,12 @@ impl FileName {
     pub fn doc_test_source_code(path: PathBuf, line: isize) -> FileName {
         FileName::DocTest(path, line)
     }
+
+    pub fn inline_asm_source_code(src: &str) -> FileName {
+        let mut hasher = StableHasher::new();
+        src.hash(&mut hasher);
+        FileName::InlineAsm(hasher.finish())
+    }
 }
 
 /// Spans represent a region of code, used for error reporting. Positions in spans
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/fuchsia_base.rs b/src/librustc_target/spec/fuchsia_base.rs
index 96b5328e1ee..dd55788b664 100644
--- a/src/librustc_target/spec/fuchsia_base.rs
+++ b/src/librustc_target/spec/fuchsia_base.rs
@@ -9,7 +9,14 @@ pub fn opts() -> TargetOptions {
             "--eh-frame-hdr".to_string(),
             "--hash-style=gnu".to_string(),
             "-z".to_string(),
+            "max-page-size=4096".to_string(),
+            "-z".to_string(),
+            "now".to_string(),
+            "-z".to_string(),
             "rodynamic".to_string(),
+            "-z".to_string(),
+            "separate-loadable-segments".to_string(),
+            "--pack-dyn-relocs=relr".to_string(),
         ],
     );
 
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..ab9db159038 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,
@@ -1129,9 +1151,16 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                             .as_ref()
                             .and_then(|args| args.args.get(0))
                             .and_then(|arg| match arg {
-                                hir::GenericArg::Type(ty) => {
-                                    sess.source_map().span_to_snippet(ty.span).ok()
+                                hir::GenericArg::Type(ty) => match ty.kind {
+                                    hir::TyKind::Tup(t) => t
+                                        .iter()
+                                        .map(|e| sess.source_map().span_to_snippet(e.span))
+                                        .collect::<Result<Vec<_>, _>>()
+                                        .map(|a| a.join(", ")),
+                                    _ => sess.source_map().span_to_snippet(ty.span),
                                 }
+                                .map(|s| format!("({})", s))
+                                .ok(),
                                 _ => None,
                             })
                             .unwrap_or_else(|| "()".to_string()),
@@ -1166,8 +1195,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 +1543,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 +2503,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/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 4bf3649dcc2..08e04f719e9 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -6,7 +6,7 @@ use rustc_ast::ast;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind, Res};
-use rustc_hir::def_id::DefId;
+use rustc_hir::def_id::{DefId, CRATE_DEF_INDEX};
 use rustc_hir::Mutability;
 use rustc_metadata::creader::LoadedMacro;
 use rustc_middle::ty;
@@ -454,11 +454,7 @@ fn build_module(cx: &DocContext<'_>, did: DefId, visited: &mut FxHashSet<DefId>)
                         name: None,
                         attrs: clean::Attributes::default(),
                         source: clean::Span::empty(),
-                        def_id: cx
-                            .tcx
-                            .hir()
-                            .local_def_id_from_node_id(ast::CRATE_NODE_ID)
-                            .to_def_id(),
+                        def_id: DefId::local(CRATE_DEF_INDEX),
                         visibility: clean::Public,
                         stability: None,
                         deprecation: None,
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 702c7d1e0f1..371df7444b0 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1549,11 +1549,11 @@ impl<'tcx> Clean<Type> for Ty<'tcx> {
             ty::FnDef(..) | ty::FnPtr(_) => {
                 let ty = cx.tcx.lift(self).expect("FnPtr lift failed");
                 let sig = ty.fn_sig(cx.tcx);
-                let local_def_id = cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID);
+                let def_id = DefId::local(CRATE_DEF_INDEX);
                 BareFunction(box BareFunctionDecl {
                     unsafety: sig.unsafety(),
                     generic_params: Vec::new(),
-                    decl: (local_def_id.to_def_id(), sig).clean(cx),
+                    decl: (def_id, sig).clean(cx),
                     abi: sig.abi(),
                 })
             }
@@ -2255,7 +2255,7 @@ impl Clean<Vec<Item>> for doctree::Import<'_> {
             name: None,
             attrs: self.attrs.clean(cx),
             source: self.whence.clean(cx),
-            def_id: cx.tcx.hir().local_def_id_from_node_id(ast::CRATE_NODE_ID).to_def_id(),
+            def_id: DefId::local(CRATE_DEF_INDEX),
             visibility: self.vis.clean(cx),
             stability: None,
             deprecation: None,
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/librustdoc/html/render.rs b/src/librustdoc/html/render.rs
index cd49da88d96..5b364ed95cf 100644
--- a/src/librustdoc/html/render.rs
+++ b/src/librustdoc/html/render.rs
@@ -4067,9 +4067,9 @@ fn sidebar_assoc_items(it: &clean::Item) -> String {
                 .filter(|i| i.inner_impl().trait_.is_none())
                 .flat_map(move |i| get_methods(i.inner_impl(), false, used_links_bor, false))
                 .collect::<Vec<_>>();
-            // We want links' order to be reproducible so we don't use unstable sort.
-            ret.sort();
             if !ret.is_empty() {
+                // We want links' order to be reproducible so we don't use unstable sort.
+                ret.sort();
                 out.push_str(&format!(
                     "<a class=\"sidebar-title\" href=\"#implementations\">Methods</a>\
                      <div class=\"sidebar-links\">{}</div>",
@@ -4240,7 +4240,7 @@ fn is_negative_impl(i: &clean::Impl) -> bool {
 fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     let mut sidebar = String::new();
 
-    let types = t
+    let mut types = t
         .items
         .iter()
         .filter_map(|m| match m.name {
@@ -4249,8 +4249,8 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
             }
             _ => None,
         })
-        .collect::<String>();
-    let consts = t
+        .collect::<Vec<_>>();
+    let mut consts = t
         .items
         .iter()
         .filter_map(|m| match m.name {
@@ -4259,7 +4259,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
             }
             _ => None,
         })
-        .collect::<String>();
+        .collect::<Vec<_>>();
     let mut required = t
         .items
         .iter()
@@ -4282,24 +4282,26 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
         .collect::<Vec<String>>();
 
     if !types.is_empty() {
+        types.sort();
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#associated-types\">\
-                                   Associated Types</a><div class=\"sidebar-links\">{}</div>",
-            types
+                Associated Types</a><div class=\"sidebar-links\">{}</div>",
+            types.join("")
         ));
     }
     if !consts.is_empty() {
+        consts.sort();
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#associated-const\">\
-                                   Associated Constants</a><div class=\"sidebar-links\">{}</div>",
-            consts
+                Associated Constants</a><div class=\"sidebar-links\">{}</div>",
+            consts.join("")
         ));
     }
     if !required.is_empty() {
         required.sort();
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#required-methods\">\
-                                   Required Methods</a><div class=\"sidebar-links\">{}</div>",
+                Required Methods</a><div class=\"sidebar-links\">{}</div>",
             required.join("")
         ));
     }
@@ -4307,7 +4309,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
         provided.sort();
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#provided-methods\">\
-                                   Provided Methods</a><div class=\"sidebar-links\">{}</div>",
+                Provided Methods</a><div class=\"sidebar-links\">{}</div>",
             provided.join("")
         ));
     }
@@ -4325,8 +4327,8 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
             res.sort();
             sidebar.push_str(&format!(
                 "<a class=\"sidebar-title\" href=\"#foreign-impls\">\
-                                       Implementations on Foreign Types</a><div \
-                                       class=\"sidebar-links\">{}</div>",
+                    Implementations on Foreign Types</a><div \
+                    class=\"sidebar-links\">{}</div>",
                 res.into_iter()
                     .map(|(name, id)| format!("<a href=\"#{}\">{}</a>", id, Escape(&name)))
                     .collect::<Vec<_>>()
@@ -4339,7 +4341,7 @@ fn sidebar_trait(buf: &mut Buffer, it: &clean::Item, t: &clean::Trait) {
     if t.auto {
         sidebar.push_str(
             "<a class=\"sidebar-title\" \
-                          href=\"#synthetic-implementors\">Auto Implementors</a>",
+                href=\"#synthetic-implementors\">Auto Implementors</a>",
         );
     }
 
@@ -4365,18 +4367,18 @@ fn sidebar_typedef(buf: &mut Buffer, it: &clean::Item) {
 }
 
 fn get_struct_fields_name(fields: &[clean::Item]) -> String {
-    fields
+    let mut fields = fields
         .iter()
         .filter(|f| if let clean::StructFieldItem(..) = f.inner { true } else { false })
         .filter_map(|f| match f.name {
-            Some(ref name) => Some(format!(
-                "<a href=\"#structfield.{name}\">\
-                                              {name}</a>",
-                name = name
-            )),
+            Some(ref name) => {
+                Some(format!("<a href=\"#structfield.{name}\">{name}</a>", name = name))
+            }
             _ => None,
         })
-        .collect()
+        .collect::<Vec<_>>();
+    fields.sort();
+    fields.join("")
 }
 
 fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
@@ -4386,7 +4388,7 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
     if !fields.is_empty() {
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#fields\">Fields</a>\
-                                   <div class=\"sidebar-links\">{}</div>",
+             <div class=\"sidebar-links\">{}</div>",
             fields
         ));
     }
@@ -4401,23 +4403,20 @@ fn sidebar_union(buf: &mut Buffer, it: &clean::Item, u: &clean::Union) {
 fn sidebar_enum(buf: &mut Buffer, it: &clean::Item, e: &clean::Enum) {
     let mut sidebar = String::new();
 
-    let variants = e
+    let mut variants = e
         .variants
         .iter()
         .filter_map(|v| match v.name {
-            Some(ref name) => Some(format!(
-                "<a href=\"#variant.{name}\">{name}\
-                                                                 </a>",
-                name = name
-            )),
+            Some(ref name) => Some(format!("<a href=\"#variant.{name}\">{name}</a>", name = name)),
             _ => None,
         })
-        .collect::<String>();
+        .collect::<Vec<_>>();
     if !variants.is_empty() {
+        variants.sort_unstable();
         sidebar.push_str(&format!(
             "<a class=\"sidebar-title\" href=\"#variants\">Variants</a>\
-                                   <div class=\"sidebar-links\">{}</div>",
-            variants
+             <div class=\"sidebar-links\">{}</div>",
+            variants.join(""),
         ));
     }
 
diff --git a/src/librustdoc/test.rs b/src/librustdoc/test.rs
index 284e6d421ee..85ba4cbdc7e 100644
--- a/src/librustdoc/test.rs
+++ b/src/librustdoc/test.rs
@@ -114,7 +114,7 @@ pub fn run(options: Options) -> Result<(), String> {
                 options,
                 false,
                 opts,
-                Some(compiler.source_map().clone()),
+                Some(compiler.session().parse_sess.clone_source_map()),
                 None,
                 enable_per_target_ignores,
             );
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/rustllvm/RustWrapper.cpp b/src/rustllvm/RustWrapper.cpp
index 24f35627d10..6fac2662506 100644
--- a/src/rustllvm/RustWrapper.cpp
+++ b/src/rustllvm/RustWrapper.cpp
@@ -1216,10 +1216,33 @@ extern "C" void LLVMRustSetInlineAsmDiagnosticHandler(
   unwrap(C)->setInlineAsmDiagnosticHandler(H, CX);
 }
 
-extern "C" void LLVMRustWriteSMDiagnosticToString(LLVMSMDiagnosticRef D,
-                                                  RustStringRef Str) {
-  RawRustStringOstream OS(Str);
-  unwrap(D)->print("", OS);
+extern "C" bool LLVMRustUnpackSMDiagnostic(LLVMSMDiagnosticRef DRef,
+                                           RustStringRef MessageOut,
+                                           RustStringRef BufferOut,
+                                           unsigned* LocOut,
+                                           unsigned* RangesOut,
+                                           size_t* NumRanges) {
+  SMDiagnostic& D = *unwrap(DRef);
+  RawRustStringOstream MessageOS(MessageOut);
+  MessageOS << D.getMessage();
+
+  if (D.getLoc() == SMLoc())
+    return false;
+
+  const SourceMgr &LSM = *D.getSourceMgr();
+  const MemoryBuffer *LBuf = LSM.getMemoryBuffer(LSM.FindBufferContainingLoc(D.getLoc()));
+  LLVMRustStringWriteImpl(BufferOut, LBuf->getBufferStart(), LBuf->getBufferSize());
+
+  *LocOut = D.getLoc().getPointer() - LBuf->getBufferStart();
+
+  *NumRanges = std::min(*NumRanges, D.getRanges().size());
+  size_t LineStart = *LocOut - (size_t)D.getColumnNo();
+  for (size_t i = 0; i < *NumRanges; i++) {
+    RangesOut[i * 2] = LineStart + D.getRanges()[i].first;
+    RangesOut[i * 2 + 1] = LineStart + D.getRanges()[i].second;
+  }
+
+  return true;
 }
 
 extern "C" LLVMValueRef LLVMRustBuildCleanupPad(LLVMBuilderRef B,
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/run-make-fulldeps/profile/Makefile b/src/test/run-make-fulldeps/profile/Makefile
index c12712590e4..04d382b475e 100644
--- a/src/test/run-make-fulldeps/profile/Makefile
+++ b/src/test/run-make-fulldeps/profile/Makefile
@@ -7,3 +7,6 @@ all:
 	$(call RUN,test) || exit 1
 	[ -e "$(TMPDIR)/test.gcno" ] || (echo "No .gcno file"; exit 1)
 	[ -e "$(TMPDIR)/test.gcda" ] || (echo "No .gcda file"; exit 1)
+	$(RUSTC) -g -Z profile -Z profile-emit=$(TMPDIR)/abc/abc.gcda test.rs
+	$(call RUN,test) || exit 1
+	[ -e "$(TMPDIR)/abc/abc.gcda" ] || (echo "gcda file not emitted to defined path"; exit 1)
diff --git a/src/test/ui-fulldeps/lint-pass-macros.rs b/src/test/ui-fulldeps/lint-pass-macros.rs
new file mode 100644
index 00000000000..b3c2a542792
--- /dev/null
+++ b/src/test/ui-fulldeps/lint-pass-macros.rs
@@ -0,0 +1,26 @@
+// compile-flags: -Z unstable-options
+// check-pass
+
+#![feature(rustc_private)]
+
+extern crate rustc_session;
+
+use rustc_session::lint::{LintArray, LintPass};
+use rustc_session::{declare_lint, declare_lint_pass, impl_lint_pass};
+
+declare_lint! {
+    pub TEST_LINT,
+    Allow,
+    "test"
+}
+
+struct Foo;
+
+struct Bar<'a>(&'a u32);
+
+impl_lint_pass!(Foo => [TEST_LINT]);
+impl_lint_pass!(Bar<'_> => [TEST_LINT]);
+
+declare_lint_pass!(Baz => [TEST_LINT]);
+
+fn main() {}
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/srcloc.rs b/src/test/ui/asm/srcloc.rs
new file mode 100644
index 00000000000..7af6f620a98
--- /dev/null
+++ b/src/test/ui/asm/srcloc.rs
@@ -0,0 +1,41 @@
+// no-system-llvm
+// only-x86_64
+// build-fail
+
+#![feature(asm)]
+
+// Checks that inline asm errors are mapped to the correct line in the source code.
+
+fn main() {
+    unsafe {
+        asm!("invalid_instruction");
+        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!("
+            invalid_instruction
+        ");
+        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!(r#"
+            invalid_instruction
+        "#);
+        //~^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!("
+            mov eax, eax
+            invalid_instruction
+            mov eax, eax
+        ");
+        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!(r#"
+            mov eax, eax
+            invalid_instruction
+            mov eax, eax
+        "#);
+        //~^^^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+
+        asm!(concat!("invalid", "_", "instruction"));
+        //~^ ERROR: invalid instruction mnemonic 'invalid_instruction'
+    }
+}
diff --git a/src/test/ui/asm/srcloc.stderr b/src/test/ui/asm/srcloc.stderr
new file mode 100644
index 00000000000..57a4fbb9742
--- /dev/null
+++ b/src/test/ui/asm/srcloc.stderr
@@ -0,0 +1,74 @@
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:11:15
+   |
+LL |         asm!("invalid_instruction");
+   |               ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:15:13
+   |
+LL |             invalid_instruction
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:20:13
+   |
+LL |             invalid_instruction
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:3:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:26:13
+   |
+LL |             invalid_instruction
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:33:13
+   |
+LL |             invalid_instruction
+   |             ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:4:13
+   |
+LL |             invalid_instruction
+   |             ^^^^^^^^^^^^^^^^^^^
+
+error: invalid instruction mnemonic 'invalid_instruction'
+  --> $DIR/srcloc.rs:38:14
+   |
+LL |         asm!(concat!("invalid", "_", "instruction"));
+   |              ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:2:2
+   |
+LL |     invalid_instruction
+   |     ^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 6 previous errors
+
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/const-eval/ub-enum.stderr b/src/test/ui/consts/const-eval/ub-enum.stderr
index d8dafac3e70..e49fd3e0b97 100644
--- a/src/test/ui/consts/const-eval/ub-enum.stderr
+++ b/src/test/ui/consts/const-eval/ub-enum.stderr
@@ -82,7 +82,7 @@ error[E0080]: it is undefined behavior to use this value
   --> $DIR/ub-enum.rs:87:1
    |
 LL | const BAD_OPTION_CHAR: Option<(char, char)> = Some(('x', unsafe { mem::transmute(!0u32) }));
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at .<enum-variant(Some)>.0.1, but expected a valid unicode codepoint
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type validation failed: encountered 0xffffffff at .<enum-variant(Some)>.0.1, but expected a valid unicode scalar value (in `0..=0x10FFFF` but not in `0xD800..=0xDFFF`)
    |
    = note: The rules on what exactly is undefined behavior aren't clear, so this check might be overzealous. Please open an issue on the rustc repository if you believe it should not be considered undefined behavior.
 
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/extenv/extenv-not-defined-custom.stderr b/src/test/ui/extenv/extenv-not-defined-custom.stderr
index 523982dd019..56415fd1f0d 100644
--- a/src/test/ui/extenv/extenv-not-defined-custom.stderr
+++ b/src/test/ui/extenv/extenv-not-defined-custom.stderr
@@ -3,6 +3,8 @@ error: my error message
    |
 LL | fn main() { env!("__HOPEFULLY_NOT_DEFINED__", "my error message"); }
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/extenv/extenv-not-defined-default.stderr b/src/test/ui/extenv/extenv-not-defined-default.stderr
index 4bfe330f592..1a9332c4f1c 100644
--- a/src/test/ui/extenv/extenv-not-defined-default.stderr
+++ b/src/test/ui/extenv/extenv-not-defined-default.stderr
@@ -3,6 +3,8 @@ error: environment variable `__HOPEFULLY_NOT_DEFINED__` not defined
    |
 LL |     env!("__HOPEFULLY_NOT_DEFINED__");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/extenv/issue-55897.stderr b/src/test/ui/extenv/issue-55897.stderr
index c57a467cdba..b62f06e33e5 100644
--- a/src/test/ui/extenv/issue-55897.stderr
+++ b/src/test/ui/extenv/issue-55897.stderr
@@ -3,6 +3,8 @@ error: environment variable `NON_EXISTENT` not defined
    |
 LL |     include!(concat!(env!("NON_EXISTENT"), "/data.rs"));
    |                      ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: suffixes on a string literal are invalid
   --> $DIR/issue-55897.rs:16:22
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-23458.stderr b/src/test/ui/issues/issue-23458.stderr
index 81f06e63975..a6500b9bb4c 100644
--- a/src/test/ui/issues/issue-23458.stderr
+++ b/src/test/ui/issues/issue-23458.stderr
@@ -2,16 +2,19 @@ error: invalid operand in inline asm: 'int $3'
   --> $DIR/issue-23458.rs:8:9
    |
 LL |         llvm_asm!("int $3");
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: <inline asm>:1:2: error: too few operands for instruction
-        int 
-        ^
+   |         ^
 
+error: too few operands for instruction
   --> $DIR/issue-23458.rs:8:9
    |
 LL |         llvm_asm!("int $3");
-   |         ^^^^^^^^^^^^^^^^^^^^
+   |         ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:2
+   |
+LL |     int 
+   |     ^
 
 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/llvm-asm/issue-69092.rs b/src/test/ui/llvm-asm/issue-69092.rs
index ecce7bfdf5b..96c019b760e 100644
--- a/src/test/ui/llvm-asm/issue-69092.rs
+++ b/src/test/ui/llvm-asm/issue-69092.rs
@@ -6,5 +6,5 @@
 
 fn main() {
     unsafe { llvm_asm!(".ascii \"Xen\0\""); }
-    //~^ ERROR: <inline asm>:1:9: error: expected string in '.ascii' directive
+    //~^ ERROR: expected string in '.ascii' directive
 }
diff --git a/src/test/ui/llvm-asm/issue-69092.stderr b/src/test/ui/llvm-asm/issue-69092.stderr
index 35f77edc3c4..2ca86cf7c1b 100644
--- a/src/test/ui/llvm-asm/issue-69092.stderr
+++ b/src/test/ui/llvm-asm/issue-69092.stderr
@@ -1,11 +1,14 @@
-error: <inline asm>:1:9: error: expected string in '.ascii' directive
-        .ascii "Xen
-               ^
-
+error: expected string in '.ascii' directive
   --> $DIR/issue-69092.rs:8:14
    |
 LL |     unsafe { llvm_asm!(".ascii \"Xen\0\""); }
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |              ^
+   |
+note: instantiated into assembly here
+  --> <inline asm>:1:9
+   |
+LL |     .ascii "Xen
+   |            ^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/macros/macros-nonfatal-errors.stderr b/src/test/ui/macros/macros-nonfatal-errors.stderr
index 6ef757a55b8..42954ebcdc1 100644
--- a/src/test/ui/macros/macros-nonfatal-errors.stderr
+++ b/src/test/ui/macros/macros-nonfatal-errors.stderr
@@ -47,6 +47,8 @@ error: environment variable `RUST_HOPEFULLY_THIS_DOESNT_EXIST` not defined
    |
 LL |     env!("RUST_HOPEFULLY_THIS_DOESNT_EXIST");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in a macro (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: format argument must be a string literal
   --> $DIR/macros-nonfatal-errors.rs:23:13
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/parser/shebang/shebang-doc-comment.rs b/src/test/ui/parser/shebang/shebang-doc-comment.rs
new file mode 100644
index 00000000000..7dbb9eebc75
--- /dev/null
+++ b/src/test/ui/parser/shebang/shebang-doc-comment.rs
@@ -0,0 +1,6 @@
+#!///bin/bash
+[allow(unused_variables)]
+//~^^ ERROR expected `[`, found doc comment
+
+// Doc comment is misinterpreted as a whitespace (regular comment) during shebang detection.
+// Even if it wasn't, it would still result in an error, just a different one.
diff --git a/src/test/ui/parser/shebang/shebang-doc-comment.stderr b/src/test/ui/parser/shebang/shebang-doc-comment.stderr
new file mode 100644
index 00000000000..f524f556837
--- /dev/null
+++ b/src/test/ui/parser/shebang/shebang-doc-comment.stderr
@@ -0,0 +1,8 @@
+error: expected `[`, found doc comment `///bin/bash`
+  --> $DIR/shebang-doc-comment.rs:1:3
+   |
+LL | #!///bin/bash
+   |   ^^^^^^^^^^^ expected `[`
+
+error: aborting due to previous error
+
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/fn-trait-notation.fixed b/src/test/ui/suggestions/fn-trait-notation.fixed
new file mode 100644
index 00000000000..cf940f4e926
--- /dev/null
+++ b/src/test/ui/suggestions/fn-trait-notation.fixed
@@ -0,0 +1,19 @@
+// run-rustfix
+fn e0658<F, G, H>(f: F, g: G, h: H) -> i32
+where
+    F: Fn(i32) -> i32, //~ ERROR E0658
+    G: Fn(i32, i32) -> (i32, i32), //~ ERROR E0658
+    H: Fn(i32) -> i32, //~ ERROR E0658
+{
+    f(3);
+    g(3, 4);
+    h(3)
+}
+
+fn main() {
+    e0658(
+        |a| a,
+        |a, b| (b, a),
+        |a| a,
+    );
+}
diff --git a/src/test/ui/suggestions/fn-trait-notation.rs b/src/test/ui/suggestions/fn-trait-notation.rs
new file mode 100644
index 00000000000..f0bb03315d9
--- /dev/null
+++ b/src/test/ui/suggestions/fn-trait-notation.rs
@@ -0,0 +1,19 @@
+// run-rustfix
+fn e0658<F, G, H>(f: F, g: G, h: H) -> i32
+where
+    F: Fn<i32, Output = i32>, //~ ERROR E0658
+    G: Fn<(i32, i32, ), Output = (i32, i32)>, //~ ERROR E0658
+    H: Fn<(i32,), Output = i32>, //~ ERROR E0658
+{
+    f(3);
+    g(3, 4);
+    h(3)
+}
+
+fn main() {
+    e0658(
+        |a| a,
+        |a, b| (b, a),
+        |a| a,
+    );
+}
diff --git a/src/test/ui/suggestions/fn-trait-notation.stderr b/src/test/ui/suggestions/fn-trait-notation.stderr
new file mode 100644
index 00000000000..3e3b5417440
--- /dev/null
+++ b/src/test/ui/suggestions/fn-trait-notation.stderr
@@ -0,0 +1,30 @@
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+  --> $DIR/fn-trait-notation.rs:4:8
+   |
+LL |     F: Fn<i32, Output = i32>,
+   |        ^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32`
+   |
+   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+  --> $DIR/fn-trait-notation.rs:5:8
+   |
+LL |     G: Fn<(i32, i32, ), Output = (i32, i32)>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32, i32) -> (i32, i32)`
+   |
+   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+   = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
+
+error[E0658]: the precise format of `Fn`-family traits' type parameters is subject to change
+  --> $DIR/fn-trait-notation.rs:6:8
+   |
+LL |     H: Fn<(i32,), Output = i32>,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^ help: use parenthetical notation instead: `Fn(i32) -> i32`
+   |
+   = note: see issue #29625 <https://github.com/rust-lang/rust/issues/29625> for more information
+   = help: add `#![feature(unboxed_closures)]` 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/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