about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml6
-rw-r--r--.gitignore1
-rw-r--r--.reuse/dep528
-rw-r--r--Cargo.lock9
-rw-r--r--LICENSES/Apache-2.0.txt73
-rw-r--r--LICENSES/BSD-2-Clause.txt9
-rw-r--r--LICENSES/MIT.txt9
-rw-r--r--LICENSES/OFL-1.1.txt43
-rw-r--r--compiler/rustc_apfloat/src/lib.rs2
-rw-r--r--compiler/rustc_arena/src/lib.rs4
-rw-r--r--compiler/rustc_ast/src/ast.rs30
-rw-r--r--compiler/rustc_ast/src/ast_traits.rs47
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs3
-rw-r--r--compiler/rustc_ast/src/lib.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs34
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs50
-rw-r--r--compiler/rustc_ast_passes/Cargo.toml1
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs248
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs248
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs58
-rw-r--r--compiler/rustc_ast_passes/src/lib.rs1
-rw-r--r--compiler/rustc_ast_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_borrowck/src/diagnostics/mod.rs14
-rw-r--r--compiler/rustc_borrowck/src/session_diagnostics.rs8
-rw-r--r--compiler/rustc_borrowck/src/type_check/canonical.rs7
-rw-r--r--compiler/rustc_borrowck/src/type_check/free_region_relations.rs45
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs139
-rw-r--r--compiler/rustc_builtin_macros/src/asm.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/assert.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/cfg.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/bounds.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/clone.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs67
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/debug.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/decodable.rs3
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/default.rs7
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/encodable.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs30
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/ty.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/hash.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/mod.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/edition_panic.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/format.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs6
-rw-r--r--compiler/rustc_builtin_macros/src/proc_macro_harness.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/standard_library_imports.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test.rs5
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/example/alloc_system.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/unsize.rs1
-rw-r--r--compiler/rustc_codegen_gcc/example/alloc_system.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/base.rs1
-rw-r--r--compiler/rustc_const_eval/src/errors.rs18
-rw-r--r--compiler/rustc_const_eval/src/interpret/cast.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/ops.rs5
-rw-r--r--compiler/rustc_data_structures/src/lib.rs2
-rw-r--r--compiler/rustc_data_structures/src/map_in_place.rs127
-rw-r--r--compiler/rustc_data_structures/src/thin_vec.rs45
-rw-r--r--compiler/rustc_data_structures/src/transitive_relation.rs121
-rw-r--r--compiler/rustc_data_structures/src/transitive_relation/tests.rs48
-rw-r--r--compiler/rustc_driver/src/lib.rs2
-rw-r--r--compiler/rustc_error_codes/src/lib.rs2
-rw-r--r--compiler/rustc_error_messages/locales/en-US/ast_passes.ftl93
-rw-r--r--compiler/rustc_error_messages/locales/en-US/borrowck.ftl6
-rw-r--r--compiler/rustc_error_messages/locales/en-US/expand.ftl17
-rw-r--r--compiler/rustc_error_messages/locales/en-US/parser.ftl118
-rw-r--r--compiler/rustc_error_messages/locales/en-US/typeck.ftl14
-rw-r--r--compiler/rustc_error_messages/src/lib.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic_builder.rs32
-rw-r--r--compiler/rustc_errors/src/lib.rs84
-rw-r--r--compiler/rustc_expand/src/base.rs4
-rw-r--r--compiler/rustc_expand/src/build.rs9
-rw-r--r--compiler/rustc_expand/src/config.rs8
-rw-r--r--compiler/rustc_expand/src/errors.rs48
-rw-r--r--compiler/rustc_expand/src/expand.rs40
-rw-r--r--compiler/rustc_expand/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs34
-rw-r--r--compiler/rustc_expand/src/module.rs8
-rw-r--r--compiler/rustc_expand/src/placeholders.rs8
-rw-r--r--compiler/rustc_feature/src/lib.rs2
-rw-r--r--compiler/rustc_fs_util/src/lib.rs3
-rw-r--r--compiler/rustc_graphviz/src/lib.rs2
-rw-r--r--compiler/rustc_hir/src/lib.rs2
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_index/src/lib.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/mod.rs145
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs3
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs5
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs2
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/note.rs4
-rw-r--r--compiler/rustc_infer/src/infer/free_regions.rs13
-rw-r--r--compiler/rustc_infer/src/infer/opaque_types.rs14
-rw-r--r--compiler/rustc_infer/src/infer/outlives/env.rs60
-rw-r--r--compiler/rustc_infer/src/infer/outlives/obligations.rs3
-rw-r--r--compiler/rustc_infer/src/infer/outlives/test_type_match.rs9
-rw-r--r--compiler/rustc_interface/src/passes.rs4
-rw-r--r--compiler/rustc_lexer/src/lib.rs2
-rw-r--r--compiler/rustc_lint/src/early.rs2
-rw-r--r--compiler/rustc_lint/src/types.rs2
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs51
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs14
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp25
-rw-r--r--compiler/rustc_llvm/src/lib.rs2
-rw-r--r--compiler/rustc_log/src/lib.rs3
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic.rs82
-rw-r--r--compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs87
-rw-r--r--compiler/rustc_macros/src/diagnostics/mod.rs4
-rw-r--r--compiler/rustc_macros/src/diagnostics/utils.rs59
-rw-r--r--compiler/rustc_macros/src/lib.rs10
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs257
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs5
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs191
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs6
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs32
-rw-r--r--compiler/rustc_middle/src/mir/interpret/value.rs4
-rw-r--r--compiler/rustc_middle/src/mir/query.rs22
-rw-r--r--compiler/rustc_middle/src/query/mod.rs8
-rw-r--r--compiler/rustc_middle/src/traits/mod.rs16
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs15
-rw-r--r--compiler/rustc_middle/src/ty/list.rs4
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs4
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs16
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs9
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs23
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/mod.rs3
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs88
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs13
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs76
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs12
-rw-r--r--compiler/rustc_parse/src/lib.rs4
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs8
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs17
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs397
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs454
-rw-r--r--compiler/rustc_parse/src/parser/generics.rs14
-rw-r--r--compiler/rustc_parse/src/parser/item.rs59
-rw-r--r--compiler/rustc_parse/src/parser/pat.rs10
-rw-r--r--compiler/rustc_parse/src/parser/stmt.rs51
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs26
-rw-r--r--compiler/rustc_parse_format/src/lib.rs2
-rw-r--r--compiler/rustc_passes/src/errors.rs171
-rw-r--r--compiler/rustc_privacy/src/errors.rs14
-rw-r--r--compiler/rustc_query_impl/src/lib.rs2
-rw-r--r--compiler/rustc_query_impl/src/on_disk_cache.rs58
-rw-r--r--compiler/rustc_resolve/src/imports.rs40
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs12
-rw-r--r--compiler/rustc_serialize/src/lib.rs2
-rw-r--r--compiler/rustc_serialize/src/serialize.rs2
-rw-r--r--compiler/rustc_session/src/parse.rs79
-rw-r--r--compiler/rustc_session/src/session.rs9
-rw-r--r--compiler/rustc_smir/src/lib.rs2
-rw-r--r--compiler/rustc_span/src/lib.rs18
-rw-r--r--compiler/rustc_span/src/source_map.rs7
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs4
-rw-r--r--compiler/rustc_target/src/lib.rs2
-rw-r--r--compiler/rustc_target/src/spec/apple_sdk_base.rs1
-rw-r--r--compiler/rustc_trait_selection/src/traits/engine.rs23
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs28
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs4
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs274
-rw-r--r--compiler/rustc_trait_selection/src/traits/mod.rs14
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs30
-rw-r--r--compiler/rustc_trait_selection/src/traits/util.rs25
-rw-r--r--compiler/rustc_trait_selection/src/traits/wf.rs2
-rw-r--r--compiler/rustc_traits/src/lib.rs2
-rw-r--r--compiler/rustc_transmute/src/lib.rs2
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs60
-rw-r--r--compiler/rustc_ty_utils/src/lib.rs2
-rw-r--r--compiler/rustc_type_ir/src/lib.rs2
-rw-r--r--compiler/rustc_typeck/src/astconv/mod.rs57
-rw-r--r--compiler/rustc_typeck/src/check/compare_method.rs161
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs70
-rw-r--r--compiler/rustc_typeck/src/check/fn_ctxt/checks.rs602
-rw-r--r--compiler/rustc_typeck/src/check/generator_interior.rs12
-rw-r--r--compiler/rustc_typeck/src/check/method/confirm.rs14
-rw-r--r--compiler/rustc_typeck/src/check/method/mod.rs7
-rw-r--r--compiler/rustc_typeck/src/check/method/probe.rs7
-rw-r--r--compiler/rustc_typeck/src/check/mod.rs1
-rw-r--r--compiler/rustc_typeck/src/check/regionck.rs47
-rw-r--r--compiler/rustc_typeck/src/check/wfcheck.rs110
-rw-r--r--compiler/rustc_typeck/src/check/writeback.rs26
-rw-r--r--compiler/rustc_typeck/src/check_unused.rs63
-rw-r--r--compiler/rustc_typeck/src/coherence/builtin.rs8
-rw-r--r--compiler/rustc_typeck/src/collect.rs7
-rw-r--r--compiler/rustc_typeck/src/errors.rs73
-rw-r--r--compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs93
-rw-r--r--compiler/rustc_typeck/src/lib.rs1
-rw-r--r--compiler/rustc_typeck/src/outlives/outlives_bounds.rs30
-rw-r--r--library/alloc/src/alloc/tests.rs2
-rw-r--r--library/alloc/src/boxed.rs2
-rw-r--r--library/alloc/src/collections/binary_heap.rs3
-rw-r--r--library/alloc/src/collections/vec_deque/mod.rs7
-rw-r--r--library/alloc/src/ffi/c_str.rs6
-rw-r--r--library/alloc/src/lib.rs9
-rw-r--r--library/alloc/src/slice.rs86
-rw-r--r--library/alloc/src/str.rs24
-rw-r--r--library/alloc/src/string.rs19
-rw-r--r--library/alloc/src/sync/tests.rs19
-rw-r--r--library/alloc/src/vec/in_place_collect.rs2
-rw-r--r--library/alloc/src/vec/into_iter.rs8
-rw-r--r--library/alloc/src/vec/mod.rs19
-rw-r--r--library/alloc/src/vec/spec_extend.rs2
-rw-r--r--library/alloc/tests/lib.rs1
-rw-r--r--library/alloc/tests/str.rs10
-rw-r--r--library/alloc/tests/thin_box.rs8
-rw-r--r--library/alloc/tests/vec.rs45
-rw-r--r--library/core/src/any.rs5
-rw-r--r--library/core/src/array/mod.rs2
-rw-r--r--library/core/src/borrow.rs2
-rw-r--r--library/core/src/char/mod.rs4
-rw-r--r--library/core/src/cmp.rs13
-rw-r--r--library/core/src/default.rs2
-rw-r--r--library/core/src/intrinsics.rs6
-rw-r--r--library/core/src/iter/adapters/flatten.rs375
-rw-r--r--library/core/src/num/f32.rs15
-rw-r--r--library/core/src/num/f64.rs15
-rw-r--r--library/core/src/num/mod.rs2
-rw-r--r--library/core/src/primitive_docs.rs61
-rw-r--r--library/core/src/slice/mod.rs15
-rw-r--r--library/core/src/slice/sort.rs36
-rw-r--r--library/core/src/str/lossy.rs244
-rw-r--r--library/core/src/str/mod.rs6
-rw-r--r--library/core/src/str/validations.rs4
-rw-r--r--library/core/src/sync/atomic.rs14
-rw-r--r--library/core/tests/iter/adapters/flatten.rs42
-rw-r--r--library/core/tests/lib.rs1
-rw-r--r--library/core/tests/str_lossy.rs138
-rw-r--r--library/panic_abort/src/android.rs2
-rw-r--r--library/panic_unwind/src/dwarf/eh.rs2
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/collections/hash/map/tests.rs24
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/f32.rs2
-rw-r--r--library/std/src/f64.rs2
-rw-r--r--library/std/src/ffi/os_str.rs3
-rw-r--r--library/std/src/io/tests.rs3
-rw-r--r--library/std/src/lib.rs19
-rw-r--r--library/std/src/net/ip.rs204
-rw-r--r--library/std/src/net/ip/tests.rs98
-rw-r--r--library/std/src/os/fortanix_sgx/mod.rs1
-rw-r--r--library/std/src/os/unix/net/addr.rs2
-rw-r--r--library/std/src/os/unix/net/listener.rs12
-rw-r--r--library/std/src/path/tests.rs5
-rw-r--r--library/std/src/primitive_docs.rs61
-rw-r--r--library/std/src/process.rs10
-rw-r--r--library/std/src/sync/mpsc/mpsc_queue/tests.rs2
-rw-r--r--library/std/src/sync/mpsc/spsc_queue/tests.rs5
-rw-r--r--library/std/src/sync/mpsc/sync_tests.rs21
-rw-r--r--library/std/src/sync/mpsc/tests.rs12
-rw-r--r--library/std/src/sync/rwlock/tests.rs2
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/alloc.rs165
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/mod.rs8
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/raw.rs24
-rw-r--r--library/std/src/sys/sgx/abi/usercalls/tests.rs34
-rw-r--r--library/std/src/sys/unix/fs.rs2
-rw-r--r--library/std/src/sys/unix/os_str.rs40
-rw-r--r--library/std/src/sys/unix/os_str/tests.rs8
-rw-r--r--library/std/src/sys/windows/alloc.rs4
-rw-r--r--library/std/src/sys/windows/c.rs26
-rw-r--r--library/std/src/sys/windows/compat.rs121
-rw-r--r--library/std/src/sys/windows/fs.rs6
-rw-r--r--library/std/src/sys/windows/mod.rs18
-rw-r--r--library/std/src/sys/windows/os.rs6
-rw-r--r--library/std/src/sys/windows/thread_parker.rs27
-rw-r--r--library/std/src/sys_common/wtf8.rs3
-rw-r--r--library/std/src/thread/tests.rs19
-rw-r--r--library/std/src/time/tests.rs3
-rw-r--r--src/bootstrap/bin/rustc.rs15
-rw-r--r--src/bootstrap/builder.rs2
-rw-r--r--src/bootstrap/config.rs39
-rw-r--r--src/bootstrap/native.rs89
-rw-r--r--src/bootstrap/util.rs4
-rw-r--r--src/ci/docker/host-x86_64/arm-android/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/armhf-gnu/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/i686-gnu/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/Dockerfile9
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in22
-rw-r--r--src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt145
-rw-r--r--src/ci/docker/host-x86_64/test-various/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/wasm32/Dockerfile2
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile3
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile4
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile4
-rw-r--r--src/ci/docker/static/gitconfig2
-rw-r--r--src/ci/github-actions/ci.yml18
-rwxr-xr-xsrc/ci/run.sh22
-rwxr-xr-xsrc/ci/scripts/install-clang.sh4
-rw-r--r--src/doc/rustc/src/platform-support/fuchsia.md20
-rw-r--r--src/librustdoc/Cargo.toml2
-rw-r--r--src/librustdoc/clean/auto_trait.rs12
-rw-r--r--src/librustdoc/clean/inline.rs4
-rw-r--r--src/librustdoc/clean/mod.rs35
-rw-r--r--src/librustdoc/clean/types.rs41
-rw-r--r--src/librustdoc/formats/cache.rs2
-rw-r--r--src/librustdoc/html/format.rs7
-rw-r--r--src/librustdoc/html/highlight.rs224
-rw-r--r--src/librustdoc/html/highlight/fixtures/decorations.html6
-rw-r--r--src/librustdoc/html/highlight/fixtures/sample.html15
-rw-r--r--src/librustdoc/html/highlight/fixtures/sample.rs1
-rw-r--r--src/librustdoc/html/highlight/tests.rs7
-rw-r--r--src/librustdoc/html/render/mod.rs33
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css70
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css65
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css65
-rw-r--r--src/librustdoc/html/static/css/themes/light.css67
-rw-r--r--src/librustdoc/json/conversions.rs6
-rw-r--r--src/test/assembly/x86_64-floating-point-clamp.rs25
-rw-r--r--src/test/codegen/README.md22
-rw-r--r--src/test/codegen/pic-relocation-model.rs2
-rw-r--r--src/test/codegen/pie-relocation-model.rs2
-rw-r--r--src/test/codegen/try_question_mark_nop.rs54
-rw-r--r--src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff74
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff4
-rw-r--r--src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/aggregate.rs1
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff7
-rw-r--r--src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff7
-rw-r--r--src/test/mir-opt/const_prop/array_index.rs1
-rw-r--r--src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff10
-rw-r--r--src/test/mir-opt/const_prop/bad_op_div_by_zero.rs1
-rw-r--r--src/test/mir-opt/const_prop/boolean_identities.rs1
-rw-r--r--src/test/mir-opt/const_prop/boxes.main.ConstProp.diff7
-rw-r--r--src/test/mir-opt/const_prop/boxes.rs1
-rw-r--r--src/test/mir-opt/const_prop/cast.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/cast.rs1
-rw-r--r--src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/checked_add.rs1
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff6
-rw-r--r--src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs1
-rw-r--r--src/test/mir-opt/const_prop/control-flow-simplification.rs7
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff2
-rw-r--r--src/test/mir-opt/const_prop/discriminant.rs1
-rw-r--r--src/test/mir-opt/const_prop/indirect.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/indirect.rs1
-rw-r--r--src/test/mir-opt/const_prop/issue-66971.rs1
-rw-r--r--src/test/mir-opt/const_prop/issue-67019.rs1
-rw-r--r--src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/mult_by_zero.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_no_prop.rs1
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs1
-rw-r--r--src/test/mir-opt/const_prop/optimizes_into_variable.rs1
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff4
-rw-r--r--src/test/mir-opt/const_prop/read_immutable_static.rs1
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff2
-rw-r--r--src/test/mir-opt/const_prop/ref_deref_project.rs1
-rw-r--r--src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir26
-rw-r--r--src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir108
-rw-r--r--src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir52
-rw-r--r--src/test/mir-opt/inline/cycle.g.Inline.diff28
-rw-r--r--src/test/mir-opt/inline/cycle.main.Inline.diff50
-rw-r--r--src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff30
-rw-r--r--src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff12
-rw-r--r--src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir22
-rw-r--r--src/test/mir-opt/inline/inline_cycle.one.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_cycle.two.Inline.diff30
-rw-r--r--src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_diverging.f.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_diverging.h.Inline.diff34
-rw-r--r--src/test/mir-opt/inline/inline_generator.main.Inline.diff94
-rw-r--r--src/test/mir-opt/inline/inline_options.main.Inline.after.mir24
-rw-r--r--src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir26
-rw-r--r--src/test/mir-opt/inline/inline_specialization.main.Inline.diff2
-rw-r--r--src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir12
-rw-r--r--src/test/mir-opt/inline/polymorphic-recursion.rs25
-rw-r--r--src/test/mir-opt/issue-91633.rs31
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff12
-rw-r--r--src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff12
-rw-r--r--src/test/mir-opt/issue_91633.bar.mir_map.0.mir39
-rw-r--r--src/test/mir-opt/issue_91633.foo.mir_map.0.mir57
-rw-r--r--src/test/mir-opt/issue_91633.fun.mir_map.0.mir35
-rw-r--r--src/test/mir-opt/issue_91633.hey.mir_map.0.mir35
-rw-r--r--src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir18
-rw-r--r--src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir16
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff12
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff12
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff12
-rw-r--r--src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff12
-rw-r--r--src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir16
-rw-r--r--src/test/mir-opt/separate_const_switch.identity.ConstProp.diff20
-rw-r--r--src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff27
-rw-r--r--src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff28
-rw-r--r--src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir12
-rw-r--r--src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff43
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff12
-rw-r--r--src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff12
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff12
-rw-r--r--src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff12
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff22
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff18
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir18
-rw-r--r--src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir14
-rw-r--r--src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir2
-rw-r--r--src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir2
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir24
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff34
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir28
-rw-r--r--src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff48
-rw-r--r--src/test/mir-opt/unreachable.main.UnreachablePropagation.diff9
-rw-r--r--src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff25
-rw-r--r--src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir2
-rw-r--r--src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir2
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt6
-rw-r--r--src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt5
-rw-r--r--src/test/rustdoc-gui/pocket-menu.goml2
-rw-r--r--src/test/rustdoc-gui/search-filter.goml2
-rw-r--r--src/test/rustdoc-gui/search-form-elements.goml243
-rw-r--r--src/test/rustdoc-gui/search-input.goml7
-rw-r--r--src/test/rustdoc/issue-100679-sidebar-links-deref.rs30
-rw-r--r--src/test/rustdoc/issue-32374.rs14
-rw-r--r--src/test/rustdoc/issue-41783.codeblock.html4
-rw-r--r--src/test/rustdoc/issue-41783.rs6
-rw-r--r--src/test/ui-fulldeps/internal-lints/diagnostics.rs2
-rw-r--r--src/test/ui-fulldeps/pprust-expr-roundtrip.rs5
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs211
-rw-r--r--src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr338
-rw-r--r--src/test/ui/associated-consts/defaults-cyclic-fail.stderr4
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr2
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr2
-rw-r--r--src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr2
-rw-r--r--src/test/ui/associated-types/associated-types-eq-3.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-bound.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr4
-rw-r--r--src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr8
-rw-r--r--src/test/ui/associated-types/associated-types-path-2.stderr10
-rw-r--r--src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr4
-rw-r--r--src/test/ui/associated-types/defaults-suitability.stderr6
-rw-r--r--src/test/ui/associated-types/higher-ranked-projection.badbase.stderr17
-rw-r--r--src/test/ui/associated-types/higher-ranked-projection.badnll.stderr2
-rw-r--r--src/test/ui/associated-types/hr-associated-type-bound-2.stderr4
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-1.stderr4
-rw-r--r--src/test/ui/associated-types/impl-wf-cycle-2.stderr2
-rw-r--r--src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr6
-rw-r--r--src/test/ui/associated-types/issue-44153.stderr2
-rw-r--r--src/test/ui/associated-types/issue-59324.stderr14
-rw-r--r--src/test/ui/associated-types/issue-65774-1.stderr2
-rw-r--r--src/test/ui/associated-types/substs-ppaux.normal.stderr2
-rw-r--r--src/test/ui/associated-types/substs-ppaux.verbose.stderr2
-rw-r--r--src/test/ui/async-await/issue-67252-unnamed-future.stderr10
-rw-r--r--src/test/ui/async-await/issue-68112.stderr16
-rw-r--r--src/test/ui/async-await/issue-70594.stderr2
-rw-r--r--src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-62009-1.stderr2
-rw-r--r--src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr10
-rw-r--r--src/test/ui/async-await/unnecessary-await.stderr2
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr4
-rw-r--r--src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr6
-rw-r--r--src/test/ui/block-result/issue-22645.stderr2
-rw-r--r--src/test/ui/borrowck/issue-64453.stderr1
-rw-r--r--src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr5
-rw-r--r--src/test/ui/chalkify/type_wf.rs4
-rw-r--r--src/test/ui/chalkify/type_wf.stderr6
-rw-r--r--src/test/ui/check-static-values-constraints.stderr1
-rw-r--r--src/test/ui/closure_context/issue-26046-fn-mut.stderr2
-rw-r--r--src/test/ui/closure_context/issue-26046-fn-once.stderr2
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr10
-rw-r--r--src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr10
-rw-r--r--src/test/ui/closures/closure-move-sync.stderr22
-rw-r--r--src/test/ui/closures/closure-wrong-kind.stderr10
-rw-r--r--src/test/ui/coherence/issue-100191-2.stderr4
-rw-r--r--src/test/ui/const-generics/defaults/trait_objects_fail.stderr8
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr24
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr4
-rw-r--r--src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr8
-rw-r--r--src/test/ui/consts/const-block-const-bound.stderr4
-rw-r--r--src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr2
-rw-r--r--src/test/ui/consts/const-blocks/migrate-fail.stderr4
-rw-r--r--src/test/ui/consts/const-blocks/nll-fail.stderr4
-rw-r--r--src/test/ui/consts/const-blocks/trait-error.stderr2
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr26
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr26
-rw-r--r--src/test/ui/consts/const-eval/ub-wide-ptr.rs6
-rw-r--r--src/test/ui/consts/issue-32829-2.stderr2
-rw-r--r--src/test/ui/consts/issue-36163.stderr2
-rw-r--r--src/test/ui/consts/mir_check_nonconst.stderr1
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs1
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr22
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-enum.rs3
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-enum.stderr22
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-struct.rs1
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-struct.stderr22
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs1
-rw-r--r--src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr22
-rw-r--r--src/test/ui/derives/deriving-copyclone.stderr12
-rw-r--r--src/test/ui/derives/deriving-no-inner-impl-error-message.rs1
-rw-r--r--src/test/ui/derives/deriving-no-inner-impl-error-message.stderr24
-rw-r--r--src/test/ui/deriving/deriving-all-codegen.stdout57
-rw-r--r--src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr6
-rw-r--r--src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr6
-rw-r--r--src/test/ui/drop/drop-foreign-fundamental.rs23
-rw-r--r--src/test/ui/drop/drop-foreign-fundamental.stderr9
-rw-r--r--src/test/ui/dropck/drop-on-non-struct.rs7
-rw-r--r--src/test/ui/dropck/drop-on-non-struct.stderr4
-rw-r--r--src/test/ui/error-codes/E0117.rs2
-rw-r--r--src/test/ui/error-codes/E0117.stderr4
-rw-r--r--src/test/ui/error-codes/E0120.stderr4
-rw-r--r--src/test/ui/error-codes/E0275.stderr4
-rw-r--r--src/test/ui/error-codes/E0277-2.stderr4
-rw-r--r--src/test/ui/extern/extern-types-unsized.stderr12
-rw-r--r--src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr4
-rw-r--r--src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs30
-rw-r--r--src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr21
-rw-r--r--src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs26
-rw-r--r--src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr24
-rw-r--r--src/test/ui/fmt/ifmt-unimpl.stderr2
-rw-r--r--src/test/ui/fmt/send-sync.stderr14
-rw-r--r--src/test/ui/for/for-c-in-str.rs2
-rw-r--r--src/test/ui/for/for-c-in-str.stderr2
-rw-r--r--src/test/ui/for/for-loop-bogosity.stderr2
-rw-r--r--src/test/ui/generator/drop-tracking-parent-expression.stderr12
-rw-r--r--src/test/ui/generator/drop-yield-twice.stderr12
-rw-r--r--src/test/ui/generator/generator-yielding-or-returning-itself.stderr26
-rw-r--r--src/test/ui/generator/issue-68112.rs3
-rw-r--r--src/test/ui/generator/issue-68112.stderr12
-rw-r--r--src/test/ui/generator/not-send-sync.stderr28
-rw-r--r--src/test/ui/generator/partial-drop.stderr39
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-1.stderr12
-rw-r--r--src/test/ui/generator/print/generator-print-verbose-2.stderr28
-rw-r--r--src/test/ui/generator/yield-outside-generator-issue-78653.stderr2
-rw-r--r--src/test/ui/generic-associated-types/bugs/issue-88460.stderr6
-rw-r--r--src/test/ui/generic-associated-types/impl_bounds.stderr4
-rw-r--r--src/test/ui/generic-associated-types/issue-74824.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-76535.base.stderr2
-rw-r--r--src/test/ui/generic-associated-types/issue-79422.base.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr2
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr6
-rw-r--r--src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr6
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.rs9
-rw-r--r--src/test/ui/impl-trait/issues/issue-86800.stderr25
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.rs10
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait.stderr16
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.rs2
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait2.stderr8
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.rs2
-rw-r--r--src/test/ui/impl-trait/nested-return-type2-tait3.stderr8
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.rs8
-rw-r--r--src/test/ui/impl-trait/nested-return-type2.stderr16
-rw-r--r--src/test/ui/impl-trait/nested_impl_trait.stderr4
-rw-r--r--src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr2
-rw-r--r--src/test/ui/implied-bounds/issue-100690.rs45
-rw-r--r--src/test/ui/implied-bounds/issue-100690.stderr22
-rw-r--r--src/test/ui/index-help.stderr2
-rw-r--r--src/test/ui/indexing-requires-a-uint.stderr2
-rw-r--r--src/test/ui/inference/issue-71732.stderr6
-rw-r--r--src/test/ui/inference/issue-86162-1.stderr2
-rw-r--r--src/test/ui/inference/issue-86162-2.stderr2
-rw-r--r--src/test/ui/integral-indexing.stderr16
-rw-r--r--src/test/ui/interior-mutability/interior-mutability.stderr8
-rw-r--r--src/test/ui/issues/issue-100605.rs9
-rw-r--r--src/test/ui/issues/issue-100605.stderr46
-rw-r--r--src/test/ui/issues/issue-16538.mir.stderr1
-rw-r--r--src/test/ui/issues/issue-16538.thir.stderr1
-rw-r--r--src/test/ui/issues/issue-17252.stderr2
-rw-r--r--src/test/ui/issues/issue-18611.stderr8
-rw-r--r--src/test/ui/issues/issue-20162.stderr6
-rw-r--r--src/test/ui/issues/issue-20413.stderr16
-rw-r--r--src/test/ui/issues/issue-20605.stderr4
-rw-r--r--src/test/ui/issues/issue-20831-debruijn.stderr24
-rw-r--r--src/test/ui/issues/issue-21763.stderr6
-rw-r--r--src/test/ui/issues/issue-22872.stderr2
-rw-r--r--src/test/ui/issues/issue-23122-2.stderr7
-rw-r--r--src/test/ui/issues/issue-23302-3.stderr4
-rw-r--r--src/test/ui/issues/issue-25901.stderr1
-rw-r--r--src/test/ui/issues/issue-31173.rs2
-rw-r--r--src/test/ui/issues/issue-31173.stderr40
-rw-r--r--src/test/ui/issues/issue-32709.stderr2
-rw-r--r--src/test/ui/issues/issue-33941.stderr12
-rw-r--r--src/test/ui/issues/issue-34334.stderr6
-rw-r--r--src/test/ui/issues/issue-34349.stderr10
-rw-r--r--src/test/ui/issues/issue-35570.rs3
-rw-r--r--src/test/ui/issues/issue-35570.stderr12
-rw-r--r--src/test/ui/issues/issue-38821.stderr2
-rw-r--r--src/test/ui/issues/issue-39970.stderr2
-rw-r--r--src/test/ui/issues/issue-40827.stderr4
-rw-r--r--src/test/ui/issues/issue-41974.stderr4
-rw-r--r--src/test/ui/issues/issue-59488.rs1
-rw-r--r--src/test/ui/issues/issue-59488.stderr21
-rw-r--r--src/test/ui/issues/issue-60218.stderr4
-rw-r--r--src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr12
-rw-r--r--src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr2
-rw-r--r--src/test/ui/issues/issue-69455.stderr2
-rw-r--r--src/test/ui/issues/issue-7364.stderr2
-rw-r--r--src/test/ui/iterators/collect-into-array.rs1
-rw-r--r--src/test/ui/iterators/collect-into-array.stderr6
-rw-r--r--src/test/ui/iterators/collect-into-slice.rs5
-rw-r--r--src/test/ui/iterators/collect-into-slice.stderr23
-rw-r--r--src/test/ui/iterators/integral.stderr24
-rw-r--r--src/test/ui/iterators/issue-28098.stderr4
-rw-r--r--src/test/ui/iterators/ranges.stderr4
-rw-r--r--src/test/ui/iterators/string.stderr4
-rw-r--r--src/test/ui/kindck/kindck-impl-type-params-2.rs2
-rw-r--r--src/test/ui/kindck/kindck-impl-type-params-2.stderr4
-rw-r--r--src/test/ui/kindck/kindck-impl-type-params.stderr12
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr6
-rw-r--r--src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr6
-rw-r--r--src/test/ui/kindck/kindck-nonsendable-1.stderr10
-rw-r--r--src/test/ui/kindck/kindck-send-object.stderr12
-rw-r--r--src/test/ui/kindck/kindck-send-object1.stderr12
-rw-r--r--src/test/ui/kindck/kindck-send-object2.stderr12
-rw-r--r--src/test/ui/kindck/kindck-send-owned.stderr6
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/branches.stderr6
-rw-r--r--src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr12
-rw-r--r--src/test/ui/lexical-scopes.stderr2
-rw-r--r--src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs30
-rw-r--r--src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr27
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr2
-rw-r--r--src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr2
-rw-r--r--src/test/ui/macros/stringify.rs7
-rw-r--r--src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr6
-rw-r--r--src/test/ui/mutexguard-sync.stderr2
-rw-r--r--src/test/ui/never_type/defaulted-never-note.fallback.stderr6
-rw-r--r--src/test/ui/never_type/defaulted-never-note.rs1
-rw-r--r--src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr6
-rw-r--r--src/test/ui/never_type/feature-gate-never_type_fallback.stderr8
-rw-r--r--src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr6
-rw-r--r--src/test/ui/nll/normalization-bounds-error.stderr8
-rw-r--r--src/test/ui/no-send-res-ports.stderr17
-rw-r--r--src/test/ui/not-clone-closure.stderr6
-rw-r--r--src/test/ui/not-panic/not-panic-safe-2.stderr12
-rw-r--r--src/test/ui/not-panic/not-panic-safe-3.stderr12
-rw-r--r--src/test/ui/not-panic/not-panic-safe-4.stderr12
-rw-r--r--src/test/ui/not-panic/not-panic-safe-5.stderr6
-rw-r--r--src/test/ui/not-panic/not-panic-safe-6.stderr12
-rw-r--r--src/test/ui/object-safety/issue-19538.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr4
-rw-r--r--src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/on-unimplemented/multiple-impls.stderr12
-rw-r--r--src/test/ui/on-unimplemented/on-impl.stderr4
-rw-r--r--src/test/ui/on-unimplemented/slice-index.stderr4
-rw-r--r--src/test/ui/or-patterns/inner-or-pat.or3.stderr11
-rw-r--r--src/test/ui/or-patterns/inner-or-pat.or4.stderr11
-rw-r--r--src/test/ui/or-patterns/inner-or-pat.rs73
-rw-r--r--src/test/ui/or-patterns/or-patterns-syntactic-pass.rs16
-rw-r--r--src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr13
-rw-r--r--src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs4
-rw-r--r--src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr24
-rw-r--r--src/test/ui/parser/fn-defined-using-def.rs10
-rw-r--r--src/test/ui/parser/fn-defined-using-def.stderr10
-rw-r--r--src/test/ui/parser/fn-defined-using-fun.rs10
-rw-r--r--src/test/ui/parser/fn-defined-using-fun.stderr10
-rw-r--r--src/test/ui/parser/fn-defined-using-func.rs10
-rw-r--r--src/test/ui/parser/fn-defined-using-func.stderr10
-rw-r--r--src/test/ui/parser/fn-defined-using-function.rs10
-rw-r--r--src/test/ui/parser/fn-defined-using-function.stderr10
-rw-r--r--src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr4
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.rs47
-rw-r--r--src/test/ui/parser/kw-in-trait-bounds.stderr171
-rw-r--r--src/test/ui/parser/struct-literal-in-for.stderr2
-rw-r--r--src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr30
-rw-r--r--src/test/ui/pattern/rest-pat-syntactic.rs5
-rw-r--r--src/test/ui/pattern/rest-pat-syntactic.stderr24
-rw-r--r--src/test/ui/phantom-auto-trait.stderr4
-rw-r--r--src/test/ui/proc-macro/signature.stderr5
-rw-r--r--src/test/ui/range/range-1.stderr6
-rw-r--r--src/test/ui/recursion/issue-83150.stderr6
-rw-r--r--src/test/ui/recursion/issue-95134.rs28
-rw-r--r--src/test/ui/recursion/issue-95134.stderr7
-rw-r--r--src/test/ui/regions/outlives-with-missing.rs16
-rw-r--r--src/test/ui/regions/outlives-with-missing.stderr12
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs3
-rw-r--r--src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr17
-rw-r--r--src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.rs21
-rw-r--r--src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr12
-rw-r--r--src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr8
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr10
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs29
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr12
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs2
-rw-r--r--src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr6
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr2
-rw-r--r--src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr2
-rw-r--r--src/test/ui/span/issue-35987.stderr4
-rw-r--r--src/test/ui/span/lint-unused-unsafe-thir.rs4
-rw-r--r--src/test/ui/span/lint-unused-unsafe-thir.stderr18
-rw-r--r--src/test/ui/span/lint-unused-unsafe.mir.stderr548
-rw-r--r--src/test/ui/span/lint-unused-unsafe.rs74
-rw-r--r--src/test/ui/specialization/default-generic-associated-type-bound.stderr2
-rw-r--r--src/test/ui/specialization/issue-38091-2.stderr2
-rw-r--r--src/test/ui/specialization/issue-39448.stderr4
-rw-r--r--src/test/ui/specialization/issue-45814.stderr4
-rw-r--r--src/test/ui/specialization/min_specialization/issue-79224.stderr22
-rw-r--r--src/test/ui/static/static-vec-repeat-not-constant.stderr1
-rw-r--r--src/test/ui/stats/hir-stats.stderr156
-rw-r--r--src/test/ui/str/str-idx.stderr4
-rw-r--r--src/test/ui/str/str-mut-idx.stderr4
-rw-r--r--src/test/ui/suggestions/as-ref-2.fixed13
-rw-r--r--src/test/ui/suggestions/as-ref-2.rs2
-rw-r--r--src/test/ui/suggestions/as-ref-2.stderr10
-rw-r--r--src/test/ui/suggestions/derive-clone-for-eq.stderr2
-rw-r--r--src/test/ui/suggestions/derive-macro-missing-bounds.stderr16
-rw-r--r--src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr12
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr6
-rw-r--r--src/test/ui/suggestions/imm-ref-trait-object-literal.stderr2
-rw-r--r--src/test/ui/suggestions/into-str.stderr2
-rw-r--r--src/test/ui/suggestions/issue-62843.stderr4
-rw-r--r--src/test/ui/suggestions/issue-71394-no-from-impl.stderr8
-rw-r--r--src/test/ui/suggestions/issue-84973-2.stderr2
-rw-r--r--src/test/ui/suggestions/issue-84973-blacklist.stderr6
-rw-r--r--src/test/ui/suggestions/issue-84973-negative.stderr2
-rw-r--r--src/test/ui/suggestions/issue-84973.stderr2
-rw-r--r--src/test/ui/suggestions/issue-96223.stderr4
-rw-r--r--src/test/ui/suggestions/issue-96555.stderr6
-rw-r--r--src/test/ui/suggestions/many-type-ascription.rs4
-rw-r--r--src/test/ui/suggestions/many-type-ascription.stderr12
-rw-r--r--src/test/ui/suggestions/option-content-move.fixed39
-rw-r--r--src/test/ui/suggestions/option-content-move.rs2
-rw-r--r--src/test/ui/suggestions/option-content-move.stderr14
-rw-r--r--src/test/ui/suggestions/slice-issue-87994.stderr16
-rw-r--r--src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed15
-rw-r--r--src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs15
-rw-r--r--src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr25
-rw-r--r--src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr4
-rw-r--r--src/test/ui/suggestions/suggest-dereferencing-index.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr6
-rw-r--r--src/test/ui/suggestions/suggest-remove-refs-1.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-remove-refs-2.stderr2
-rw-r--r--src/test/ui/suggestions/suggest-remove-refs-3.stderr2
-rw-r--r--src/test/ui/suggestions/type-ascription-and-other-error.rs6
-rw-r--r--src/test/ui/suggestions/type-ascription-and-other-error.stderr8
-rw-r--r--src/test/ui/traits/alias/cross-crate.stderr4
-rw-r--r--src/test/ui/traits/alias/self-in-const-generics.rs12
-rw-r--r--src/test/ui/traits/alias/self-in-const-generics.stderr11
-rw-r--r--src/test/ui/traits/alias/self-in-generics.rs7
-rw-r--r--src/test/ui/traits/alias/self-in-generics.stderr2
-rw-r--r--src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr4
-rw-r--r--src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr4
-rw-r--r--src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr4
-rw-r--r--src/test/ui/traits/bad-method-typaram-kind.stderr4
-rw-r--r--src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs3
-rw-r--r--src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr8
-rw-r--r--src/test/ui/traits/bound/on-structs-and-enums-locals.rs2
-rw-r--r--src/test/ui/traits/bound/on-structs-and-enums-locals.stderr6
-rw-r--r--src/test/ui/traits/bound/on-structs-and-enums-xc1.rs2
-rw-r--r--src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr6
-rw-r--r--src/test/ui/traits/cycle-cache-err-60010.stderr4
-rw-r--r--src/test/ui/traits/inductive-overflow/lifetime.rs2
-rw-r--r--src/test/ui/traits/inductive-overflow/lifetime.stderr4
-rw-r--r--src/test/ui/traits/inductive-overflow/simultaneous.stderr2
-rw-r--r--src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr2
-rw-r--r--src/test/ui/traits/inductive-overflow/supertrait.stderr2
-rw-r--r--src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr30
-rw-r--r--src/test/ui/traits/issue-18400.stderr4
-rw-r--r--src/test/ui/traits/issue-20692.stderr2
-rw-r--r--src/test/ui/traits/issue-38604.stderr2
-rw-r--r--src/test/ui/traits/issue-71036.rs2
-rw-r--r--src/test/ui/traits/issue-71036.stderr2
-rw-r--r--src/test/ui/traits/issue-71136.stderr2
-rw-r--r--src/test/ui/traits/issue-77982.stderr8
-rw-r--r--src/test/ui/traits/issue-82830.stderr2
-rw-r--r--src/test/ui/traits/issue-91594.stderr6
-rw-r--r--src/test/ui/traits/issue-91949-hangs-on-recursion.stderr4
-rw-r--r--src/test/ui/traits/issue-97576.stderr8
-rw-r--r--src/test/ui/traits/multidispatch-convert-ambig-dest.stderr10
-rw-r--r--src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr8
-rw-r--r--src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr2
-rw-r--r--src/test/ui/traits/object/safety.stderr2
-rw-r--r--src/test/ui/traits/suggest-deferences/issue-39029.stderr12
-rw-r--r--src/test/ui/traits/suggest-deferences/issue-62530.stderr10
-rw-r--r--src/test/ui/traits/suggest-deferences/multiple-0.stderr10
-rw-r--r--src/test/ui/traits/suggest-deferences/root-obligation.stderr4
-rw-r--r--src/test/ui/traits/suggest-where-clause.stderr4
-rw-r--r--src/test/ui/traits/test-2.stderr2
-rw-r--r--src/test/ui/transmutability/references.stderr4
-rw-r--r--src/test/ui/try-block/try-block-bad-type.stderr2
-rw-r--r--src/test/ui/try-trait/bad-interconversion.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr6
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr8
-rw-r--r--src/test/ui/type-alias-impl-trait/issue-90400-2.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr2
-rw-r--r--src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr4
-rw-r--r--src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr2
-rw-r--r--src/test/ui/type/type-params-in-different-spaces-2.stderr12
-rw-r--r--src/test/ui/typeck/issue-90101.stderr2
-rw-r--r--src/test/ui/typeck/issue-91633.rs8
-rw-r--r--src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr8
-rw-r--r--src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr6
-rw-r--r--src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr12
-rw-r--r--src/test/ui/union/union-generic.mirunsafeck.stderr4
-rw-r--r--src/test/ui/union/union-generic.thirunsafeck.stderr4
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr38
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.rs2
-rw-r--r--src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr24
-rw-r--r--src/test/ui/unsized-locals/unsized-exprs.stderr4
-rw-r--r--src/test/ui/unsized/issue-30355.stderr4
-rw-r--r--src/test/ui/unsized/issue-71659.stderr6
-rw-r--r--src/test/ui/unsized/issue-75707.stderr4
-rw-r--r--src/test/ui/unsized/unsized-fn-param.stderr16
-rw-r--r--src/test/ui/unsized/unsized-struct.stderr4
-rw-r--r--src/test/ui/unsized/unsized3.stderr10
-rw-r--r--src/test/ui/wf/hir-wf-check-erase-regions.stderr4
-rw-r--r--src/test/ui/wf/wf-const-type.stderr2
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr6
-rw-r--r--src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr6
-rw-r--r--src/test/ui/wf/wf-foreign-fn-decl-ret.stderr4
-rw-r--r--src/test/ui/wf/wf-static-type.stderr2
-rw-r--r--src/test/ui/wf/wf-unsafe-trait-obj-match.stderr4
-rw-r--r--src/test/ui/where-clauses/where-clause-method-substituion.stderr4
-rw-r--r--src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr6
m---------src/tools/miri16
-rw-r--r--src/tools/rust-analyzer/bench_data/glorious_old_parser2
-rw-r--r--src/tools/rustfmt/src/attr.rs5
-rw-r--r--src/tools/rustfmt/src/imports.rs4
-rw-r--r--src/tools/rustfmt/src/modules.rs8
-rw-r--r--src/tools/rustfmt/src/parse/parser.rs2
-rw-r--r--src/tools/tidy/src/style.rs15
-rw-r--r--triagebot.toml16
841 files changed, 10551 insertions, 6597 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7eb41fec36a..11b115cb2ff 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -391,24 +391,28 @@ jobs:
             env:
               RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --set llvm.allow-old-toolchain"
               SCRIPT: make ci-mingw-subset-1
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             os: windows-latest-xl
           - name: i686-mingw-2
             env:
               RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --set llvm.allow-old-toolchain"
               SCRIPT: make ci-mingw-subset-2
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             os: windows-latest-xl
           - name: x86_64-mingw-1
             env:
               SCRIPT: make ci-mingw-subset-1
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler --set llvm.allow-old-toolchain"
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             os: windows-latest-xl
           - name: x86_64-mingw-2
             env:
               SCRIPT: make ci-mingw-subset-2
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-profiler --set llvm.allow-old-toolchain"
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             os: windows-latest-xl
           - name: dist-x86_64-msvc
@@ -433,6 +437,7 @@ jobs:
           - name: dist-i686-mingw
             env:
               RUST_CONFIGURE_ARGS: "--build=i686-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain"
+              NO_DOWNLOAD_CI_LLVM: 1
               SCRIPT: python x.py dist
               CUSTOM_MINGW: 1
               DIST_REQUIRE_ALL_TOOLS: 1
@@ -441,6 +446,7 @@ jobs:
             env:
               SCRIPT: python x.py dist
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-gnu --enable-full-tools --enable-profiler --set llvm.allow-old-toolchain"
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
               DIST_REQUIRE_ALL_TOOLS: 1
             os: windows-latest-xl
diff --git a/.gitignore b/.gitignore
index a6625ac2ac4..b16fb6341c2 100644
--- a/.gitignore
+++ b/.gitignore
@@ -42,6 +42,7 @@ no_llvm_build
 /llvm/
 /mingw-build/
 /build/
+/build-rust-analyzer/
 /dist/
 /unicode-downloads
 /target
diff --git a/.reuse/dep5 b/.reuse/dep5
new file mode 100644
index 00000000000..e040f73b9e1
--- /dev/null
+++ b/.reuse/dep5
@@ -0,0 +1,28 @@
+Format: https://www.debian.org/doc/packaging-manuals/copyright-format/1.0/
+Files-Excluded:
+ src/llvm-project
+
+Files: *
+Copyright: The Rust Project Developers (see https://thanks.rust-lang.org)
+License: MIT or Apache-2.0
+
+Files: library/std/src/sync/mpsc/mpsc_queue.rs
+       library/std/src/sync/mpsc/spsc_queue.rs
+Copyright: 2010-2011 Dmitry Vyukov
+License: BSD-2-Clause
+
+Files: src/librustdoc/html/static/fonts/FiraSans*
+Copyright: 2014, Mozilla Foundation, 2014, Telefonica S.A.
+License: OFL-1.1
+
+Files: src/librustdoc/html/static/fonts/NanumBarun*
+Copyright: 2010 NAVER Corporation
+License: OFL-1.1
+
+Files: src/librustdoc/html/static/fonts/SourceCodePro*
+Copyright: 2010, 2012 Adobe Systems Incorporated
+License: OFL-1.1
+
+Files: src/librustdoc/html/static/fonts/SourceSerif4*
+Copyright: 2014-2021 Adobe Systems Incorporated
+License: OFL-1.1
diff --git a/Cargo.lock b/Cargo.lock
index b8c8466ffe9..cb245ce0ff8 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1421,9 +1421,9 @@ dependencies = [
 
 [[package]]
 name = "fortanix-sgx-abi"
-version = "0.3.3"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "c56c422ef86062869b2d57ae87270608dc5929969dd130a6e248979cf4fb6ca6"
+checksum = "57cafc2274c10fab234f176b25903ce17e690fca7597090d50880e047a0389c5"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -2415,9 +2415,9 @@ dependencies = [
 
 [[package]]
 name = "minifier"
-version = "0.2.1"
+version = "0.2.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "ac96d1e7a65f206443f95afff6de8f1690c77c97d6fc9c9bb2d2cd0662e9ff9f"
+checksum = "8eb022374af2f446981254e6bf9efb6e2c9e1a53176d395fca02792fd4435729"
 
 [[package]]
 name = "minimal-lexical"
@@ -3595,6 +3595,7 @@ dependencies = [
  "rustc_data_structures",
  "rustc_errors",
  "rustc_feature",
+ "rustc_macros",
  "rustc_parse",
  "rustc_session",
  "rustc_span",
diff --git a/LICENSES/Apache-2.0.txt b/LICENSES/Apache-2.0.txt
new file mode 100644
index 00000000000..137069b8238
--- /dev/null
+++ b/LICENSES/Apache-2.0.txt
@@ -0,0 +1,73 @@
+Apache License
+Version 2.0, January 2004
+http://www.apache.org/licenses/
+
+TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+1. Definitions.
+
+"License" shall mean the terms and conditions for use, reproduction, and distribution as defined by Sections 1 through 9 of this document.
+
+"Licensor" shall mean the copyright owner or entity authorized by the copyright owner that is granting the License.
+
+"Legal Entity" shall mean the union of the acting entity and all other entities that control, are controlled by, or are under common control with that entity. For the purposes of this definition, "control" means (i) the power, direct or indirect, to cause the direction or management of such entity, whether by contract or otherwise, or (ii) ownership of fifty percent (50%) or more of the outstanding shares, or (iii) beneficial ownership of such entity.
+
+"You" (or "Your") shall mean an individual or Legal Entity exercising permissions granted by this License.
+
+"Source" form shall mean the preferred form for making modifications, including but not limited to software source code, documentation source, and configuration files.
+
+"Object" form shall mean any form resulting from mechanical transformation or translation of a Source form, including but not limited to compiled object code, generated documentation, and conversions to other media types.
+
+"Work" shall mean the work of authorship, whether in Source or Object form, made available under the License, as indicated by a copyright notice that is included in or attached to the work (an example is provided in the Appendix below).
+
+"Derivative Works" shall mean any work, whether in Source or Object form, that is based on (or derived from) the Work and for which the editorial revisions, annotations, elaborations, or other modifications represent, as a whole, an original work of authorship. For the purposes of this License, Derivative Works shall not include works that remain separable from, or merely link (or bind by name) to the interfaces of, the Work and Derivative Works thereof.
+
+"Contribution" shall mean any work of authorship, including the original version of the Work and any modifications or additions to that Work or Derivative Works thereof, that is intentionally submitted to Licensor for inclusion in the Work by the copyright owner or by an individual or Legal Entity authorized to submit on behalf of the copyright owner. For the purposes of this definition, "submitted" means any form of electronic, verbal, or written communication sent to the Licensor or its representatives, including but not limited to communication on electronic mailing lists, source code control systems, and issue tracking systems that are managed by, or on behalf of, the Licensor for the purpose of discussing and improving the Work, but excluding communication that is conspicuously marked or otherwise designated in writing by the copyright owner as "Not a Contribution."
+
+"Contributor" shall mean Licensor and any individual or Legal Entity on behalf of whom a Contribution has been received by Licensor and subsequently incorporated within the Work.
+
+2. Grant of Copyright License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable copyright license to reproduce, prepare Derivative Works of, publicly display, publicly perform, sublicense, and distribute the Work and such Derivative Works in Source or Object form.
+
+3. Grant of Patent License. Subject to the terms and conditions of this License, each Contributor hereby grants to You a perpetual, worldwide, non-exclusive, no-charge, royalty-free, irrevocable (except as stated in this section) patent license to make, have made, use, offer to sell, sell, import, and otherwise transfer the Work, where such license applies only to those patent claims licensable by such Contributor that are necessarily infringed by their Contribution(s) alone or by combination of their Contribution(s) with the Work to which such Contribution(s) was submitted. If You institute patent litigation against any entity (including a cross-claim or counterclaim in a lawsuit) alleging that the Work or a Contribution incorporated within the Work constitutes direct or contributory patent infringement, then any patent licenses granted to You under this License for that Work shall terminate as of the date such litigation is filed.
+
+4. Redistribution. You may reproduce and distribute copies of the Work or Derivative Works thereof in any medium, with or without modifications, and in Source or Object form, provided that You meet the following conditions:
+
+     (a) You must give any other recipients of the Work or Derivative Works a copy of this License; and
+
+     (b) You must cause any modified files to carry prominent notices stating that You changed the files; and
+
+     (c) You must retain, in the Source form of any Derivative Works that You distribute, all copyright, patent, trademark, and attribution notices from the Source form of the Work, excluding those notices that do not pertain to any part of the Derivative Works; and
+
+     (d) If the Work includes a "NOTICE" text file as part of its distribution, then any Derivative Works that You distribute must include a readable copy of the attribution notices contained within such NOTICE file, excluding those notices that do not pertain to any part of the Derivative Works, in at least one of the following places: within a NOTICE text file distributed as part of the Derivative Works; within the Source form or documentation, if provided along with the Derivative Works; or, within a display generated by the Derivative Works, if and wherever such third-party notices normally appear. The contents of the NOTICE file are for informational purposes only and do not modify the License. You may add Your own attribution notices within Derivative Works that You distribute, alongside or as an addendum to the NOTICE text from the Work, provided that such additional attribution notices cannot be construed as modifying the License.
+
+     You may add Your own copyright statement to Your modifications and may provide additional or different license terms and conditions for use, reproduction, or distribution of Your modifications, or for any such Derivative Works as a whole, provided Your use, reproduction, and distribution of the Work otherwise complies with the conditions stated in this License.
+
+5. Submission of Contributions. Unless You explicitly state otherwise, any Contribution intentionally submitted for inclusion in the Work by You to the Licensor shall be under the terms and conditions of this License, without any additional terms or conditions. Notwithstanding the above, nothing herein shall supersede or modify the terms of any separate license agreement you may have executed with Licensor regarding such Contributions.
+
+6. Trademarks. This License does not grant permission to use the trade names, trademarks, service marks, or product names of the Licensor, except as required for reasonable and customary use in describing the origin of the Work and reproducing the content of the NOTICE file.
+
+7. Disclaimer of Warranty. Unless required by applicable law or agreed to in writing, Licensor provides the Work (and each Contributor provides its Contributions) on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied, including, without limitation, any warranties or conditions of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A PARTICULAR PURPOSE. You are solely responsible for determining the appropriateness of using or redistributing the Work and assume any risks associated with Your exercise of permissions under this License.
+
+8. Limitation of Liability. In no event and under no legal theory, whether in tort (including negligence), contract, or otherwise, unless required by applicable law (such as deliberate and grossly negligent acts) or agreed to in writing, shall any Contributor be liable to You for damages, including any direct, indirect, special, incidental, or consequential damages of any character arising as a result of this License or out of the use or inability to use the Work (including but not limited to damages for loss of goodwill, work stoppage, computer failure or malfunction, or any and all other commercial damages or losses), even if such Contributor has been advised of the possibility of such damages.
+
+9. Accepting Warranty or Additional Liability. While redistributing the Work or Derivative Works thereof, You may choose to offer, and charge a fee for, acceptance of support, warranty, indemnity, or other liability obligations and/or rights consistent with this License. However, in accepting such obligations, You may act only on Your own behalf and on Your sole responsibility, not on behalf of any other Contributor, and only if You agree to indemnify, defend, and hold each Contributor harmless for any liability incurred by, or claims asserted against, such Contributor by reason of your accepting any such warranty or additional liability.
+
+END OF TERMS AND CONDITIONS
+
+APPENDIX: How to apply the Apache License to your work.
+
+To apply the Apache License to your work, attach the following boilerplate notice, with the fields enclosed by brackets "[]" replaced with your own identifying information. (Don't include the brackets!)  The text should be enclosed in the appropriate comment syntax for the file format. We also recommend that a file or class name and description of purpose be included on the same "printed page" as the copyright notice for easier identification within third-party archives.
+
+Copyright [yyyy] [name of copyright owner]
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
diff --git a/LICENSES/BSD-2-Clause.txt b/LICENSES/BSD-2-Clause.txt
new file mode 100644
index 00000000000..5f662b354cd
--- /dev/null
+++ b/LICENSES/BSD-2-Clause.txt
@@ -0,0 +1,9 @@
+Copyright (c) <year> <owner> 
+
+Redistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:
+
+1. Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.
+
+2. Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
diff --git a/LICENSES/MIT.txt b/LICENSES/MIT.txt
new file mode 100644
index 00000000000..2071b23b0e0
--- /dev/null
+++ b/LICENSES/MIT.txt
@@ -0,0 +1,9 @@
+MIT License
+
+Copyright (c) <year> <copyright holders>
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/LICENSES/OFL-1.1.txt b/LICENSES/OFL-1.1.txt
new file mode 100644
index 00000000000..6fe84ee21eb
--- /dev/null
+++ b/LICENSES/OFL-1.1.txt
@@ -0,0 +1,43 @@
+SIL OPEN FONT LICENSE
+
+Version 1.1 - 26 February 2007
+
+PREAMBLE
+
+The goals of the Open Font License (OFL) are to stimulate worldwide development of collaborative font projects, to support the font creation efforts of academic and linguistic communities, and to provide a free and open framework in which fonts may be shared and improved in partnership with others.
+
+The OFL allows the licensed fonts to be used, studied, modified and redistributed freely as long as they are not sold by themselves. The fonts, including any derivative works, can be bundled, embedded, redistributed and/or sold with any software provided that any reserved names are not used by derivative works. The fonts and derivatives, however, cannot be released under any other type of license. The requirement for fonts to remain under this license does not apply to any document created using the fonts or their derivatives.
+
+DEFINITIONS
+
+"Font Software" refers to the set of files released by the Copyright Holder(s) under this license and clearly marked as such. This may include source files, build scripts and documentation.
+
+"Reserved Font Name" refers to any names specified as such after the copyright statement(s).
+
+"Original Version" refers to the collection of Font Software components as distributed by the Copyright Holder(s).
+
+"Modified Version" refers to any derivative made by adding to, deleting, or substituting — in part or in whole — any of the components of the Original Version, by changing formats or by porting the Font Software to a new environment.
+
+"Author" refers to any designer, engineer, programmer, technical writer or other person who contributed to the Font Software.
+
+PERMISSION & CONDITIONS
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of the Font Software, to use, study, copy, merge, embed, modify, redistribute, and sell modified and unmodified copies of the Font Software, subject to the following conditions:
+
+1) Neither the Font Software nor any of its individual components, in Original or Modified Versions, may be sold by itself.
+
+2) Original or Modified Versions of the Font Software may be bundled, redistributed and/or sold with any software, provided that each copy contains the above copyright notice and this license. These can be included either as stand-alone text files, human-readable headers or in the appropriate machine-readable metadata fields within text or binary files as long as those fields can be easily viewed by the user.
+
+3) No Modified Version of the Font Software may use the Reserved Font Name(s) unless explicit written permission is granted by the corresponding Copyright Holder. This restriction only applies to the primary font name as presented to the users.
+
+4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font Software shall not be used to promote, endorse or advertise any Modified Version, except to acknowledge the contribution(s) of the Copyright Holder(s) and the Author(s) or with their explicit written permission.
+
+5) The Font Software, modified or unmodified, in part or in whole, must be distributed entirely under this license, and must not be distributed under any other license. The requirement for fonts to remain under this license does not apply to any document created using the Font Software.
+
+TERMINATION
+
+This license becomes null and void if any of the above conditions are not met.
+
+DISCLAIMER
+
+THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM OTHER DEALINGS IN THE FONT SOFTWARE.
diff --git a/compiler/rustc_apfloat/src/lib.rs b/compiler/rustc_apfloat/src/lib.rs
index cfc3d5b15a6..dde368e7b92 100644
--- a/compiler/rustc_apfloat/src/lib.rs
+++ b/compiler/rustc_apfloat/src/lib.rs
@@ -33,6 +33,8 @@
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![no_std]
 #![forbid(unsafe_code)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate alloc;
diff --git a/compiler/rustc_arena/src/lib.rs b/compiler/rustc_arena/src/lib.rs
index 6529f11100d..d2f8ef8eaae 100644
--- a/compiler/rustc_arena/src/lib.rs
+++ b/compiler/rustc_arena/src/lib.rs
@@ -19,6 +19,8 @@
 #![feature(rustc_attrs)]
 #![cfg_attr(test, feature(test))]
 #![feature(strict_provenance)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 use smallvec::SmallVec;
 
@@ -217,7 +219,7 @@ impl<T> TypedArena<T> {
             } else {
                 let ptr = self.ptr.get();
                 // Advance the pointer.
-                self.ptr.set(self.ptr.get().offset(1));
+                self.ptr.set(self.ptr.get().add(1));
                 // Write into uninitialized memory.
                 ptr::write(ptr, object);
                 &mut *ptr
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 268b0527b1c..598bf771008 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -504,7 +504,7 @@ pub struct WhereEqPredicate {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Crate {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub items: Vec<P<Item>>,
     pub spans: ModSpans,
     /// Must be equal to `CRATE_NODE_ID` after the crate root is expanded, but may hold
@@ -770,7 +770,7 @@ pub enum PatKind {
     Paren(P<Pat>),
 
     /// A macro pattern; pre-expansion.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
 }
 
 #[derive(Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Copy)]
@@ -980,7 +980,7 @@ pub enum StmtKind {
 
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct MacCallStmt {
-    pub mac: MacCall,
+    pub mac: P<MacCall>,
     pub style: MacStmtStyle,
     pub attrs: AttrVec,
     pub tokens: Option<LazyTokenStream>,
@@ -1268,7 +1268,7 @@ impl Expr {
                 id: DUMMY_NODE_ID,
                 kind: ExprKind::Err,
                 span: DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
                 tokens: None,
             },
         )
@@ -1437,7 +1437,7 @@ pub enum ExprKind {
     InlineAsm(P<InlineAsm>),
 
     /// A macro invocation; pre-expansion.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
 
     /// A struct literal expression.
     ///
@@ -2040,7 +2040,7 @@ pub enum TyKind {
     /// Inferred type of a `self` or `&self` argument in a method.
     ImplicitSelf,
     /// A macro in the type position.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
     /// Placeholder for a kind that has failed to be defined.
     Err,
     /// Placeholder for a `va_list`.
@@ -2669,7 +2669,7 @@ impl VariantData {
 /// An item definition.
 #[derive(Clone, Encodable, Decodable, Debug)]
 pub struct Item<K = ItemKind> {
-    pub attrs: Vec<Attribute>,
+    pub attrs: AttrVec,
     pub id: NodeId,
     pub span: Span,
     pub vis: Visibility,
@@ -2877,7 +2877,7 @@ pub enum ItemKind {
     /// A macro invocation.
     ///
     /// E.g., `foo!(..)`.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
 
     /// A macro definition.
     MacroDef(MacroDef),
@@ -2951,7 +2951,7 @@ pub enum AssocItemKind {
     /// An associated type.
     TyAlias(Box<TyAlias>),
     /// A macro expanding to associated items.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
 }
 
 impl AssocItemKind {
@@ -3000,7 +3000,7 @@ pub enum ForeignItemKind {
     /// An foreign type.
     TyAlias(Box<TyAlias>),
     /// A macro expanding to foreign items.
-    MacCall(MacCall),
+    MacCall(P<MacCall>),
 }
 
 impl From<ForeignItemKind> for ItemKind {
@@ -3036,19 +3036,19 @@ mod size_asserts {
     use super::*;
     use rustc_data_structures::static_assert_size;
     // These are in alphabetical order, which is easy to maintain.
-    static_assert_size!(AssocItem, 160);
-    static_assert_size!(AssocItemKind, 72);
+    static_assert_size!(AssocItem, 104);
+    static_assert_size!(AssocItemKind, 32);
     static_assert_size!(Attribute, 32);
     static_assert_size!(Block, 48);
     static_assert_size!(Expr, 104);
     static_assert_size!(ExprKind, 72);
     static_assert_size!(Fn, 192);
-    static_assert_size!(ForeignItem, 160);
-    static_assert_size!(ForeignItemKind, 72);
+    static_assert_size!(ForeignItem, 96);
+    static_assert_size!(ForeignItemKind, 24);
     static_assert_size!(GenericBound, 88);
     static_assert_size!(Generics, 72);
     static_assert_size!(Impl, 200);
-    static_assert_size!(Item, 200);
+    static_assert_size!(Item, 184);
     static_assert_size!(ItemKind, 112);
     static_assert_size!(Lit, 48);
     static_assert_size!(LitKind, 24);
diff --git a/compiler/rustc_ast/src/ast_traits.rs b/compiler/rustc_ast/src/ast_traits.rs
index 1fc5e480215..0947a71b824 100644
--- a/compiler/rustc_ast/src/ast_traits.rs
+++ b/compiler/rustc_ast/src/ast_traits.rs
@@ -270,7 +270,7 @@ pub trait HasAttrs {
     /// during token collection.
     const SUPPORTS_CUSTOM_INNER_ATTRS: bool;
     fn attrs(&self) -> &[Attribute];
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec));
 }
 
 macro_rules! impl_has_attrs {
@@ -283,8 +283,8 @@ macro_rules! impl_has_attrs {
                     &self.attrs
                 }
 
-                fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-                    VecOrAttrVec::visit(&mut self.attrs, f)
+                fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
+                    f(&mut self.attrs)
                 }
             }
         )+
@@ -299,7 +299,7 @@ macro_rules! impl_has_attrs_none {
                 fn attrs(&self) -> &[Attribute] {
                     &[]
                 }
-                fn visit_attrs(&mut self, _f: impl FnOnce(&mut Vec<Attribute>)) {}
+                fn visit_attrs(&mut self, _f: impl FnOnce(&mut AttrVec)) {}
             }
         )+
     };
@@ -330,7 +330,7 @@ impl<T: AstDeref<Target: HasAttrs>> HasAttrs for T {
     fn attrs(&self) -> &[Attribute] {
         self.ast_deref().attrs()
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         self.ast_deref_mut().visit_attrs(f)
     }
 }
@@ -340,7 +340,7 @@ impl<T: HasAttrs> HasAttrs for Option<T> {
     fn attrs(&self) -> &[Attribute] {
         self.as_ref().map(|inner| inner.attrs()).unwrap_or(&[])
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         if let Some(inner) = self.as_mut() {
             inner.visit_attrs(f);
         }
@@ -362,13 +362,13 @@ impl HasAttrs for StmtKind {
         }
     }
 
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         match self {
-            StmtKind::Local(local) => visit_attrvec(&mut local.attrs, f),
+            StmtKind::Local(local) => f(&mut local.attrs),
             StmtKind::Expr(expr) | StmtKind::Semi(expr) => expr.visit_attrs(f),
             StmtKind::Item(item) => item.visit_attrs(f),
             StmtKind::Empty => {}
-            StmtKind::MacCall(mac) => visit_attrvec(&mut mac.attrs, f),
+            StmtKind::MacCall(mac) => f(&mut mac.attrs),
         }
     }
 }
@@ -378,38 +378,11 @@ impl HasAttrs for Stmt {
     fn attrs(&self) -> &[Attribute] {
         self.kind.attrs()
     }
-    fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         self.kind.visit_attrs(f);
     }
 }
 
-/// Helper trait for the impls above. Abstracts over
-/// the two types of attribute fields that AST nodes
-/// may have (`Vec<Attribute>` or `AttrVec`).
-trait VecOrAttrVec {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>));
-}
-
-impl VecOrAttrVec for Vec<Attribute> {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-        f(self)
-    }
-}
-
-impl VecOrAttrVec for AttrVec {
-    fn visit(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
-        visit_attrvec(self, f)
-    }
-}
-
-fn visit_attrvec(attrs: &mut AttrVec, f: impl FnOnce(&mut Vec<Attribute>)) {
-    crate::mut_visit::visit_clobber(attrs, |attrs| {
-        let mut vec = attrs.into();
-        f(&mut vec);
-        vec.into()
-    });
-}
-
 /// A newtype around an AST node that implements the traits above if the node implements them.
 pub struct AstNodeWrapper<Wrapped, Tag> {
     pub wrapped: Wrapped,
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 0d114f1366c..5b72ec2b601 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -12,7 +12,6 @@ use crate::tokenstream::{DelimSpan, Spacing, TokenTree};
 use crate::tokenstream::{LazyTokenStream, TokenStream};
 use crate::util::comments;
 
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_index::bit_set::GrowableBitSet;
 use rustc_span::source_map::BytePos;
 use rustc_span::symbol::{sym, Ident, Symbol};
@@ -487,7 +486,7 @@ impl MetaItemKind {
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ExprKind::Lit(lit.clone()),
                     span: lit.span,
-                    attrs: ThinVec::new(),
+                    attrs: ast::AttrVec::new(),
                     tokens: None,
                 });
                 MacArgs::Eq(span, MacArgsEq::Ast(expr))
diff --git a/compiler/rustc_ast/src/lib.rs b/compiler/rustc_ast/src/lib.rs
index 528fc4816e9..2426a0cb7dd 100644
--- a/compiler/rustc_ast/src/lib.rs
+++ b/compiler/rustc_ast/src/lib.rs
@@ -19,6 +19,8 @@
 #![feature(slice_internals)]
 #![feature(stmt_expr_attributes)]
 #![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 0520319e3be..458d1156ec2 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -14,7 +14,6 @@ use crate::tokenstream::*;
 
 use rustc_data_structures::map_in_place::MapInPlace;
 use rustc_data_structures::sync::Lrc;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
@@ -338,12 +337,7 @@ where
 }
 
 // No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_attrs<T: MutVisitor>(attrs: &mut Vec<Attribute>, vis: &mut T) {
-    visit_vec(attrs, |attr| vis.visit_attribute(attr));
-}
-
-// No `noop_` prefix because there isn't a corresponding method in `MutVisitor`.
-pub fn visit_thin_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
+pub fn visit_attrs<T: MutVisitor>(attrs: &mut AttrVec, vis: &mut T) {
     for attr in attrs.iter_mut() {
         vis.visit_attribute(attr);
     }
@@ -398,7 +392,7 @@ pub fn noop_flat_map_pat_field<T: MutVisitor>(
     vis.visit_ident(ident);
     vis.visit_pat(pat);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     smallvec![fp]
 }
 
@@ -424,7 +418,7 @@ pub fn noop_visit_use_tree<T: MutVisitor>(use_tree: &mut UseTree, vis: &mut T) {
 
 pub fn noop_flat_map_arm<T: MutVisitor>(mut arm: Arm, vis: &mut T) -> SmallVec<[Arm; 1]> {
     let Arm { attrs, pat, guard, body, span, id, is_placeholder: _ } = &mut arm;
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     vis.visit_id(id);
     vis.visit_pat(pat);
     visit_opt(guard, |guard| vis.visit_expr(guard));
@@ -507,7 +501,7 @@ pub fn noop_flat_map_variant<T: MutVisitor>(
     let Variant { ident, vis, attrs, id, data, disr_expr, span, is_placeholder: _ } = &mut variant;
     visitor.visit_ident(ident);
     visitor.visit_vis(vis);
-    visit_thin_attrs(attrs, visitor);
+    visit_attrs(attrs, visitor);
     visitor.visit_id(id);
     visitor.visit_variant_data(data);
     visit_opt(disr_expr, |disr_expr| visitor.visit_anon_const(disr_expr));
@@ -589,7 +583,7 @@ pub fn noop_visit_local<T: MutVisitor>(local: &mut P<Local>, vis: &mut T) {
         }
     }
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_lazy_tts(tokens, vis);
 }
 
@@ -640,7 +634,7 @@ pub fn noop_visit_meta_item<T: MutVisitor>(mi: &mut MetaItem, vis: &mut T) {
 pub fn noop_flat_map_param<T: MutVisitor>(mut param: Param, vis: &mut T) -> SmallVec<[Param; 1]> {
     let Param { attrs, id, pat, span, ty, is_placeholder: _ } = &mut param;
     vis.visit_id(id);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     vis.visit_pat(pat);
     vis.visit_span(span);
     vis.visit_ty(ty);
@@ -882,7 +876,7 @@ pub fn noop_flat_map_generic_param<T: MutVisitor>(
     if let Some(ref mut colon_span) = colon_span {
         vis.visit_span(colon_span);
     }
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_vec(bounds, |bound| noop_visit_param_bound(bound, vis));
     match kind {
         GenericParamKind::Lifetime => {}
@@ -978,7 +972,7 @@ pub fn noop_flat_map_field_def<T: MutVisitor>(
     visitor.visit_vis(vis);
     visitor.visit_id(id);
     visitor.visit_ty(ty);
-    visit_thin_attrs(attrs, visitor);
+    visit_attrs(attrs, visitor);
     smallvec![fd]
 }
 
@@ -991,7 +985,7 @@ pub fn noop_flat_map_expr_field<T: MutVisitor>(
     vis.visit_expr(expr);
     vis.visit_id(id);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     smallvec![f]
 }
 
@@ -1432,7 +1426,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
     }
     vis.visit_id(id);
     vis.visit_span(span);
-    visit_thin_attrs(attrs, vis);
+    visit_attrs(attrs, vis);
     visit_lazy_tts(tokens, vis);
 }
 
@@ -1478,7 +1472,7 @@ pub fn noop_flat_map_stmt_kind<T: MutVisitor>(
         StmtKind::MacCall(mut mac) => {
             let MacCallStmt { mac: mac_, style: _, attrs, tokens } = mac.deref_mut();
             vis.visit_mac_call(mac_);
-            visit_thin_attrs(attrs, vis);
+            visit_attrs(attrs, vis);
             visit_lazy_tts(tokens, vis);
             smallvec![StmtKind::MacCall(mac)]
         }
@@ -1513,12 +1507,6 @@ impl<T: DummyAstNode + 'static> DummyAstNode for P<T> {
     }
 }
 
-impl<T> DummyAstNode for ThinVec<T> {
-    fn dummy() -> Self {
-        Default::default()
-    }
-}
-
 impl DummyAstNode for Item {
     fn dummy() -> Self {
         Item {
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 32dbd2ff47d..bd61f4fa87a 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -6,7 +6,6 @@ use rustc_ast::attr;
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_errors::struct_span_err;
 use rustc_hir as hir;
 use rustc_hir::def::Res;
@@ -448,12 +447,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let lowered_cond = self.with_loop_condition_scope(|t| t.lower_expr(cond));
         let new_cond = self.manage_let_cond(lowered_cond);
         let then = self.lower_block_expr(body);
-        let expr_break = self.expr_break(span, ThinVec::new());
+        let expr_break = self.expr_break(span, AttrVec::new());
         let stmt_break = self.stmt_expr(span, expr_break);
         let else_blk = self.block_all(span, arena_vec![self; stmt_break], None);
-        let else_expr = self.arena.alloc(self.expr_block(else_blk, ThinVec::new()));
+        let else_expr = self.arena.alloc(self.expr_block(else_blk, AttrVec::new()));
         let if_kind = hir::ExprKind::If(new_cond, self.arena.alloc(then), Some(else_expr));
-        let if_expr = self.expr(span, if_kind, ThinVec::new());
+        let if_expr = self.expr(span, if_kind, AttrVec::new());
         let block = self.block_expr(self.arena.alloc(if_expr));
         let span = self.lower_span(span.with_hi(cond.span.hi()));
         let opt_label = self.lower_label(opt_label);
@@ -512,7 +511,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let constructor = self.arena.alloc(self.expr_lang_item_path(
             method_span,
             lang_item,
-            ThinVec::new(),
+            AttrVec::new(),
             None,
         ));
         self.expr_call(overall_span, constructor, std::slice::from_ref(expr))
@@ -635,7 +634,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let gen_future = self.expr_lang_item_path(
             unstable_span,
             hir::LangItem::FromGenerator,
-            ThinVec::new(),
+            AttrVec::new(),
             None,
         );
 
@@ -747,7 +746,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let break_x = self.with_loop_scope(loop_node_id, move |this| {
                 let expr_break =
                     hir::ExprKind::Break(this.lower_loop_destination(None), Some(x_expr));
-                this.arena.alloc(this.expr(gen_future_span, expr_break, ThinVec::new()))
+                this.arena.alloc(this.expr(gen_future_span, expr_break, AttrVec::new()))
             });
             self.arm(ready_pat, break_x)
         };
@@ -780,7 +779,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             let yield_expr = self.expr(
                 span,
                 hir::ExprKind::Yield(unit, hir::YieldSource::Await { expr: Some(expr_hir_id) }),
-                ThinVec::new(),
+                AttrVec::new(),
             );
             let yield_expr = self.arena.alloc(yield_expr);
 
@@ -987,7 +986,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::AsyncGeneratorKind::Closure,
                     |this| this.with_new_scopes(|this| this.lower_expr_mut(body)),
                 );
-                this.expr(fn_decl_span, async_body, ThinVec::new())
+                this.expr(fn_decl_span, async_body, AttrVec::new())
             });
             body_id
         });
@@ -1257,7 +1256,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let ident = self.expr_ident(lhs.span, ident, binding);
         let assign =
             hir::ExprKind::Assign(self.lower_expr(lhs), ident, self.lower_span(eq_sign_span));
-        let expr = self.expr(lhs.span, assign, ThinVec::new());
+        let expr = self.expr(lhs.span, assign, AttrVec::new());
         assignments.push(self.stmt_expr(lhs.span, expr));
         pat
     }
@@ -1299,7 +1298,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let fn_path =
             hir::QPath::LangItem(hir::LangItem::RangeInclusiveNew, self.lower_span(span), None);
         let fn_expr =
-            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), ThinVec::new()));
+            self.arena.alloc(self.expr(span, hir::ExprKind::Path(fn_path), AttrVec::new()));
         hir::ExprKind::Call(fn_expr, arena_vec![self; e1, e2])
     }
 
@@ -1472,7 +1471,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         // `None => break`
         let none_arm = {
             let break_expr =
-                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, ThinVec::new()));
+                self.with_loop_scope(e.id, |this| this.expr_break_alloc(for_span, AttrVec::new()));
             let pat = self.pat_none(for_span);
             self.arm(pat, break_expr)
         };
@@ -1481,7 +1480,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         let some_arm = {
             let some_pat = self.pat_some(pat_span, pat);
             let body_block = self.with_loop_scope(e.id, |this| this.lower_block(body, false));
-            let body_expr = self.arena.alloc(self.expr_block(body_block, ThinVec::new()));
+            let body_expr = self.arena.alloc(self.expr_block(body_block, AttrVec::new()));
             self.arm(some_pat, body_expr)
         };
 
@@ -1596,7 +1595,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             };
             attr::mk_attr_outer(allow)
         };
-        let attrs = vec![attr];
+        let attrs: AttrVec = vec![attr].into();
 
         // `ControlFlow::Continue(val) => #[allow(unreachable_code)] val,`
         let continue_arm = {
@@ -1606,7 +1605,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 span,
                 val_ident,
                 val_pat_nid,
-                ThinVec::from(attrs.clone()),
+                attrs.clone(),
             ));
             let continue_pat = self.pat_cf_continue(unstable_span, val_pat);
             self.arm(continue_pat, val_expr)
@@ -1625,7 +1624,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 self.arena.alloc(residual_expr),
                 unstable_span,
             );
-            let thin_attrs = ThinVec::from(attrs);
             let ret_expr = if let Some(catch_node) = self.catch_scope {
                 let target_id = Ok(self.lower_node_id(catch_node));
                 self.arena.alloc(self.expr(
@@ -1634,13 +1632,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         hir::Destination { label: None, target_id },
                         Some(from_residual_expr),
                     ),
-                    thin_attrs,
+                    attrs,
                 ))
             } else {
                 self.arena.alloc(self.expr(
                     try_span,
                     hir::ExprKind::Ret(Some(from_residual_expr)),
-                    thin_attrs,
+                    attrs,
                 ))
             };
 
@@ -1728,7 +1726,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         arms: &'hir [hir::Arm<'hir>],
         source: hir::MatchSource,
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Match(arg, arms, source), ThinVec::new())
+        self.expr(span, hir::ExprKind::Match(arg, arms, source), AttrVec::new())
     }
 
     fn expr_break(&mut self, span: Span, attrs: AttrVec) -> hir::Expr<'hir> {
@@ -1745,12 +1743,12 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.expr(
             span,
             hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Mut, e),
-            ThinVec::new(),
+            AttrVec::new(),
         )
     }
 
     fn expr_unit(&mut self, sp: Span) -> &'hir hir::Expr<'hir> {
-        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), ThinVec::new()))
+        self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[]), AttrVec::new()))
     }
 
     fn expr_call_mut(
@@ -1759,7 +1757,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         e: &'hir hir::Expr<'hir>,
         args: &'hir [hir::Expr<'hir>],
     ) -> hir::Expr<'hir> {
-        self.expr(span, hir::ExprKind::Call(e, args), ThinVec::new())
+        self.expr(span, hir::ExprKind::Call(e, args), AttrVec::new())
     }
 
     fn expr_call(
@@ -1779,7 +1777,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         hir_id: Option<hir::HirId>,
     ) -> hir::Expr<'hir> {
         let path =
-            self.arena.alloc(self.expr_lang_item_path(span, lang_item, ThinVec::new(), hir_id));
+            self.arena.alloc(self.expr_lang_item_path(span, lang_item, AttrVec::new(), hir_id));
         self.expr_call_mut(span, path, args)
     }
 
@@ -1822,7 +1820,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
         ident: Ident,
         binding: hir::HirId,
     ) -> hir::Expr<'hir> {
-        self.expr_ident_with_attrs(sp, ident, binding, ThinVec::new())
+        self.expr_ident_with_attrs(sp, ident, binding, AttrVec::new())
     }
 
     fn expr_ident_with_attrs(
@@ -1860,13 +1858,13 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 }),
                 None,
             ),
-            ThinVec::new(),
+            AttrVec::new(),
         )
     }
 
     fn expr_block_empty(&mut self, span: Span) -> &'hir hir::Expr<'hir> {
         let blk = self.block_all(span, &[], None);
-        let expr = self.expr_block(blk, ThinVec::new());
+        let expr = self.expr_block(blk, AttrVec::new());
         self.arena.alloc(expr)
     }
 
diff --git a/compiler/rustc_ast_passes/Cargo.toml b/compiler/rustc_ast_passes/Cargo.toml
index 22742b2adbd..37eff9207c1 100644
--- a/compiler/rustc_ast_passes/Cargo.toml
+++ b/compiler/rustc_ast_passes/Cargo.toml
@@ -11,6 +11,7 @@ rustc_attr = { path = "../rustc_attr" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_feature = { path = "../rustc_feature" }
+rustc_macros = { path = "../rustc_macros" }
 rustc_parse = { path = "../rustc_parse" }
 rustc_session = { path = "../rustc_session" }
 rustc_span = { path = "../rustc_span" }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index e61dfef7bd3..b337e5328c5 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -13,7 +13,7 @@ use rustc_ast::walk_list;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust::{self, State};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::{error_code, pluralize, struct_span_err, Applicability, Diagnostic};
+use rustc_errors::{error_code, fluent, pluralize, struct_span_err, Applicability};
 use rustc_parse::validate_attr;
 use rustc_session::lint::builtin::{
     DEPRECATED_WHERE_CLAUSE_LOCATION, MISSING_ABI, PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -27,6 +27,8 @@ use rustc_target::spec::abi;
 use std::mem;
 use std::ops::{Deref, DerefMut};
 
+use crate::errors::*;
+
 const MORE_EXTERN: &str =
     "for more information, visit https://doc.rust-lang.org/std/keyword.extern.html";
 
@@ -117,23 +119,7 @@ impl<'a> AstValidator<'a> {
 
     /// Emits an error banning the `let` expression provided in the given location.
     fn ban_let_expr(&self, expr: &'a Expr, forbidden_let_reason: ForbiddenLetReason) {
-        let err = "`let` expressions are not supported here";
-        let mut diag = self.session.struct_span_err(expr.span, err);
-        diag.note("only supported directly in conditions of `if` and `while` expressions");
-        match forbidden_let_reason {
-            ForbiddenLetReason::GenericForbidden => {}
-            ForbiddenLetReason::NotSupportedOr(span) => {
-                diag.span_note(span, "`||` operators are not supported in let chain expressions");
-            }
-            ForbiddenLetReason::NotSupportedParentheses(span) => {
-                diag.span_note(
-                    span,
-                    "`let`s wrapped in parentheses are not supported in a context with let \
-                    chains",
-                );
-            }
-        }
-        diag.emit();
+        self.session.emit_err(ForbiddenLet { span: expr.span, reason: forbidden_let_reason });
     }
 
     fn check_gat_where(
@@ -163,7 +149,7 @@ impl<'a> AstValidator<'a> {
                 DEPRECATED_WHERE_CLAUSE_LOCATION,
                 id,
                 where_clauses.0.1,
-                "where clause not allowed here",
+                fluent::ast_passes::deprecated_where_clause_location,
                 BuiltinLintDiagnostics::DeprecatedWhereclauseLocation(
                     where_clauses.1.1.shrink_to_hi(),
                     suggestion,
@@ -193,10 +179,7 @@ impl<'a> AstValidator<'a> {
             AssocConstraintKind::Equality { .. } => {}
             AssocConstraintKind::Bound { .. } => {
                 if self.is_assoc_ty_bound_banned {
-                    self.err_handler().span_err(
-                        constraint.span,
-                        "associated type bounds are not allowed within structs, enums, or unions",
-                    );
+                    self.session.emit_err(ForbiddenAssocConstraint { span: constraint.span });
                 }
             }
         }
@@ -268,31 +251,26 @@ impl<'a> AstValidator<'a> {
     fn check_lifetime(&self, ident: Ident) {
         let valid_names = [kw::UnderscoreLifetime, kw::StaticLifetime, kw::Empty];
         if !valid_names.contains(&ident.name) && ident.without_first_quote().is_reserved() {
-            self.err_handler().span_err(ident.span, "lifetimes cannot use keyword names");
+            self.session.emit_err(KeywordLifetime { span: ident.span });
         }
     }
 
     fn check_label(&self, ident: Ident) {
         if ident.without_first_quote().is_reserved() {
-            self.err_handler()
-                .span_err(ident.span, &format!("invalid label name `{}`", ident.name));
+            self.session.emit_err(InvalidLabel { span: ident.span, name: ident.name });
         }
     }
 
-    fn invalid_visibility(&self, vis: &Visibility, note: Option<&str>) {
+    fn invalid_visibility(&self, vis: &Visibility, note: Option<InvalidVisibilityNote>) {
         if let VisibilityKind::Inherited = vis.kind {
             return;
         }
 
-        let mut err =
-            struct_span_err!(self.session, vis.span, E0449, "unnecessary visibility qualifier");
-        if vis.kind.is_pub() {
-            err.span_label(vis.span, "`pub` not permitted here because it's implied");
-        }
-        if let Some(note) = note {
-            err.note(note);
-        }
-        err.emit();
+        self.session.emit_err(InvalidVisibility {
+            span: vis.span,
+            implied: if vis.kind.is_pub() { Some(vis.span) } else { None },
+            note,
+        });
     }
 
     fn check_decl_no_pat(decl: &FnDecl, mut report_err: impl FnMut(Span, Option<Ident>, bool)) {
@@ -309,29 +287,13 @@ impl<'a> AstValidator<'a> {
 
     fn check_trait_fn_not_async(&self, fn_span: Span, asyncness: Async) {
         if let Async::Yes { span, .. } = asyncness {
-            struct_span_err!(
-                self.session,
-                fn_span,
-                E0706,
-                "functions in traits cannot be declared `async`"
-            )
-            .span_label(span, "`async` because of this")
-            .note("`async` trait functions are not currently supported")
-            .note("consider using the `async-trait` crate: https://crates.io/crates/async-trait")
-            .emit();
+            self.session.emit_err(TraitFnAsync { fn_span, span });
         }
     }
 
     fn check_trait_fn_not_const(&self, constness: Const) {
         if let Const::Yes(span) = constness {
-            struct_span_err!(
-                self.session,
-                span,
-                E0379,
-                "functions in traits cannot be declared const"
-            )
-            .span_label(span, "functions in traits cannot be const")
-            .emit();
+            self.session.emit_err(TraitFnConst { span });
         }
     }
 
@@ -344,8 +306,7 @@ impl<'a> AstValidator<'a> {
                 GenericParamKind::Lifetime { .. } => {
                     if !param.bounds.is_empty() {
                         let spans: Vec<_> = param.bounds.iter().map(|b| b.span()).collect();
-                        self.err_handler()
-                            .span_err(spans, "lifetime bounds cannot be used in this context");
+                        self.session.emit_err(ForbiddenLifetimeBound { spans });
                     }
                     None
                 }
@@ -353,10 +314,7 @@ impl<'a> AstValidator<'a> {
             })
             .collect();
         if !non_lt_param_spans.is_empty() {
-            self.err_handler().span_err(
-                non_lt_param_spans,
-                "only lifetime parameters can be used in this context",
-            );
+            self.session.emit_err(ForbiddenNonLifetimeParam { spans: non_lt_param_spans });
         }
     }
 
@@ -373,10 +331,7 @@ impl<'a> AstValidator<'a> {
         let max_num_args: usize = u16::MAX.into();
         if fn_decl.inputs.len() > max_num_args {
             let Param { span, .. } = fn_decl.inputs[0];
-            self.err_handler().span_fatal(
-                span,
-                &format!("function can not have more than {} arguments", max_num_args),
-            );
+            self.session.emit_fatal(FnParamTooMany { span, max_num_args });
         }
     }
 
@@ -384,19 +339,13 @@ impl<'a> AstValidator<'a> {
         match &*fn_decl.inputs {
             [Param { ty, span, .. }] => {
                 if let TyKind::CVarArgs = ty.kind {
-                    self.err_handler().span_err(
-                        *span,
-                        "C-variadic function must be declared with at least one named argument",
-                    );
+                    self.session.emit_err(FnParamCVarArgsOnly { span: *span });
                 }
             }
             [ps @ .., _] => {
                 for Param { ty, span, .. } in ps {
                     if let TyKind::CVarArgs = ty.kind {
-                        self.err_handler().span_err(
-                            *span,
-                            "`...` must be the last argument of a C-variadic function",
-                        );
+                        self.session.emit_err(FnParamCVarArgsNotLast { span: *span });
                     }
                 }
             }
@@ -423,19 +372,9 @@ impl<'a> AstValidator<'a> {
             })
             .for_each(|attr| {
                 if attr.is_doc_comment() {
-                    self.err_handler()
-                        .struct_span_err(
-                            attr.span,
-                            "documentation comments cannot be applied to function parameters",
-                        )
-                        .span_label(attr.span, "doc comments are not allowed here")
-                        .emit();
+                    self.session.emit_err(FnParamDocComment { span: attr.span });
                 } else {
-                    self.err_handler().span_err(
-                        attr.span,
-                        "allow, cfg, cfg_attr, deny, expect, \
-                forbid, and warn are the only allowed built-in attributes in function parameters",
-                    );
+                    self.session.emit_err(FnParamForbiddenAttr { span: attr.span });
                 }
             });
     }
@@ -443,14 +382,7 @@ impl<'a> AstValidator<'a> {
     fn check_decl_self_param(&self, fn_decl: &FnDecl, self_semantic: SelfSemantic) {
         if let (SelfSemantic::No, [param, ..]) = (self_semantic, &*fn_decl.inputs) {
             if param.is_self() {
-                self.err_handler()
-                    .struct_span_err(
-                        param.span,
-                        "`self` parameter is only allowed in associated functions",
-                    )
-                    .span_label(param.span, "not semantically valid as function parameter")
-                    .note("associated functions are those in `impl` or `trait` definitions")
-                    .emit();
+                self.session.emit_err(FnParamForbiddenSelf { span: param.span });
             }
         }
     }
@@ -458,47 +390,20 @@ impl<'a> AstValidator<'a> {
     fn check_defaultness(&self, span: Span, defaultness: Defaultness) {
         if let Defaultness::Default(def_span) = defaultness {
             let span = self.session.source_map().guess_head_span(span);
-            self.err_handler()
-                .struct_span_err(span, "`default` is only allowed on items in trait impls")
-                .span_label(def_span, "`default` because of this")
-                .emit();
+            self.session.emit_err(ForbiddenDefault { span, def_span });
         }
     }
 
-    fn error_item_without_body(&self, sp: Span, ctx: &str, msg: &str, sugg: &str) {
-        self.error_item_without_body_with_help(sp, ctx, msg, sugg, |_| ());
-    }
-
-    fn error_item_without_body_with_help(
-        &self,
-        sp: Span,
-        ctx: &str,
-        msg: &str,
-        sugg: &str,
-        help: impl FnOnce(&mut Diagnostic),
-    ) {
+    /// If `sp` ends with a semicolon, returns it as a `Span`
+    /// Otherwise, returns `sp.shrink_to_hi()`
+    fn ending_semi_or_hi(&self, sp: Span) -> Span {
         let source_map = self.session.source_map();
         let end = source_map.end_point(sp);
-        let replace_span = if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
+
+        if source_map.span_to_snippet(end).map(|s| s == ";").unwrap_or(false) {
             end
         } else {
             sp.shrink_to_hi()
-        };
-        let mut err = self.err_handler().struct_span_err(sp, msg);
-        err.span_suggestion(
-            replace_span,
-            &format!("provide a definition for the {}", ctx),
-            sugg,
-            Applicability::HasPlaceholders,
-        );
-        help(&mut err);
-        err.emit();
-    }
-
-    fn check_impl_item_provided<T>(&self, sp: Span, body: &Option<T>, ctx: &str, sugg: &str) {
-        if body.is_none() {
-            let msg = format!("associated {} in `impl` without body", ctx);
-            self.error_item_without_body(sp, ctx, &msg, sugg);
         }
     }
 
@@ -1168,7 +1073,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
 
                 self.invalid_visibility(
                     &item.vis,
-                    Some("place qualifiers on individual impl items instead"),
+                    Some(InvalidVisibilityNote::IndividualImplItems),
                 );
                 if let Unsafe::Yes(span) = unsafety {
                     error(span, "unsafe").code(error_code!(E0197)).emit();
@@ -1191,37 +1096,23 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 self.check_defaultness(item.span, defaultness);
 
                 if body.is_none() {
-                    let msg = "free function without a body";
-                    let ext = sig.header.ext;
-
-                    let f = |e: &mut Diagnostic| {
-                        if let Extern::Implicit(start_span) | Extern::Explicit(_, start_span) = &ext
-                        {
-                            let start_suggestion = if let Extern::Explicit(abi, _) = ext {
-                                format!("extern \"{}\" {{", abi.symbol_unescaped)
-                            } else {
-                                "extern {".to_owned()
-                            };
-
-                            let end_suggestion = " }".to_owned();
-                            let end_span = item.span.shrink_to_hi();
-
-                            e
-                            .multipart_suggestion(
-                                "if you meant to declare an externally defined function, use an `extern` block",
-                                vec![(*start_span, start_suggestion), (end_span, end_suggestion)],
-                                Applicability::MaybeIncorrect,
-                             );
-                        }
-                    };
-
-                    self.error_item_without_body_with_help(
-                        item.span,
-                        "function",
-                        msg,
-                        " { <body> }",
-                        f,
-                    );
+                    self.session.emit_err(FnWithoutBody {
+                        span: item.span,
+                        replace_span: self.ending_semi_or_hi(item.span),
+                        extern_block_suggestion: match sig.header.ext {
+                            Extern::None => None,
+                            Extern::Implicit(start_span) => Some(ExternBlockSuggestion {
+                                start_span,
+                                end_span: item.span.shrink_to_hi(),
+                                abi: None,
+                            }),
+                            Extern::Explicit(abi, start_span) => Some(ExternBlockSuggestion {
+                                start_span,
+                                end_span: item.span.shrink_to_hi(),
+                                abi: Some(abi.symbol_unescaped),
+                            }),
+                        },
+                    });
                 }
 
                 self.visit_vis(&item.vis);
@@ -1236,7 +1127,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 let old_item = mem::replace(&mut self.extern_mod, Some(item));
                 self.invalid_visibility(
                     &item.vis,
-                    Some("place qualifiers on individual foreign items instead"),
+                    Some(InvalidVisibilityNote::IndividualForeignItems),
                 );
                 if let Unsafe::Yes(span) = unsafety {
                     self.err_handler().span_err(span, "extern block cannot be declared unsafe");
@@ -1327,12 +1218,16 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }
             ItemKind::Const(def, .., None) => {
                 self.check_defaultness(item.span, def);
-                let msg = "free constant item without body";
-                self.error_item_without_body(item.span, "constant", msg, " = <expr>;");
+                self.session.emit_err(ConstWithoutBody {
+                    span: item.span,
+                    replace_span: self.ending_semi_or_hi(item.span),
+                });
             }
             ItemKind::Static(.., None) => {
-                let msg = "free static item without body";
-                self.error_item_without_body(item.span, "static", msg, " = <expr>;");
+                self.session.emit_err(StaticWithoutBody {
+                    span: item.span,
+                    replace_span: self.ending_semi_or_hi(item.span),
+                });
             }
             ItemKind::TyAlias(box TyAlias {
                 defaultness,
@@ -1343,8 +1238,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
             }) => {
                 self.check_defaultness(item.span, defaultness);
                 if ty.is_none() {
-                    let msg = "free type alias without body";
-                    self.error_item_without_body(item.span, "type", msg, " = <type>;");
+                    self.session.emit_err(TyAliasWithoutBody {
+                        span: item.span,
+                        replace_span: self.ending_semi_or_hi(item.span),
+                    });
                 }
                 self.check_type_no_bounds(bounds, "this context");
                 if where_clauses.1.0 {
@@ -1648,10 +1545,20 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
         if ctxt == AssocCtxt::Impl {
             match &item.kind {
                 AssocItemKind::Const(_, _, body) => {
-                    self.check_impl_item_provided(item.span, body, "constant", " = <expr>;");
+                    if body.is_none() {
+                        self.session.emit_err(AssocConstWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                 }
                 AssocItemKind::Fn(box Fn { body, .. }) => {
-                    self.check_impl_item_provided(item.span, body, "function", " { <body> }");
+                    if body.is_none() {
+                        self.session.emit_err(AssocFnWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                 }
                 AssocItemKind::TyAlias(box TyAlias {
                     generics,
@@ -1661,7 +1568,12 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                     ty,
                     ..
                 }) => {
-                    self.check_impl_item_provided(item.span, ty, "type", " = <type>;");
+                    if ty.is_none() {
+                        self.session.emit_err(AssocTypeWithoutBody {
+                            span: item.span,
+                            replace_span: self.ending_semi_or_hi(item.span),
+                        });
+                    }
                     self.check_type_no_bounds(bounds, "`impl`s");
                     if ty.is_some() {
                         self.check_gat_where(
@@ -1876,7 +1788,7 @@ pub fn check_crate(session: &Session, krate: &Crate, lints: &mut LintBuffer) ->
 
 /// Used to forbid `let` expressions in certain syntactic locations.
 #[derive(Clone, Copy)]
-enum ForbiddenLetReason {
+pub(crate) enum ForbiddenLetReason {
     /// `let` is not valid and the source environment is not important
     GenericForbidden,
     /// A let chain with the `||` operator
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
new file mode 100644
index 00000000000..16ba14e9092
--- /dev/null
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -0,0 +1,248 @@
+//! Errors emitted by ast_passes.
+
+use rustc_errors::{fluent, AddSubdiagnostic, Applicability, Diagnostic};
+use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_span::{Span, Symbol};
+
+use crate::ast_validation::ForbiddenLetReason;
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_let)]
+#[note]
+pub struct ForbiddenLet {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub(crate) reason: ForbiddenLetReason,
+}
+
+impl AddSubdiagnostic for ForbiddenLetReason {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        match self {
+            Self::GenericForbidden => {}
+            Self::NotSupportedOr(span) => {
+                diag.span_note(span, fluent::ast_passes::not_supported_or);
+            }
+            Self::NotSupportedParentheses(span) => {
+                diag.span_note(span, fluent::ast_passes::not_supported_parentheses);
+            }
+        }
+    }
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_assoc_constraint)]
+pub struct ForbiddenAssocConstraint {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::keyword_lifetime)]
+pub struct KeywordLifetime {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::invalid_label)]
+pub struct InvalidLabel {
+    #[primary_span]
+    pub span: Span,
+    pub name: Symbol,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::invalid_visibility, code = "E0449")]
+pub struct InvalidVisibility {
+    #[primary_span]
+    pub span: Span,
+    #[label(ast_passes::implied)]
+    pub implied: Option<Span>,
+    #[subdiagnostic]
+    pub note: Option<InvalidVisibilityNote>,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum InvalidVisibilityNote {
+    #[note(ast_passes::individual_impl_items)]
+    IndividualImplItems,
+    #[note(ast_passes::individual_foreign_items)]
+    IndividualForeignItems,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::trait_fn_async, code = "E0706")]
+#[note]
+#[note(ast_passes::note2)]
+pub struct TraitFnAsync {
+    #[primary_span]
+    pub fn_span: Span,
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::trait_fn_const, code = "E0379")]
+pub struct TraitFnConst {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_lifetime_bound)]
+pub struct ForbiddenLifetimeBound {
+    #[primary_span]
+    pub spans: Vec<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_non_lifetime_param)]
+pub struct ForbiddenNonLifetimeParam {
+    #[primary_span]
+    pub spans: Vec<Span>,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_too_many)]
+pub struct FnParamTooMany {
+    #[primary_span]
+    pub span: Span,
+    pub max_num_args: usize,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_c_var_args_only)]
+pub struct FnParamCVarArgsOnly {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_c_var_args_not_last)]
+pub struct FnParamCVarArgsNotLast {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_doc_comment)]
+pub struct FnParamDocComment {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_forbidden_attr)]
+pub struct FnParamForbiddenAttr {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_param_forbidden_self)]
+#[note]
+pub struct FnParamForbiddenSelf {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::forbidden_default)]
+pub struct ForbiddenDefault {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub def_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_const_without_body)]
+pub struct AssocConstWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_fn_without_body)]
+pub struct AssocFnWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::assoc_type_without_body)]
+pub struct AssocTypeWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <type>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::const_without_body)]
+pub struct ConstWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::static_without_body)]
+pub struct StaticWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <expr>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::ty_alias_without_body)]
+pub struct TyAliasWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " = <type>;", applicability = "has-placeholders")]
+    pub replace_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(ast_passes::fn_without_body)]
+pub struct FnWithoutBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " {{ <body> }}", applicability = "has-placeholders")]
+    pub replace_span: Span,
+    #[subdiagnostic]
+    pub extern_block_suggestion: Option<ExternBlockSuggestion>,
+}
+
+pub struct ExternBlockSuggestion {
+    pub start_span: Span,
+    pub end_span: Span,
+    pub abi: Option<Symbol>,
+}
+
+impl AddSubdiagnostic for ExternBlockSuggestion {
+    fn add_to_diagnostic(self, diag: &mut Diagnostic) {
+        let start_suggestion = if let Some(abi) = self.abi {
+            format!("extern \"{}\" {{", abi)
+        } else {
+            "extern {".to_owned()
+        };
+        let end_suggestion = " }".to_owned();
+
+        diag.multipart_suggestion(
+            fluent::ast_passes::extern_block_suggestion,
+            vec![(self.start_span, start_suggestion), (self.end_span, end_suggestion)],
+            Applicability::MaybeIncorrect,
+        );
+    }
+}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 97eee56f948..68fca081018 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -2,10 +2,10 @@ use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::{AssocConstraint, AssocConstraintKind, NodeId};
 use rustc_ast::{PatKind, RangeEnd, VariantData};
-use rustc_errors::{struct_span_err, Applicability};
+use rustc_errors::{struct_span_err, Applicability, StashKey};
+use rustc_feature::Features;
 use rustc_feature::{AttributeGate, BuiltinAttribute, BUILTIN_ATTRIBUTE_MAP};
-use rustc_feature::{Features, GateIssue};
-use rustc_session::parse::{feature_err, feature_err_issue};
+use rustc_session::parse::{feature_err, feature_warn};
 use rustc_session::Session;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::sym;
@@ -20,9 +20,7 @@ macro_rules! gate_feature_fn {
         let has_feature: bool = has_feature(visitor.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable($name) {
-            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
-                .help(help)
-                .emit();
+            feature_err(&visitor.sess.parse_sess, name, span, explain).help(help).emit();
         }
     }};
     ($visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
@@ -31,8 +29,19 @@ macro_rules! gate_feature_fn {
         let has_feature: bool = has_feature(visitor.features);
         debug!("gate_feature(feature = {:?}, span = {:?}); has? {}", name, span, has_feature);
         if !has_feature && !span.allows_unstable($name) {
-            feature_err_issue(&visitor.sess.parse_sess, name, span, GateIssue::Language, explain)
-                .emit();
+            feature_err(&visitor.sess.parse_sess, name, span, explain).emit();
+        }
+    }};
+    (future_incompatible; $visitor: expr, $has_feature: expr, $span: expr, $name: expr, $explain: expr) => {{
+        let (visitor, has_feature, span, name, explain) =
+            (&*$visitor, $has_feature, $span, $name, $explain);
+        let has_feature: bool = has_feature(visitor.features);
+        debug!(
+            "gate_feature(feature = {:?}, span = {:?}); has? {} (future_incompatible)",
+            name, span, has_feature
+        );
+        if !has_feature && !span.allows_unstable($name) {
+            feature_warn(&visitor.sess.parse_sess, name, span, explain);
         }
     }};
 }
@@ -44,6 +53,9 @@ macro_rules! gate_feature_post {
     ($visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
         gate_feature_fn!($visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
     };
+    (future_incompatible; $visitor: expr, $feature: ident, $span: expr, $explain: expr) => {
+        gate_feature_fn!(future_incompatible; $visitor, |x: &Features| x.$feature, $span, sym::$feature, $explain)
+    };
 }
 
 pub fn check_attribute(attr: &ast::Attribute, sess: &Session, features: &Features) {
@@ -588,11 +600,10 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         {
             // When we encounter a statement of the form `foo: Ty = val;`, this will emit a type
             // ascription error, but the likely intention was to write a `let` statement. (#78907).
-            feature_err_issue(
+            feature_err(
                 &self.sess.parse_sess,
                 sym::type_ascription,
                 lhs.span,
-                GateIssue::Language,
                 "type ascription is experimental",
             ).span_suggestion_verbose(
                 lhs.span.shrink_to_lo(),
@@ -615,15 +626,22 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
                 );
             }
             ast::ExprKind::Type(..) => {
-                // To avoid noise about type ascription in common syntax errors, only emit if it
-                // is the *only* error.
                 if self.sess.parse_sess.span_diagnostic.err_count() == 0 {
+                    // To avoid noise about type ascription in common syntax errors,
+                    // only emit if it is the *only* error.
                     gate_feature_post!(
                         &self,
                         type_ascription,
                         e.span,
                         "type ascription is experimental"
                     );
+                } else {
+                    // And if it isn't, cancel the early-pass warning.
+                    self.sess
+                        .parse_sess
+                        .span_diagnostic
+                        .steal_diagnostic(e.span, StashKey::EarlySyntaxWarning)
+                        .map(|err| err.cancel());
                 }
             }
             ast::ExprKind::TryBlock(_) => {
@@ -789,14 +807,12 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
 
     // All uses of `gate_all!` below this point were added in #65742,
     // and subsequently disabled (with the non-early gating readded).
+    // We emit an early future-incompatible warning for these.
+    // New syntax gates should go above here to get a hard error gate.
     macro_rules! gate_all {
         ($gate:ident, $msg:literal) => {
-            // FIXME(eddyb) do something more useful than always
-            // disabling these uses of early feature-gatings.
-            if false {
-                for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
-                    gate_feature_post!(&visitor, $gate, *span, $msg);
-                }
+            for span in spans.get(&sym::$gate).unwrap_or(&vec![]) {
+                gate_feature_post!(future_incompatible; &visitor, $gate, *span, $msg);
             }
         };
     }
@@ -809,11 +825,7 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session) {
     gate_all!(try_blocks, "`try` blocks are unstable");
     gate_all!(label_break_value, "labels on blocks are unstable");
     gate_all!(box_syntax, "box expression syntax is experimental; you can call `Box::new` instead");
-    // To avoid noise about type ascription in common syntax errors,
-    // only emit if it is the *only* error. (Also check it last.)
-    if sess.parse_sess.span_diagnostic.err_count() == 0 {
-        gate_all!(type_ascription, "type ascription is experimental");
-    }
+    gate_all!(type_ascription, "type ascription is experimental");
 
     visit::walk_crate(&mut visitor, krate);
 }
diff --git a/compiler/rustc_ast_passes/src/lib.rs b/compiler/rustc_ast_passes/src/lib.rs
index 2bc3b6f3616..6a826298985 100644
--- a/compiler/rustc_ast_passes/src/lib.rs
+++ b/compiler/rustc_ast_passes/src/lib.rs
@@ -12,6 +12,7 @@
 #![recursion_limit = "256"]
 
 pub mod ast_validation;
+mod errors;
 pub mod feature_gate;
 pub mod node_count;
 pub mod show_span;
diff --git a/compiler/rustc_ast_pretty/src/lib.rs b/compiler/rustc_ast_pretty/src/lib.rs
index 79178830bf9..bf094af5f7b 100644
--- a/compiler/rustc_ast_pretty/src/lib.rs
+++ b/compiler/rustc_ast_pretty/src/lib.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 #![feature(associated_type_bounds)]
 #![feature(box_patterns)]
 #![feature(with_negative_coherence)]
diff --git a/compiler/rustc_borrowck/src/diagnostics/mod.rs b/compiler/rustc_borrowck/src/diagnostics/mod.rs
index 098e8de9420..683084cf09d 100644
--- a/compiler/rustc_borrowck/src/diagnostics/mod.rs
+++ b/compiler/rustc_borrowck/src/diagnostics/mod.rs
@@ -1086,14 +1086,6 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             ),
                         );
                     }
-                    if is_option_or_result && maybe_reinitialized_locations_is_empty {
-                        err.span_suggestion_verbose(
-                            fn_call_span.shrink_to_lo(),
-                            "consider calling `.as_ref()` to borrow the type's contents",
-                            "as_ref().",
-                            Applicability::MachineApplicable,
-                        );
-                    }
                     // Avoid pointing to the same function in multiple different
                     // error messages.
                     if span != DUMMY_SP && self.fn_self_span_reported.insert(self_arg.span) {
@@ -1102,6 +1094,12 @@ impl<'cx, 'tcx> MirBorrowckCtxt<'cx, 'tcx> {
                             &format!("this function takes ownership of the receiver `self`, which moves {}", place_name)
                         );
                     }
+                    if is_option_or_result && maybe_reinitialized_locations_is_empty {
+                        err.span_label(
+                            var_span,
+                            "help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents",
+                        );
+                    }
                 }
                 // Other desugarings takes &self, which cannot cause a move
                 _ => {}
diff --git a/compiler/rustc_borrowck/src/session_diagnostics.rs b/compiler/rustc_borrowck/src/session_diagnostics.rs
index 895723d44ff..8c9676e4bfa 100644
--- a/compiler/rustc_borrowck/src/session_diagnostics.rs
+++ b/compiler/rustc_borrowck/src/session_diagnostics.rs
@@ -3,7 +3,7 @@ use rustc_middle::ty::Ty;
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::move_unsized, code = "E0161")]
+#[diag(borrowck::move_unsized, code = "E0161")]
 pub(crate) struct MoveUnsized<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -12,7 +12,7 @@ pub(crate) struct MoveUnsized<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::higher_ranked_lifetime_error)]
+#[diag(borrowck::higher_ranked_lifetime_error)]
 pub(crate) struct HigherRankedLifetimeError {
     #[subdiagnostic]
     pub cause: Option<HigherRankedErrorCause>,
@@ -29,14 +29,14 @@ pub(crate) enum HigherRankedErrorCause {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::higher_ranked_subtype_error)]
+#[diag(borrowck::higher_ranked_subtype_error)]
 pub(crate) struct HigherRankedSubtypeError {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(borrowck::generic_does_not_live_long_enough)]
+#[diag(borrowck::generic_does_not_live_long_enough)]
 pub(crate) struct GenericDoesNotLiveLongEnough {
     pub kind: String,
     #[primary_span]
diff --git a/compiler/rustc_borrowck/src/type_check/canonical.rs b/compiler/rustc_borrowck/src/type_check/canonical.rs
index 6cfe5efb688..451b82c5c18 100644
--- a/compiler/rustc_borrowck/src/type_check/canonical.rs
+++ b/compiler/rustc_borrowck/src/type_check/canonical.rs
@@ -90,12 +90,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         locations: Locations,
         category: ConstraintCategory<'tcx>,
     ) {
-        self.prove_predicates(
-            Some(ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
+        self.prove_predicate(
+            ty::Binder::dummy(ty::PredicateKind::Trait(ty::TraitPredicate {
                 trait_ref,
                 constness: ty::BoundConstness::NotConst,
                 polarity: ty::ImplPolarity::Positive,
-            }))),
+            }))
+            .to_predicate(self.tcx()),
             locations,
             category,
         );
diff --git a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
index 74655369faf..7c10047e9dc 100644
--- a/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
+++ b/compiler/rustc_borrowck/src/type_check/free_region_relations.rs
@@ -1,5 +1,5 @@
 use rustc_data_structures::frozen::Frozen;
-use rustc_data_structures::transitive_relation::TransitiveRelation;
+use rustc_data_structures::transitive_relation::{TransitiveRelation, TransitiveRelationBuilder};
 use rustc_infer::infer::canonical::QueryRegionConstraints;
 use rustc_infer::infer::outlives;
 use rustc_infer::infer::outlives::env::RegionBoundPairs;
@@ -61,25 +61,13 @@ pub(crate) fn create<'tcx>(
         constraints,
         universal_regions: universal_regions.clone(),
         region_bound_pairs: Default::default(),
-        relations: UniversalRegionRelations {
-            universal_regions: universal_regions.clone(),
-            outlives: Default::default(),
-            inverse_outlives: Default::default(),
-        },
+        outlives: Default::default(),
+        inverse_outlives: Default::default(),
     }
     .create()
 }
 
 impl UniversalRegionRelations<'_> {
-    /// Records in the `outlives_relation` (and
-    /// `inverse_outlives_relation`) that `fr_a: fr_b`. Invoked by the
-    /// builder below.
-    fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
-        debug!("relate_universal_regions: fr_a={:?} outlives fr_b={:?}", fr_a, fr_b);
-        self.outlives.add(fr_a, fr_b);
-        self.inverse_outlives.add(fr_b, fr_a);
-    }
-
     /// Given two universal regions, returns the postdominating
     /// upper-bound (effectively the least upper bound).
     ///
@@ -216,11 +204,20 @@ struct UniversalRegionRelationsBuilder<'this, 'tcx> {
     constraints: &'this mut MirTypeckRegionConstraints<'tcx>,
 
     // outputs:
-    relations: UniversalRegionRelations<'tcx>,
+    outlives: TransitiveRelationBuilder<RegionVid>,
+    inverse_outlives: TransitiveRelationBuilder<RegionVid>,
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
 impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
+    /// Records in the `outlives_relation` (and
+    /// `inverse_outlives_relation`) that `fr_a: fr_b`.
+    fn relate_universal_regions(&mut self, fr_a: RegionVid, fr_b: RegionVid) {
+        debug!("relate_universal_regions: fr_a={:?} outlives fr_b={:?}", fr_a, fr_b);
+        self.outlives.add(fr_a, fr_b);
+        self.inverse_outlives.add(fr_b, fr_a);
+    }
+
     pub(crate) fn create(mut self) -> CreateResult<'tcx> {
         let unnormalized_input_output_tys = self
             .universal_regions
@@ -268,7 +265,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                 // }
                 // impl Foo for () {
                 //   type Bar = ();
-                //   fn foo(&self) ->&() {}
+                //   fn foo(&self) -> &() {}
                 // }
                 // ```
                 // Both &Self::Bar and &() are WF
@@ -292,9 +289,9 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         let fr_fn_body = self.universal_regions.fr_fn_body;
         for fr in self.universal_regions.universal_regions() {
             debug!("build: relating free region {:?} to itself and to 'static", fr);
-            self.relations.relate_universal_regions(fr, fr);
-            self.relations.relate_universal_regions(fr_static, fr);
-            self.relations.relate_universal_regions(fr, fr_fn_body);
+            self.relate_universal_regions(fr, fr);
+            self.relate_universal_regions(fr_static, fr);
+            self.relate_universal_regions(fr, fr_fn_body);
         }
 
         for data in &constraint_sets {
@@ -313,7 +310,11 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
         }
 
         CreateResult {
-            universal_region_relations: Frozen::freeze(self.relations),
+            universal_region_relations: Frozen::freeze(UniversalRegionRelations {
+                universal_regions: self.universal_regions,
+                outlives: self.outlives.freeze(),
+                inverse_outlives: self.inverse_outlives.freeze(),
+            }),
             region_bound_pairs: self.region_bound_pairs,
             normalized_inputs_and_output,
         }
@@ -356,7 +357,7 @@ impl<'tcx> UniversalRegionRelationsBuilder<'_, 'tcx> {
                     // The bound says that `r1 <= r2`; we store `r2: r1`.
                     let r1 = self.universal_regions.to_region_vid(r1);
                     let r2 = self.universal_regions.to_region_vid(r2);
-                    self.relations.relate_universal_regions(r2, r1);
+                    self.relate_universal_regions(r2, r1);
                 }
 
                 OutlivesBound::RegionSubParam(r_a, param_b) => {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 7bf7f7357bf..293d847ec9a 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -178,97 +178,15 @@ pub(crate) fn type_check<'mir, 'tcx>(
         upvars,
     };
 
-    let opaque_type_values = type_check_internal(
+    let mut checker = TypeChecker::new(
         infcx,
-        param_env,
         body,
-        promoted,
+        param_env,
         &region_bound_pairs,
         implicit_region_bound,
         &mut borrowck_context,
-        |mut cx| {
-            debug!("inside extra closure of type_check_internal");
-            cx.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
-            liveness::generate(
-                &mut cx,
-                body,
-                elements,
-                flow_inits,
-                move_data,
-                location_table,
-                use_polonius,
-            );
-
-            translate_outlives_facts(&mut cx);
-            let opaque_type_values =
-                infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
-
-            opaque_type_values
-                .into_iter()
-                .map(|(opaque_type_key, decl)| {
-                    cx.fully_perform_op(
-                        Locations::All(body.span),
-                        ConstraintCategory::OpaqueType,
-                        CustomTypeOp::new(
-                            |infcx| {
-                                infcx.register_member_constraints(
-                                    param_env,
-                                    opaque_type_key,
-                                    decl.hidden_type.ty,
-                                    decl.hidden_type.span,
-                                );
-                                Ok(InferOk { value: (), obligations: vec![] })
-                            },
-                            || "opaque_type_map".to_string(),
-                        ),
-                    )
-                    .unwrap();
-                    let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
-                    trace!(
-                        "finalized opaque type {:?} to {:#?}",
-                        opaque_type_key,
-                        hidden_type.ty.kind()
-                    );
-                    if hidden_type.has_infer_types_or_consts() {
-                        infcx.tcx.sess.delay_span_bug(
-                            decl.hidden_type.span,
-                            &format!("could not resolve {:#?}", hidden_type.ty.kind()),
-                        );
-                        hidden_type.ty = infcx.tcx.ty_error();
-                    }
-
-                    (opaque_type_key, (hidden_type, decl.origin))
-                })
-                .collect()
-        },
     );
 
-    MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
-}
-
-#[instrument(
-    skip(infcx, body, promoted, region_bound_pairs, borrowck_context, extra),
-    level = "debug"
-)]
-fn type_check_internal<'a, 'tcx, R>(
-    infcx: &'a InferCtxt<'a, 'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    body: &'a Body<'tcx>,
-    promoted: &'a IndexVec<Promoted, Body<'tcx>>,
-    region_bound_pairs: &'a RegionBoundPairs<'tcx>,
-    implicit_region_bound: ty::Region<'tcx>,
-    borrowck_context: &'a mut BorrowCheckContext<'a, 'tcx>,
-    extra: impl FnOnce(TypeChecker<'a, 'tcx>) -> R,
-) -> R {
-    debug!("body: {:#?}", body);
-    let mut checker = TypeChecker::new(
-        infcx,
-        body,
-        param_env,
-        region_bound_pairs,
-        implicit_region_bound,
-        borrowck_context,
-    );
     let errors_reported = {
         let mut verifier = TypeVerifier::new(&mut checker, promoted);
         verifier.visit_body(&body);
@@ -280,7 +198,56 @@ fn type_check_internal<'a, 'tcx, R>(
         checker.typeck_mir(body);
     }
 
-    extra(checker)
+    checker.equate_inputs_and_outputs(&body, universal_regions, &normalized_inputs_and_output);
+    liveness::generate(
+        &mut checker,
+        body,
+        elements,
+        flow_inits,
+        move_data,
+        location_table,
+        use_polonius,
+    );
+
+    translate_outlives_facts(&mut checker);
+    let opaque_type_values = infcx.inner.borrow_mut().opaque_type_storage.take_opaque_types();
+
+    let opaque_type_values = opaque_type_values
+        .into_iter()
+        .map(|(opaque_type_key, decl)| {
+            checker
+                .fully_perform_op(
+                    Locations::All(body.span),
+                    ConstraintCategory::OpaqueType,
+                    CustomTypeOp::new(
+                        |infcx| {
+                            infcx.register_member_constraints(
+                                param_env,
+                                opaque_type_key,
+                                decl.hidden_type.ty,
+                                decl.hidden_type.span,
+                            );
+                            Ok(InferOk { value: (), obligations: vec![] })
+                        },
+                        || "opaque_type_map".to_string(),
+                    ),
+                )
+                .unwrap();
+            let mut hidden_type = infcx.resolve_vars_if_possible(decl.hidden_type);
+            trace!("finalized opaque type {:?} to {:#?}", opaque_type_key, hidden_type.ty.kind());
+            if hidden_type.has_infer_types_or_consts() {
+                infcx.tcx.sess.delay_span_bug(
+                    decl.hidden_type.span,
+                    &format!("could not resolve {:#?}", hidden_type.ty.kind()),
+                );
+                hidden_type.ty = infcx.tcx.ty_error();
+            }
+
+            (opaque_type_key, (hidden_type, decl.origin))
+        })
+        .collect();
+
+    MirTypeckResults { constraints, universal_region_relations, opaque_type_values }
 }
 
 fn translate_outlives_facts(typeck: &mut TypeChecker<'_, '_>) {
@@ -1911,7 +1878,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
 
-            &Rvalue::NullaryOp(_, ty) => {
+            &Rvalue::NullaryOp(NullOp::SizeOf | NullOp::AlignOf, ty) => {
                 let trait_ref = ty::TraitRef {
                     def_id: tcx.require_lang_item(LangItem::Sized, Some(self.last_span)),
                     substs: tcx.mk_substs_trait(ty, &[]),
diff --git a/compiler/rustc_builtin_macros/src/asm.rs b/compiler/rustc_builtin_macros/src/asm.rs
index 1a0ea8f4160..a1051d990b1 100644
--- a/compiler/rustc_builtin_macros/src/asm.rs
+++ b/compiler/rustc_builtin_macros/src/asm.rs
@@ -852,7 +852,7 @@ pub(super) fn expand_global_asm<'cx>(
             if let Some(inline_asm) = expand_preparsed_asm(ecx, args) {
                 MacEager::items(smallvec![P(ast::Item {
                     ident: Ident::empty(),
-                    attrs: Vec::new(),
+                    attrs: ast::AttrVec::new(),
                     id: ast::DUMMY_NODE_ID,
                     kind: ast::ItemKind::GlobalAsm(Box::new(inline_asm)),
                     vis: ast::Visibility {
diff --git a/compiler/rustc_builtin_macros/src/assert.rs b/compiler/rustc_builtin_macros/src/assert.rs
index 925c36edb51..119724b5049 100644
--- a/compiler/rustc_builtin_macros/src/assert.rs
+++ b/compiler/rustc_builtin_macros/src/assert.rs
@@ -52,7 +52,7 @@ pub fn expand_assert<'cx>(
     let expr = if let Some(tokens) = custom_message {
         let then = cx.expr(
             call_site_span,
-            ExprKind::MacCall(MacCall {
+            ExprKind::MacCall(P(MacCall {
                 path: panic_path(),
                 args: P(MacArgs::Delimited(
                     DelimSpan::from_single(call_site_span),
@@ -60,7 +60,7 @@ pub fn expand_assert<'cx>(
                     tokens,
                 )),
                 prior_type_ascription: None,
-            }),
+            })),
         );
         expr_if_not(cx, call_site_span, cond_expr, then, None)
     }
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index c04d04020cc..d2ee4249989 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -119,7 +119,8 @@ impl<'cx, 'a> Context<'cx, 'a> {
                 vec![self.cx.attribute(attr::mk_list_item(
                     Ident::new(sym::allow, self.span),
                     vec![attr::mk_nested_word_item(Ident::new(sym::unused_imports, self.span))],
-                ))],
+                ))]
+                .into(),
                 ItemKind::Use(UseTree {
                     prefix: self.cx.path(self.span, self.cx.std_path(&[sym::asserting])),
                     kind: UseTreeKind::Nested(vec![
@@ -177,7 +178,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
         });
         self.cx.expr(
             self.span,
-            ExprKind::MacCall(MacCall {
+            ExprKind::MacCall(P(MacCall {
                 path: panic_path,
                 args: P(MacArgs::Delimited(
                     DelimSpan::from_single(self.span),
@@ -185,7 +186,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
                     initial.into_iter().chain(captures).collect::<TokenStream>(),
                 )),
                 prior_type_ascription: None,
-            }),
+            })),
         )
     }
 
diff --git a/compiler/rustc_builtin_macros/src/cfg.rs b/compiler/rustc_builtin_macros/src/cfg.rs
index aa355150b4f..9046bf13059 100644
--- a/compiler/rustc_builtin_macros/src/cfg.rs
+++ b/compiler/rustc_builtin_macros/src/cfg.rs
@@ -36,7 +36,7 @@ pub fn expand_cfg(
 }
 
 #[derive(SessionDiagnostic)]
-#[error(builtin_macros::requires_cfg_pattern)]
+#[diag(builtin_macros::requires_cfg_pattern)]
 struct RequiresCfgPattern {
     #[primary_span]
     #[label]
@@ -44,7 +44,7 @@ struct RequiresCfgPattern {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(builtin_macros::expected_one_cfg_pattern)]
+#[diag(builtin_macros::expected_one_cfg_pattern)]
 struct OneCfgPattern {
     #[primary_span]
     span: Span,
diff --git a/compiler/rustc_builtin_macros/src/deriving/bounds.rs b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
index 5ef68c6aeaa..77e0b6c55a8 100644
--- a/compiler/rustc_builtin_macros/src/deriving/bounds.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/bounds.rs
@@ -15,7 +15,6 @@ pub fn expand_deriving_copy(
 ) {
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(marker::Copy),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/clone.rs b/compiler/rustc_builtin_macros/src/deriving/clone.rs
index 7755ff779c4..dd7989cf48c 100644
--- a/compiler/rustc_builtin_macros/src/deriving/clone.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/clone.rs
@@ -68,10 +68,9 @@ pub fn expand_deriving_clone(
     }
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(clone::Clone),
         additional_bounds: bounds,
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
index 4e798bf6acb..9b6d3e5032f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/eq.rs
@@ -20,10 +20,9 @@ pub fn expand_deriving_eq(
     let hidden = rustc_ast::attr::mk_nested_word_item(Ident::new(sym::hidden, span));
     let doc = rustc_ast::attr::mk_list_item(Ident::new(sym::doc, span), vec![hidden]);
     let no_coverage = cx.meta_word(span, sym::no_coverage);
-    let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)];
+    let attrs = vec![cx.attribute(inline), cx.attribute(doc), cx.attribute(no_coverage)].into();
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(cmp::Eq),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
index 1612be86237..0e17b951787 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/ord.rs
@@ -15,10 +15,9 @@ pub fn expand_deriving_ord(
     push: &mut dyn FnMut(Annotatable),
 ) {
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(cmp::Ord),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
index 0141b337726..ac1325b92a6 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_eq.rs
@@ -15,14 +15,8 @@ pub fn expand_deriving_partial_eq(
     item: &Annotatable,
     push: &mut dyn FnMut(Annotatable),
 ) {
-    fn cs_op(
-        cx: &mut ExtCtxt<'_>,
-        span: Span,
-        substr: &Substructure<'_>,
-        op: BinOpKind,
-        combiner: BinOpKind,
-        base: bool,
-    ) -> BlockOrExpr {
+    fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
+        let base = true;
         let expr = cs_fold(
             true, // use foldl
             cx,
@@ -47,39 +41,22 @@ pub fn expand_deriving_partial_eq(
                             cx.expr_deref(field.span, expr.clone())
                         }
                     };
-                    cx.expr_binary(field.span, op, convert(&field.self_expr), convert(other_expr))
+                    cx.expr_binary(
+                        field.span,
+                        BinOpKind::Eq,
+                        convert(&field.self_expr),
+                        convert(other_expr),
+                    )
+                }
+                CsFold::Combine(span, expr1, expr2) => {
+                    cx.expr_binary(span, BinOpKind::And, expr1, expr2)
                 }
-                CsFold::Combine(span, expr1, expr2) => cx.expr_binary(span, combiner, expr1, expr2),
                 CsFold::Fieldless => cx.expr_bool(span, base),
             },
         );
         BlockOrExpr::new_expr(expr)
     }
 
-    fn cs_eq(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
-        cs_op(cx, span, substr, BinOpKind::Eq, BinOpKind::And, true)
-    }
-    fn cs_ne(cx: &mut ExtCtxt<'_>, span: Span, substr: &Substructure<'_>) -> BlockOrExpr {
-        cs_op(cx, span, substr, BinOpKind::Ne, BinOpKind::Or, false)
-    }
-
-    macro_rules! md {
-        ($name:expr, $f:ident) => {{
-            let inline = cx.meta_word(span, sym::inline);
-            let attrs = vec![cx.attribute(inline)];
-            MethodDef {
-                name: $name,
-                generics: Bounds::empty(),
-                explicit_self: true,
-                nonself_args: vec![(self_ref(), sym::other)],
-                ret_ty: Path(path_local!(bool)),
-                attributes: attrs,
-                unify_fieldless_variants: true,
-                combine_substructure: combine_substructure(Box::new(|a, b, c| $f(a, b, c))),
-            }
-        }};
-    }
-
     super::inject_impl_of_structural_trait(
         cx,
         span,
@@ -88,17 +65,23 @@ pub fn expand_deriving_partial_eq(
         push,
     );
 
-    // avoid defining `ne` if we can
-    // c-like enums, enums without any fields and structs without fields
-    // can safely define only `eq`.
-    let mut methods = vec![md!(sym::eq, cs_eq)];
-    if !is_type_without_fields(item) {
-        methods.push(md!(sym::ne, cs_ne));
-    }
+    // No need to generate `ne`, the default suffices, and not generating it is
+    // faster.
+    let inline = cx.meta_word(span, sym::inline);
+    let attrs = vec![cx.attribute(inline)].into();
+    let methods = vec![MethodDef {
+        name: sym::eq,
+        generics: Bounds::empty(),
+        explicit_self: true,
+        nonself_args: vec![(self_ref(), sym::other)],
+        ret_ty: Path(path_local!(bool)),
+        attributes: attrs,
+        unify_fieldless_variants: true,
+        combine_substructure: combine_substructure(Box::new(|a, b, c| cs_eq(a, b, c))),
+    }];
 
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(cmp::PartialEq),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
index 2ebb01cc8a0..7763e554017 100644
--- a/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/cmp/partial_ord.rs
@@ -19,7 +19,7 @@ pub fn expand_deriving_partial_ord(
         Path(Path::new_(pathvec_std!(option::Option), vec![Box::new(ordering_ty)], PathKind::Std));
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
 
     let partial_cmp_def = MethodDef {
         name: sym::partial_cmp,
@@ -36,7 +36,6 @@ pub fn expand_deriving_partial_ord(
 
     let trait_def = TraitDef {
         span,
-        attributes: vec![],
         path: path_std!(cmp::PartialOrd),
         additional_bounds: vec![],
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/debug.rs b/compiler/rustc_builtin_macros/src/deriving/debug.rs
index 5ab70e441b8..4af7fd81653 100644
--- a/compiler/rustc_builtin_macros/src/deriving/debug.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/debug.rs
@@ -19,7 +19,6 @@ pub fn expand_deriving_debug(
 
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: path_std!(fmt::Debug),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
@@ -30,7 +29,7 @@ pub fn expand_deriving_debug(
             explicit_self: true,
             nonself_args: vec![(fmtr, sym::f)],
             ret_ty: Path(path_std!(fmt::Result)),
-            attributes: Vec::new(),
+            attributes: ast::AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 show_substructure(a, b, c)
diff --git a/compiler/rustc_builtin_macros/src/deriving/decodable.rs b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
index d688143a2a5..7174dbbe7ea 100644
--- a/compiler/rustc_builtin_macros/src/deriving/decodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/decodable.rs
@@ -22,7 +22,6 @@ pub fn expand_deriving_rustc_decodable(
 
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: Path::new_(vec![krate, sym::Decodable], vec![], PathKind::Global),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
@@ -48,7 +47,7 @@ pub fn expand_deriving_rustc_decodable(
                 ],
                 PathKind::Std,
             )),
-            attributes: Vec::new(),
+            attributes: ast::AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 decodable_substructure(a, b, c, krate)
diff --git a/compiler/rustc_builtin_macros/src/deriving/default.rs b/compiler/rustc_builtin_macros/src/deriving/default.rs
index 5177690917f..f316f01ef66 100644
--- a/compiler/rustc_builtin_macros/src/deriving/default.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/default.rs
@@ -2,9 +2,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 
 use rustc_ast as ast;
-use rustc_ast::walk_list;
-use rustc_ast::EnumDef;
-use rustc_ast::VariantData;
+use rustc_ast::{walk_list, EnumDef, VariantData};
 use rustc_errors::Applicability;
 use rustc_expand::base::{Annotatable, DummyResult, ExtCtxt};
 use rustc_span::symbol::Ident;
@@ -22,10 +20,9 @@ pub fn expand_deriving_default(
     item.visit_with(&mut DetectNonVariantDefaultAttr { cx });
 
     let inline = cx.meta_word(span, sym::inline);
-    let attrs = vec![cx.attribute(inline)];
+    let attrs = vec![cx.attribute(inline)].into();
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: Path::new(vec![kw::Default, sym::Default]),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
diff --git a/compiler/rustc_builtin_macros/src/deriving/encodable.rs b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
index 70167cac68a..b220e54238f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/encodable.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/encodable.rs
@@ -89,7 +89,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::pathvec_std;
 
-use rustc_ast::{ExprKind, MetaItem, Mutability};
+use rustc_ast::{AttrVec, ExprKind, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{sym, Ident, Symbol};
 use rustc_span::Span;
@@ -106,7 +106,6 @@ pub fn expand_deriving_rustc_encodable(
 
     let trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path: Path::new_(vec![krate, sym::Encodable], vec![], PathKind::Global),
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
@@ -132,7 +131,7 @@ pub fn expand_deriving_rustc_encodable(
                 ],
                 PathKind::Std,
             )),
-            attributes: Vec::new(),
+            attributes: AttrVec::new(),
             unify_fieldless_variants: false,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 encodable_substructure(a, b, c, krate)
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 9f3a80ea7cb..c1bbc601560 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -184,8 +184,6 @@ pub struct TraitDef<'a> {
     /// The span for the current #[derive(Foo)] header.
     pub span: Span,
 
-    pub attributes: Vec<ast::Attribute>,
-
     /// Path of the trait, including any type parameters
     pub path: Path,
 
@@ -219,7 +217,7 @@ pub struct MethodDef<'a> {
     /// Returns type
     pub ret_ty: Ty,
 
-    pub attributes: Vec<ast::Attribute>,
+    pub attributes: ast::AttrVec,
 
     /// Can we combine fieldless variants for enums into a single match arm?
     /// If true, indicates that the trait operation uses the enum tag in some
@@ -564,7 +562,7 @@ impl<'a> TraitDef<'a> {
                     kind: ast::VisibilityKind::Inherited,
                     tokens: None,
                 },
-                attrs: Vec::new(),
+                attrs: ast::AttrVec::new(),
                 kind: ast::AssocItemKind::TyAlias(Box::new(ast::TyAlias {
                     defaultness: ast::Defaultness::Final,
                     generics: Generics::default(),
@@ -605,7 +603,7 @@ impl<'a> TraitDef<'a> {
                         param.bounds.iter().cloned()
                     ).collect();
 
-                cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, vec![], bounds, None)
+                cx.typaram(param.ident.span.with_ctxt(ctxt), param.ident, bounds, None)
             }
             GenericParamKind::Const { ty, kw_span, .. } => {
                 let const_nodefault_kind = GenericParamKind::Const {
@@ -718,15 +716,13 @@ impl<'a> TraitDef<'a> {
         let self_type = cx.ty_path(path);
 
         let attr = cx.attribute(cx.meta_word(self.span, sym::automatically_derived));
+        let attrs = vec![attr].into();
         let opt_trait_ref = Some(trait_ref);
 
-        let mut a = vec![attr];
-        a.extend(self.attributes.iter().cloned());
-
         cx.item(
             self.span,
             Ident::empty(),
-            a,
+            attrs,
             ast::ItemKind::Impl(Box::new(ast::Impl {
                 unsafety: ast::Unsafe::No,
                 polarity: ast::ImplPolarity::Positive,
@@ -1629,19 +1625,3 @@ where
         StaticEnum(..) | StaticStruct(..) => cx.span_bug(trait_span, "static function in `derive`"),
     }
 }
-
-/// Returns `true` if the type has no value fields
-/// (for an enum, no variant has any fields)
-pub fn is_type_without_fields(item: &Annotatable) -> bool {
-    if let Annotatable::Item(ref item) = *item {
-        match item.kind {
-            ast::ItemKind::Enum(ref enum_def, _) => {
-                enum_def.variants.iter().all(|v| v.data.fields().is_empty())
-            }
-            ast::ItemKind::Struct(ref variant_data, _) => variant_data.fields().is_empty(),
-            _ => false,
-        }
-    } else {
-        false
-    }
-}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
index 4d46f7cd48a..36e2e293086 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/ty.rs
@@ -146,7 +146,6 @@ fn mk_ty_param(
     cx: &ExtCtxt<'_>,
     span: Span,
     name: Symbol,
-    attrs: &[ast::Attribute],
     bounds: &[Path],
     self_ident: Ident,
     self_generics: &Generics,
@@ -158,7 +157,7 @@ fn mk_ty_param(
             cx.trait_bound(path)
         })
         .collect();
-    cx.typaram(span, Ident::new(name, span), attrs.to_owned(), bounds, None)
+    cx.typaram(span, Ident::new(name, span), bounds, None)
 }
 
 /// Bounds on type parameters.
@@ -183,7 +182,7 @@ impl Bounds {
             .iter()
             .map(|t| {
                 let (name, ref bounds) = *t;
-                mk_ty_param(cx, span, name, &[], &bounds, self_ty, self_generics)
+                mk_ty_param(cx, span, name, &bounds, self_ty, self_generics)
             })
             .collect();
 
diff --git a/compiler/rustc_builtin_macros/src/deriving/hash.rs b/compiler/rustc_builtin_macros/src/deriving/hash.rs
index 32ae3d34478..f1f02e7ce77 100644
--- a/compiler/rustc_builtin_macros/src/deriving/hash.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/hash.rs
@@ -2,7 +2,7 @@ use crate::deriving::generic::ty::*;
 use crate::deriving::generic::*;
 use crate::deriving::{path_std, pathvec_std};
 
-use rustc_ast::{MetaItem, Mutability};
+use rustc_ast::{AttrVec, MetaItem, Mutability};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -21,7 +21,6 @@ pub fn expand_deriving_hash(
     let arg = Path::new_local(typaram);
     let hash_trait_def = TraitDef {
         span,
-        attributes: Vec::new(),
         path,
         additional_bounds: Vec::new(),
         generics: Bounds::empty(),
@@ -32,7 +31,7 @@ pub fn expand_deriving_hash(
             explicit_self: true,
             nonself_args: vec![(Ref(Box::new(Path(arg)), Mutability::Mut), sym::state)],
             ret_ty: Unit,
-            attributes: vec![],
+            attributes: AttrVec::new(),
             unify_fieldless_variants: true,
             combine_substructure: combine_substructure(Box::new(|a, b, c| {
                 hash_substructure(a, b, c)
diff --git a/compiler/rustc_builtin_macros/src/deriving/mod.rs b/compiler/rustc_builtin_macros/src/deriving/mod.rs
index c1ca089da22..a65d0bad6de 100644
--- a/compiler/rustc_builtin_macros/src/deriving/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/mod.rs
@@ -164,7 +164,7 @@ fn inject_impl_of_structural_trait(
 
     // Keep the lint and stability attributes of the original item, to control
     // how the generated implementation is linted.
-    let mut attrs = Vec::new();
+    let mut attrs = ast::AttrVec::new();
     attrs.extend(
         item.attrs
             .iter()
diff --git a/compiler/rustc_builtin_macros/src/edition_panic.rs b/compiler/rustc_builtin_macros/src/edition_panic.rs
index ea0e768a58f..3f1a8b3bc2c 100644
--- a/compiler/rustc_builtin_macros/src/edition_panic.rs
+++ b/compiler/rustc_builtin_macros/src/edition_panic.rs
@@ -48,7 +48,7 @@ fn expand<'cx>(
     MacEager::expr(
         cx.expr(
             sp,
-            ExprKind::MacCall(MacCall {
+            ExprKind::MacCall(P(MacCall {
                 path: Path {
                     span: sp,
                     segments: cx
@@ -64,7 +64,7 @@ fn expand<'cx>(
                     tts,
                 )),
                 prior_type_ascription: None,
-            }),
+            })),
         ),
     )
 }
diff --git a/compiler/rustc_builtin_macros/src/format.rs b/compiler/rustc_builtin_macros/src/format.rs
index 08026c9d357..fd517c1e121 100644
--- a/compiler/rustc_builtin_macros/src/format.rs
+++ b/compiler/rustc_builtin_macros/src/format.rs
@@ -1176,7 +1176,7 @@ fn create_lints_for_named_arguments_used_positionally(cx: &mut Context<'_, '_>)
 
         cx.ecx.buffered_early_lint.push(BufferedEarlyLint {
             span: MultiSpan::from_span(named_arg.positional_named_arg_span),
-            msg: msg.clone(),
+            msg: msg.into(),
             node_id: ast::CRATE_NODE_ID,
             lint_id: LintId::of(&NAMED_ARGUMENTS_USED_POSITIONALLY),
             diagnostic: BuiltinLintDiagnostics::NamedArgumentUsedPositionally {
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 36cfbba45da..2bad9bbce66 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -4,7 +4,7 @@ use rustc_ast::expand::allocator::{
     AllocatorKind, AllocatorMethod, AllocatorTy, ALLOCATOR_METHODS,
 };
 use rustc_ast::ptr::P;
-use rustc_ast::{self as ast, Attribute, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
+use rustc_ast::{self as ast, AttrVec, Expr, FnHeader, FnSig, Generics, Param, StmtKind};
 use rustc_ast::{Fn, ItemKind, Mutability, Stmt, Ty, TyKind, Unsafe};
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
@@ -113,10 +113,10 @@ impl AllocFnFactory<'_, '_> {
         self.cx.expr_call(self.ty_span, method, args)
     }
 
-    fn attrs(&self) -> Vec<Attribute> {
+    fn attrs(&self) -> AttrVec {
         let special = sym::rustc_std_internal_symbol;
         let special = self.cx.meta_word(self.span, special);
-        vec![self.cx.attribute(special)]
+        vec![self.cx.attribute(special)].into()
     }
 
     fn arg_ty(
diff --git a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
index 5cfda33491d..ebe1c3663e3 100644
--- a/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
+++ b/compiler/rustc_builtin_macros/src/proc_macro_harness.rs
@@ -281,7 +281,7 @@ fn mk_decls(cx: &mut ExtCtxt<'_>, macros: &[ProcMacro]) -> P<ast::Item> {
     let span = DUMMY_SP.with_def_site_ctxt(expn_id.to_expn_id());
 
     let proc_macro = Ident::new(sym::proc_macro, span);
-    let krate = cx.item(span, proc_macro, Vec::new(), ast::ItemKind::ExternCrate(None));
+    let krate = cx.item(span, proc_macro, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
 
     let bridge = Ident::new(sym::bridge, span);
     let client = Ident::new(sym::client, span);
diff --git a/compiler/rustc_builtin_macros/src/standard_library_imports.rs b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
index 09ad5f9b3ea..90ea1e457ba 100644
--- a/compiler/rustc_builtin_macros/src/standard_library_imports.rs
+++ b/compiler/rustc_builtin_macros/src/standard_library_imports.rs
@@ -51,7 +51,7 @@ pub fn inject(
             cx.item(
                 span,
                 ident,
-                vec![cx.attribute(cx.meta_word(span, sym::macro_use))],
+                vec![cx.attribute(cx.meta_word(span, sym::macro_use))].into(),
                 ast::ItemKind::ExternCrate(None),
             ),
         );
@@ -78,7 +78,7 @@ pub fn inject(
     let use_item = cx.item(
         span,
         Ident::empty(),
-        vec![cx.attribute(cx.meta_word(span, sym::prelude_import))],
+        vec![cx.attribute(cx.meta_word(span, sym::prelude_import))].into(),
         ast::ItemKind::Use(ast::UseTree {
             prefix: cx.path(span, import_path),
             kind: ast::UseTreeKind::Glob,
diff --git a/compiler/rustc_builtin_macros/src/test.rs b/compiler/rustc_builtin_macros/src/test.rs
index e20375689f3..03c84f5ec2a 100644
--- a/compiler/rustc_builtin_macros/src/test.rs
+++ b/compiler/rustc_builtin_macros/src/test.rs
@@ -227,7 +227,8 @@ pub fn expand_test_or_bench(
             )),
             // #[rustc_test_marker]
             cx.attribute(cx.meta_word(attr_sp, sym::rustc_test_marker)),
-        ],
+        ]
+        .into(),
         // const $ident: test::TestDescAndFn =
         ast::ItemKind::Const(
             ast::Defaultness::Final,
@@ -334,7 +335,7 @@ pub fn expand_test_or_bench(
     });
 
     // extern crate test
-    let test_extern = cx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None));
+    let test_extern = cx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None));
 
     tracing::debug!("synthetic test item:\n{}\n", pprust::item_to_string(&test_const));
 
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 0ebe29df95f..093f0f10a38 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -298,8 +298,10 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
     let call_test_main = ecx.stmt_expr(call_test_main);
 
     // extern crate test
-    let test_extern_stmt =
-        ecx.stmt_item(sp, ecx.item(sp, test_id, vec![], ast::ItemKind::ExternCrate(None)));
+    let test_extern_stmt = ecx.stmt_item(
+        sp,
+        ecx.item(sp, test_id, ast::AttrVec::new(), ast::ItemKind::ExternCrate(None)),
+    );
 
     // #[rustc_main]
     let main_meta = ecx.meta_word(sp, sym::rustc_main);
@@ -333,7 +335,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
 
     let main = P(ast::Item {
         ident: main_id,
-        attrs: vec![main_attr],
+        attrs: vec![main_attr].into(),
         id: ast::DUMMY_NODE_ID,
         kind: main,
         vis: ast::Visibility { span: sp, kind: ast::VisibilityKind::Public, tokens: None },
diff --git a/compiler/rustc_codegen_cranelift/example/alloc_system.rs b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
index cf95c89bc31..50261c19397 100644
--- a/compiler/rustc_codegen_cranelift/example/alloc_system.rs
+++ b/compiler/rustc_codegen_cranelift/example/alloc_system.rs
@@ -94,7 +94,7 @@ mod platform {
     struct Header(*mut u8);
     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
-        &mut *(ptr as *mut Header).offset(-1)
+        &mut *(ptr as *mut Header).sub(1)
     }
     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
         let aligned = ptr.add(align - (ptr as usize & (align - 1)));
diff --git a/compiler/rustc_codegen_cranelift/src/unsize.rs b/compiler/rustc_codegen_cranelift/src/unsize.rs
index 052ca0a082b..dd9d891ddbd 100644
--- a/compiler/rustc_codegen_cranelift/src/unsize.rs
+++ b/compiler/rustc_codegen_cranelift/src/unsize.rs
@@ -29,6 +29,7 @@ pub(crate) fn unsized_info<'tcx>(
             let old_info =
                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
             if data_a.principal_def_id() == data_b.principal_def_id() {
+                // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
                 return old_info;
             }
 
diff --git a/compiler/rustc_codegen_gcc/example/alloc_system.rs b/compiler/rustc_codegen_gcc/example/alloc_system.rs
index 5f66ca67f2d..89661918d05 100644
--- a/compiler/rustc_codegen_gcc/example/alloc_system.rs
+++ b/compiler/rustc_codegen_gcc/example/alloc_system.rs
@@ -156,7 +156,7 @@ mod platform {
     struct Header(*mut u8);
     const HEAP_ZERO_MEMORY: DWORD = 0x00000008;
     unsafe fn get_header<'a>(ptr: *mut u8) -> &'a mut Header {
-        &mut *(ptr as *mut Header).offset(-1)
+        &mut *(ptr as *mut Header).sub(1)
     }
     unsafe fn align_ptr(ptr: *mut u8, align: usize) -> *mut u8 {
         let aligned = ptr.add(align - (ptr as usize & (align - 1)));
diff --git a/compiler/rustc_codegen_ssa/src/base.rs b/compiler/rustc_codegen_ssa/src/base.rs
index a840b270974..4c6be3f9108 100644
--- a/compiler/rustc_codegen_ssa/src/base.rs
+++ b/compiler/rustc_codegen_ssa/src/base.rs
@@ -151,6 +151,7 @@ pub fn unsized_info<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>>(
             let old_info =
                 old_info.expect("unsized_info: missing old info for trait upcasting coercion");
             if data_a.principal_def_id() == data_b.principal_def_id() {
+                // A NOP cast that doesn't actually change anything, should be allowed even with invalid vtables.
                 return old_info;
             }
 
diff --git a/compiler/rustc_const_eval/src/errors.rs b/compiler/rustc_const_eval/src/errors.rs
index a463fe7b970..01619dee0e4 100644
--- a/compiler/rustc_const_eval/src/errors.rs
+++ b/compiler/rustc_const_eval/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::SessionDiagnostic;
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::unstable_in_stable)]
+#[diag(const_eval::unstable_in_stable)]
 pub(crate) struct UnstableInStable {
     pub gate: String,
     #[primary_span]
@@ -22,14 +22,14 @@ pub(crate) struct UnstableInStable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::thread_local_access, code = "E0625")]
+#[diag(const_eval::thread_local_access, code = "E0625")]
 pub(crate) struct NonConstOpErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::static_access, code = "E0013")]
+#[diag(const_eval::static_access, code = "E0013")]
 #[help]
 pub(crate) struct StaticAccessErr {
     #[primary_span]
@@ -41,7 +41,7 @@ pub(crate) struct StaticAccessErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::raw_ptr_to_int)]
+#[diag(const_eval::raw_ptr_to_int)]
 #[note]
 #[note(const_eval::note2)]
 pub(crate) struct RawPtrToIntErr {
@@ -50,7 +50,7 @@ pub(crate) struct RawPtrToIntErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::raw_ptr_comparison)]
+#[diag(const_eval::raw_ptr_comparison)]
 #[note]
 pub(crate) struct RawPtrComparisonErr {
     #[primary_span]
@@ -58,14 +58,14 @@ pub(crate) struct RawPtrComparisonErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::panic_non_str)]
+#[diag(const_eval::panic_non_str)]
 pub(crate) struct PanicNonStrErr {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::mut_deref, code = "E0658")]
+#[diag(const_eval::mut_deref, code = "E0658")]
 pub(crate) struct MutDerefErr {
     #[primary_span]
     pub span: Span,
@@ -73,7 +73,7 @@ pub(crate) struct MutDerefErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::transient_mut_borrow, code = "E0658")]
+#[diag(const_eval::transient_mut_borrow, code = "E0658")]
 pub(crate) struct TransientMutBorrowErr {
     #[primary_span]
     pub span: Span,
@@ -81,7 +81,7 @@ pub(crate) struct TransientMutBorrowErr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(const_eval::transient_mut_borrow_raw, code = "E0658")]
+#[diag(const_eval::transient_mut_borrow_raw, code = "E0658")]
 pub(crate) struct TransientMutBorrowErrRaw {
     #[primary_span]
     pub span: Span,
diff --git a/compiler/rustc_const_eval/src/interpret/cast.rs b/compiler/rustc_const_eval/src/interpret/cast.rs
index c97c31eb9da..14eb2a1537b 100644
--- a/compiler/rustc_const_eval/src/interpret/cast.rs
+++ b/compiler/rustc_const_eval/src/interpret/cast.rs
@@ -298,7 +298,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 self.write_immediate(val, dest)
             }
             (&ty::Dynamic(ref data_a, ..), &ty::Dynamic(ref data_b, ..)) => {
-                let (old_data, old_vptr) = self.read_immediate(src)?.to_scalar_pair()?;
+                let val = self.read_immediate(src)?;
+                if data_a.principal() == data_b.principal() {
+                    // A NOP cast that doesn't actually change anything, should be allowed even with mismatching vtables.
+                    return self.write_immediate(*val, dest);
+                }
+                let (old_data, old_vptr) = val.to_scalar_pair()?;
                 let old_vptr = old_vptr.to_pointer(self)?;
                 let (ty, old_trait) = self.get_ptr_vtable(old_vptr)?;
                 if old_trait != data_a.principal() {
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
index 33802261644..c9cfc1f3f46 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/ops.rs
@@ -1,6 +1,7 @@
 //! Concrete error types for all operations which may be invalid in a certain const context.
 
 use hir::def_id::LocalDefId;
+use hir::ConstContext;
 use rustc_errors::{
     error_code, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed,
 };
@@ -331,6 +332,10 @@ impl<'tcx> NonConstOp<'tcx> for FnCallNonConst<'tcx> {
             ccx.const_kind(),
         ));
 
+        if let ConstContext::Static(_) = ccx.const_kind() {
+            err.note("consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell");
+        }
+
         err
     }
 }
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index 265f45b72d1..c8b09cffe01 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -28,6 +28,8 @@
 #![feature(vec_into_raw_parts)]
 #![allow(rustc::default_hash_types)]
 #![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_data_structures/src/map_in_place.rs b/compiler/rustc_data_structures/src/map_in_place.rs
index 874de03d37a..d912211443a 100644
--- a/compiler/rustc_data_structures/src/map_in_place.rs
+++ b/compiler/rustc_data_structures/src/map_in_place.rs
@@ -1,3 +1,4 @@
+use crate::thin_vec::ThinVec;
 use smallvec::{Array, SmallVec};
 use std::ptr;
 
@@ -15,94 +16,64 @@ pub trait MapInPlace<T>: Sized {
         I: IntoIterator<Item = T>;
 }
 
-impl<T> MapInPlace<T> for Vec<T> {
-    fn flat_map_in_place<F, I>(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator<Item = T>,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
+// The implementation of this method is syntactically identical for all the
+// different vector types.
+macro_rules! flat_map_in_place {
+    () => {
+        fn flat_map_in_place<F, I>(&mut self, mut f: F)
+        where
+            F: FnMut(T) -> I,
+            I: IntoIterator<Item = T>,
+        {
+            let mut read_i = 0;
+            let mut write_i = 0;
+            unsafe {
+                let mut old_len = self.len();
+                self.set_len(0); // make sure we just leak elements in case of panic
 
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.as_ptr().add(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
+                while read_i < old_len {
+                    // move the read_i'th item out of the vector and map it
+                    // to an iterator
+                    let e = ptr::read(self.as_ptr().add(read_i));
+                    let iter = f(e).into_iter();
+                    read_i += 1;
 
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.as_mut_ptr().add(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
+                    for e in iter {
+                        if write_i < read_i {
+                            ptr::write(self.as_mut_ptr().add(write_i), e);
+                            write_i += 1;
+                        } else {
+                            // If this is reached we ran out of space
+                            // in the middle of the vector.
+                            // However, the vector is in a valid state here,
+                            // so we just do a somewhat inefficient insert.
+                            self.set_len(old_len);
+                            self.insert(write_i, e);
 
-                        old_len = self.len();
-                        self.set_len(0);
+                            old_len = self.len();
+                            self.set_len(0);
 
-                        read_i += 1;
-                        write_i += 1;
+                            read_i += 1;
+                            write_i += 1;
+                        }
                     }
                 }
-            }
 
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
+                // write_i tracks the number of actually written new items.
+                self.set_len(write_i);
+            }
         }
-    }
+    };
 }
 
-impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
-    fn flat_map_in_place<F, I>(&mut self, mut f: F)
-    where
-        F: FnMut(T) -> I,
-        I: IntoIterator<Item = T>,
-    {
-        let mut read_i = 0;
-        let mut write_i = 0;
-        unsafe {
-            let mut old_len = self.len();
-            self.set_len(0); // make sure we just leak elements in case of panic
-
-            while read_i < old_len {
-                // move the read_i'th item out of the vector and map it
-                // to an iterator
-                let e = ptr::read(self.as_ptr().add(read_i));
-                let iter = f(e).into_iter();
-                read_i += 1;
-
-                for e in iter {
-                    if write_i < read_i {
-                        ptr::write(self.as_mut_ptr().add(write_i), e);
-                        write_i += 1;
-                    } else {
-                        // If this is reached we ran out of space
-                        // in the middle of the vector.
-                        // However, the vector is in a valid state here,
-                        // so we just do a somewhat inefficient insert.
-                        self.set_len(old_len);
-                        self.insert(write_i, e);
-
-                        old_len = self.len();
-                        self.set_len(0);
+impl<T> MapInPlace<T> for Vec<T> {
+    flat_map_in_place!();
+}
 
-                        read_i += 1;
-                        write_i += 1;
-                    }
-                }
-            }
+impl<T, A: Array<Item = T>> MapInPlace<T> for SmallVec<A> {
+    flat_map_in_place!();
+}
 
-            // write_i tracks the number of actually written new items.
-            self.set_len(write_i);
-        }
-    }
+impl<T> MapInPlace<T> for ThinVec<T> {
+    flat_map_in_place!();
 }
diff --git a/compiler/rustc_data_structures/src/thin_vec.rs b/compiler/rustc_data_structures/src/thin_vec.rs
index 716259142d1..fce42e709ab 100644
--- a/compiler/rustc_data_structures/src/thin_vec.rs
+++ b/compiler/rustc_data_structures/src/thin_vec.rs
@@ -27,6 +27,51 @@ impl<T> ThinVec<T> {
             ThinVec(None) => *self = vec![item].into(),
         }
     }
+
+    /// Note: if `set_len(0)` is called on a non-empty `ThinVec`, it will
+    /// remain in the `Some` form. This is required for some code sequences
+    /// (such as the one in `flat_map_in_place`) that call `set_len(0)` before
+    /// an operation that might panic, and then call `set_len(n)` again
+    /// afterwards.
+    pub unsafe fn set_len(&mut self, new_len: usize) {
+        match *self {
+            ThinVec(None) => {
+                // A prerequisite of `Vec::set_len` is that `new_len` must be
+                // less than or equal to capacity(). The same applies here.
+                if new_len != 0 {
+                    panic!("unsafe ThinVec::set_len({})", new_len);
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.set_len(new_len),
+        }
+    }
+
+    pub fn insert(&mut self, index: usize, value: T) {
+        match *self {
+            ThinVec(None) => {
+                if index == 0 {
+                    *self = vec![value].into();
+                } else {
+                    panic!("invalid ThinVec::insert");
+                }
+            }
+            ThinVec(Some(ref mut vec)) => vec.insert(index, value),
+        }
+    }
+
+    pub fn remove(&mut self, index: usize) -> T {
+        match self {
+            ThinVec(None) => panic!("invalid ThinVec::remove"),
+            ThinVec(Some(vec)) => vec.remove(index),
+        }
+    }
+
+    pub fn as_slice(&self) -> &[T] {
+        match self {
+            ThinVec(None) => &[],
+            ThinVec(Some(vec)) => vec.as_slice(),
+        }
+    }
 }
 
 impl<T> From<Vec<T>> for ThinVec<T> {
diff --git a/compiler/rustc_data_structures/src/transitive_relation.rs b/compiler/rustc_data_structures/src/transitive_relation.rs
index 0ff64969b07..f016c391fe7 100644
--- a/compiler/rustc_data_structures/src/transitive_relation.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation.rs
@@ -1,45 +1,57 @@
+use crate::frozen::Frozen;
 use crate::fx::FxIndexSet;
-use crate::sync::Lock;
 use rustc_index::bit_set::BitMatrix;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::mem;
+use std::ops::Deref;
 
 #[cfg(test)]
 mod tests;
 
 #[derive(Clone, Debug)]
-pub struct TransitiveRelation<T> {
+pub struct TransitiveRelationBuilder<T> {
     // List of elements. This is used to map from a T to a usize.
     elements: FxIndexSet<T>,
 
     // List of base edges in the graph. Require to compute transitive
     // closure.
     edges: Vec<Edge>,
+}
+
+#[derive(Debug)]
+pub struct TransitiveRelation<T> {
+    // Frozen transitive relation elements and edges.
+    builder: Frozen<TransitiveRelationBuilder<T>>,
 
-    // This is a cached transitive closure derived from the edges.
-    // Currently, we build it lazily and just throw out any existing
-    // copy whenever a new edge is added. (The Lock is to permit
-    // the lazy computation.) This is kind of silly, except for the
-    // fact its size is tied to `self.elements.len()`, so I wanted to
-    // wait before building it up to avoid reallocating as new edges
-    // are added with new elements. Perhaps better would be to ask the
-    // user for a batch of edges to minimize this effect, but I
-    // already wrote the code this way. :P -nmatsakis
-    closure: Lock<Option<BitMatrix<usize, usize>>>,
+    // Cached transitive closure derived from the edges.
+    closure: Frozen<BitMatrix<usize, usize>>,
 }
 
-// HACK(eddyb) manual impl avoids `Default` bound on `T`.
-impl<T: Eq + Hash> Default for TransitiveRelation<T> {
-    fn default() -> Self {
+impl<T> Deref for TransitiveRelation<T> {
+    type Target = Frozen<TransitiveRelationBuilder<T>>;
+
+    fn deref(&self) -> &Self::Target {
+        &self.builder
+    }
+}
+
+impl<T: Clone> Clone for TransitiveRelation<T> {
+    fn clone(&self) -> Self {
         TransitiveRelation {
-            elements: Default::default(),
-            edges: Default::default(),
-            closure: Default::default(),
+            builder: Frozen::freeze(self.builder.deref().clone()),
+            closure: Frozen::freeze(self.closure.deref().clone()),
         }
     }
 }
 
+// HACK(eddyb) manual impl avoids `Default` bound on `T`.
+impl<T: Eq + Hash> Default for TransitiveRelationBuilder<T> {
+    fn default() -> Self {
+        TransitiveRelationBuilder { elements: Default::default(), edges: Default::default() }
+    }
+}
+
 #[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Debug)]
 struct Index(usize);
 
@@ -49,7 +61,7 @@ struct Edge {
     target: Index,
 }
 
-impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
+impl<T: Eq + Hash + Copy> TransitiveRelationBuilder<T> {
     pub fn is_empty(&self) -> bool {
         self.edges.is_empty()
     }
@@ -63,23 +75,19 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
     }
 
     fn add_index(&mut self, a: T) -> Index {
-        let (index, added) = self.elements.insert_full(a);
-        if added {
-            // if we changed the dimensions, clear the cache
-            *self.closure.get_mut() = None;
-        }
+        let (index, _added) = self.elements.insert_full(a);
         Index(index)
     }
 
     /// Applies the (partial) function to each edge and returns a new
-    /// relation. If `f` returns `None` for any end-point, returns
-    /// `None`.
-    pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelation<U>>
+    /// relation builder. If `f` returns `None` for any end-point,
+    /// returns `None`.
+    pub fn maybe_map<F, U>(&self, mut f: F) -> Option<TransitiveRelationBuilder<U>>
     where
         F: FnMut(T) -> Option<U>,
         U: Clone + Debug + Eq + Hash + Copy,
     {
-        let mut result = TransitiveRelation::default();
+        let mut result = TransitiveRelationBuilder::default();
         for edge in &self.edges {
             result.add(f(self.elements[edge.source.0])?, f(self.elements[edge.target.0])?);
         }
@@ -93,10 +101,38 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
         let edge = Edge { source: a, target: b };
         if !self.edges.contains(&edge) {
             self.edges.push(edge);
+        }
+    }
+
+    /// Compute the transitive closure derived from the edges, and converted to
+    /// the final result. After this, all elements will be immutable to maintain
+    /// the correctness of the result.
+    pub fn freeze(self) -> TransitiveRelation<T> {
+        let mut matrix = BitMatrix::new(self.elements.len(), self.elements.len());
+        let mut changed = true;
+        while changed {
+            changed = false;
+            for edge in &self.edges {
+                // add an edge from S -> T
+                changed |= matrix.insert(edge.source.0, edge.target.0);
 
-            // added an edge, clear the cache
-            *self.closure.get_mut() = None;
+                // add all outgoing edges from T into S
+                changed |= matrix.union_rows(edge.target.0, edge.source.0);
+            }
         }
+        TransitiveRelation { builder: Frozen::freeze(self), closure: Frozen::freeze(matrix) }
+    }
+}
+
+impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
+    /// Applies the (partial) function to each edge and returns a new
+    /// relation including transitive closures.
+    pub fn maybe_map<F, U>(&self, f: F) -> Option<TransitiveRelation<U>>
+    where
+        F: FnMut(T) -> Option<U>,
+        U: Clone + Debug + Eq + Hash + Copy,
+    {
+        Some(self.builder.maybe_map(f)?.freeze())
     }
 
     /// Checks whether `a < target` (transitively)
@@ -322,30 +358,7 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
     where
         OP: FnOnce(&BitMatrix<usize, usize>) -> R,
     {
-        let mut closure_cell = self.closure.borrow_mut();
-        let mut closure = closure_cell.take();
-        if closure.is_none() {
-            closure = Some(self.compute_closure());
-        }
-        let result = op(closure.as_ref().unwrap());
-        *closure_cell = closure;
-        result
-    }
-
-    fn compute_closure(&self) -> BitMatrix<usize, usize> {
-        let mut matrix = BitMatrix::new(self.elements.len(), self.elements.len());
-        let mut changed = true;
-        while changed {
-            changed = false;
-            for edge in &self.edges {
-                // add an edge from S -> T
-                changed |= matrix.insert(edge.source.0, edge.target.0);
-
-                // add all outgoing edges from T into S
-                changed |= matrix.union_rows(edge.target.0, edge.source.0);
-            }
-        }
-        matrix
+        op(&self.closure)
     }
 
     /// Lists all the base edges in the graph: the initial _non-transitive_ set of element
diff --git a/compiler/rustc_data_structures/src/transitive_relation/tests.rs b/compiler/rustc_data_structures/src/transitive_relation/tests.rs
index e1f4c7ee073..e756c546e41 100644
--- a/compiler/rustc_data_structures/src/transitive_relation/tests.rs
+++ b/compiler/rustc_data_structures/src/transitive_relation/tests.rs
@@ -10,9 +10,10 @@ impl<T: Eq + Hash + Copy> TransitiveRelation<T> {
 
 #[test]
 fn test_one_step() {
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "b");
     relation.add("a", "c");
+    let relation = relation.freeze();
     assert!(relation.contains("a", "c"));
     assert!(relation.contains("a", "b"));
     assert!(!relation.contains("b", "a"));
@@ -21,7 +22,7 @@ fn test_one_step() {
 
 #[test]
 fn test_many_steps() {
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "b");
     relation.add("a", "c");
     relation.add("a", "f");
@@ -31,6 +32,7 @@ fn test_many_steps() {
     relation.add("b", "e");
 
     relation.add("e", "g");
+    let relation = relation.freeze();
 
     assert!(relation.contains("a", "b"));
     assert!(relation.contains("a", "c"));
@@ -51,9 +53,10 @@ fn mubs_triangle() {
     //      ^
     //      |
     //      b
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "tcx");
     relation.add("b", "tcx");
+    let relation = relation.freeze();
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["tcx"]);
     assert_eq!(relation.parents("a"), vec!["tcx"]);
     assert_eq!(relation.parents("b"), vec!["tcx"]);
@@ -72,7 +75,7 @@ fn mubs_best_choice1() {
     // need the second pare down call to get the right result (after
     // intersection, we have [1, 2], but 2 -> 1).
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -80,6 +83,7 @@ fn mubs_best_choice1() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["2"]);
     assert_eq!(relation.parents("0"), vec!["2"]);
@@ -99,7 +103,7 @@ fn mubs_best_choice2() {
     // Like the preceding test, but in this case intersection is [2,
     // 1], and hence we rely on the first pare down call.
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -107,6 +111,7 @@ fn mubs_best_choice2() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1"]);
     assert_eq!(relation.parents("0"), vec!["1"]);
@@ -118,12 +123,13 @@ fn mubs_best_choice2() {
 fn mubs_no_best_choice() {
     // in this case, the intersection yields [1, 2], and the "pare
     // down" calls find nothing to remove.
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1", "2"]);
     assert_eq!(relation.parents("0"), vec!["1", "2"]);
@@ -135,7 +141,7 @@ fn mubs_best_choice_scc() {
     // in this case, 1 and 2 form a cycle; we pick arbitrarily (but
     // consistently).
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("0", "1");
     relation.add("0", "2");
 
@@ -144,6 +150,7 @@ fn mubs_best_choice_scc() {
 
     relation.add("3", "1");
     relation.add("3", "2");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("0", "3"), vec!["1"]);
     assert_eq!(relation.parents("0"), vec!["1"]);
@@ -157,13 +164,14 @@ fn pdub_crisscross() {
     //   /\       |
     // b -> b1 ---+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("a", "b1");
     relation.add("b", "a1");
     relation.add("b", "b1");
     relation.add("a1", "x");
     relation.add("b1", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["a1", "b1"]);
     assert_eq!(relation.postdom_upper_bound("a", "b"), Some("x"));
@@ -179,7 +187,7 @@ fn pdub_crisscross_more() {
     //   /\    /\             |
     // b -> b1 -> b2 ---------+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("a", "b1");
     relation.add("b", "a1");
@@ -194,6 +202,7 @@ fn pdub_crisscross_more() {
 
     relation.add("a3", "x");
     relation.add("b2", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["a1", "b1"]);
     assert_eq!(relation.minimal_upper_bounds("a1", "b1"), vec!["a2", "b2"]);
@@ -210,11 +219,12 @@ fn pdub_lub() {
     //            |
     // b -> b1 ---+
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "a1");
     relation.add("b", "b1");
     relation.add("a1", "x");
     relation.add("b1", "x");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["x"]);
     assert_eq!(relation.postdom_upper_bound("a", "b"), Some("x"));
@@ -233,10 +243,11 @@ fn mubs_intermediate_node_on_one_side_only() {
     //           b
 
     // "digraph { a -> c -> d; b -> d; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("b", "d");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["d"]);
 }
@@ -252,12 +263,13 @@ fn mubs_scc_1() {
     //           b
 
     // "digraph { a -> c -> d; d -> c; a -> d; b -> d; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "c");
     relation.add("a", "d");
     relation.add("b", "d");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -272,12 +284,13 @@ fn mubs_scc_2() {
     //      +--- b
 
     // "digraph { a -> c -> d; d -> c; b -> d; b -> c; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "c");
     relation.add("b", "d");
     relation.add("b", "c");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -292,13 +305,14 @@ fn mubs_scc_3() {
     //           b ---+
 
     // "digraph { a -> c -> d -> e -> c; b -> d; b -> e; }",
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "e");
     relation.add("e", "c");
     relation.add("b", "d");
     relation.add("b", "e");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -314,13 +328,14 @@ fn mubs_scc_4() {
     //           b ---+
 
     // "digraph { a -> c -> d -> e -> c; a -> d; b -> e; }"
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     relation.add("a", "c");
     relation.add("c", "d");
     relation.add("d", "e");
     relation.add("e", "c");
     relation.add("a", "d");
     relation.add("b", "e");
+    let relation = relation.freeze();
 
     assert_eq!(relation.minimal_upper_bounds("a", "b"), vec!["c"]);
 }
@@ -352,10 +367,11 @@ fn parent() {
         (1, /*->*/ 3),
     ];
 
-    let mut relation = TransitiveRelation::default();
+    let mut relation = TransitiveRelationBuilder::default();
     for (a, b) in pairs {
         relation.add(a, b);
     }
+    let relation = relation.freeze();
 
     let p = relation.postdom_parent(3);
     assert_eq!(p, Some(0));
diff --git a/compiler/rustc_driver/src/lib.rs b/compiler/rustc_driver/src/lib.rs
index 94639bf8e1e..dac8df7dc55 100644
--- a/compiler/rustc_driver/src/lib.rs
+++ b/compiler/rustc_driver/src/lib.rs
@@ -1070,7 +1070,7 @@ pub fn handle_options(args: &[String]) -> Option<getopts::Matches> {
     Some(matches)
 }
 
-fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, Vec<ast::Attribute>> {
+fn parse_crate_attrs<'a>(sess: &'a Session, input: &Input) -> PResult<'a, ast::AttrVec> {
     match input {
         Input::File(ifile) => rustc_parse::parse_crate_attrs_from_file(ifile, &sess.parse_sess),
         Input::Str { name, input } => rustc_parse::parse_crate_attrs_from_source_str(
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index f2432f61653..bd424dd9d06 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -1,4 +1,6 @@
 #![deny(rustdoc::invalid_codeblock_attributes)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 //! This library is used to gather all error codes into one place,
 //! the goal being to make their maintenance easier.
 
diff --git a/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
new file mode 100644
index 00000000000..db91a886c72
--- /dev/null
+++ b/compiler/rustc_error_messages/locales/en-US/ast_passes.ftl
@@ -0,0 +1,93 @@
+ast_passes_forbidden_let =
+    `let` expressions are not supported here
+    .note = only supported directly in conditions of `if` and `while` expressions
+    .not_supported_or = `||` operators are not supported in let chain expressions
+    .not_supported_parentheses = `let`s wrapped in parentheses are not supported in a context with let chains
+
+ast_passes_deprecated_where_clause_location =
+    where clause not allowed here
+
+ast_passes_forbidden_assoc_constraint =
+    associated type bounds are not allowed within structs, enums, or unions
+
+ast_passes_keyword_lifetime =
+    lifetimes cannot use keyword names
+
+ast_passes_invalid_label =
+    invalid label name `{$name}`
+
+ast_passes_invalid_visibility =
+    unnecessary visibility qualifier
+    .implied = `pub` not permitted here because it's implied
+    .individual_impl_items = place qualifiers on individual impl items instead
+    .individual_foreign_items = place qualifiers on individual foreign items instead
+
+ast_passes_trait_fn_async =
+    functions in traits cannot be declared `async`
+    .label = `async` because of this
+    .note = `async` trait functions are not currently supported
+    .note2 = consider using the `async-trait` crate: https://crates.io/crates/async-trait
+
+ast_passes_trait_fn_const =
+    functions in traits cannot be declared const
+    .label = functions in traits cannot be const
+
+ast_passes_forbidden_lifetime_bound =
+    lifetime bounds cannot be used in this context
+
+ast_passes_forbidden_non_lifetime_param =
+    only lifetime parameters can be used in this context
+
+ast_passes_fn_param_too_many =
+    function can not have more than {$max_num_args} arguments
+
+ast_passes_fn_param_c_var_args_only =
+    C-variadic function must be declared with at least one named argument
+
+ast_passes_fn_param_c_var_args_not_last =
+    `...` must be the last argument of a C-variadic function
+
+ast_passes_fn_param_doc_comment =
+    documentation comments cannot be applied to function parameters
+    .label = doc comments are not allowed here
+
+ast_passes_fn_param_forbidden_attr =
+    allow, cfg, cfg_attr, deny, expect, forbid, and warn are the only allowed built-in attributes in function parameters
+
+ast_passes_fn_param_forbidden_self =
+    `self` parameter is only allowed in associated functions
+    .label = not semantically valid as function parameter
+    .note = associated functions are those in `impl` or `trait` definitions
+
+ast_passes_forbidden_default =
+    `default` is only allowed on items in trait impls
+    .label = `default` because of this
+
+ast_passes_assoc_const_without_body =
+    associated constant in `impl` without body
+    .suggestion = provide a definition for the constant
+
+ast_passes_assoc_fn_without_body =
+    associated function in `impl` without body
+    .suggestion = provide a definition for the function
+
+ast_passes_assoc_type_without_body =
+    associated type in `impl` without body
+    .suggestion = provide a definition for the type
+
+ast_passes_const_without_body =
+    free constant item without body
+    .suggestion = provide a definition for the constant
+
+ast_passes_static_without_body =
+    free static item without body
+    .suggestion = provide a definition for the static
+
+ast_passes_ty_alias_without_body =
+    free type alias without body
+    .suggestion = provide a definition for the type
+
+ast_passes_fn_without_body =
+    free function without a body
+    .suggestion = provide a definition for the function
+    .extern_block_suggestion = if you meant to declare an externally defined function, use an `extern` block
diff --git a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
index 4af40d2062d..a96fe7c8a05 100644
--- a/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/borrowck.ftl
@@ -13,6 +13,6 @@ borrowck_could_not_normalize =
 
 borrowck_higher_ranked_subtype_error =
     higher-ranked subtype error
-  
-generic_does_not_live_long_enough =
-    `{$kind}` does not live long enough
\ No newline at end of file
+
+borrowck_generic_does_not_live_long_enough =
+    `{$kind}` does not live long enough
diff --git a/compiler/rustc_error_messages/locales/en-US/expand.ftl b/compiler/rustc_error_messages/locales/en-US/expand.ftl
index bdfa22e77eb..5720591154f 100644
--- a/compiler/rustc_error_messages/locales/en-US/expand.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/expand.ftl
@@ -3,3 +3,20 @@ expand_explain_doc_comment_outer =
 
 expand_explain_doc_comment_inner =
     inner doc comments expand to `#![doc = "..."]`, which is what this macro attempted to match
+
+expand_expr_repeat_no_syntax_vars =
+    attempted to repeat an expression containing no syntax variables matched as repeating at this depth
+
+expand_must_repeat_once =
+    this must repeat at least once
+
+expand_count_repetition_misplaced =
+    `count` can not be placed inside the inner-most repetition
+
+expand_meta_var_expr_unrecognized_var =
+    variable `{$key}` is not recognized in meta-variable expression
+
+expand_var_still_repeating =
+    variable '{$ident}' is still repeating at this depth
+
+expand_meta_var_dif_seq_matchers = {$msg}
diff --git a/compiler/rustc_error_messages/locales/en-US/parser.ftl b/compiler/rustc_error_messages/locales/en-US/parser.ftl
index 7e583753618..3b37a393846 100644
--- a/compiler/rustc_error_messages/locales/en-US/parser.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/parser.ftl
@@ -32,3 +32,121 @@ parser_incorrect_use_of_await =
 parser_in_in_typo =
     expected iterable, found keyword `in`
     .suggestion = remove the duplicated `in`
+
+parser_invalid_variable_declaration =
+    invalid variable declaration
+
+parser_switch_mut_let_order =
+    switch the order of `mut` and `let`
+parser_missing_let_before_mut = missing keyword
+parser_use_let_not_auto = write `let` instead of `auto` to introduce a new variable
+parser_use_let_not_var = write `let` instead of `var` to introduce a new variable
+
+parser_invalid_comparison_operator = invalid comparison operator `{$invalid}`
+    .use_instead = `{$invalid}` is not a valid comparison operator, use `{$correct}`
+    .spaceship_operator_invalid = `<=>` is not a valid comparison operator, use `std::cmp::Ordering`
+
+parser_invalid_logical_operator = `{$incorrect}` is not a logical operator
+    .note = unlike in e.g., python and PHP, `&&` and `||` are used for logical operators
+    .use_amp_amp_for_conjunction = use `&&` to perform logical conjunction
+    .use_pipe_pipe_for_disjunction = use `||` to perform logical disjunction
+
+parser_tilde_is_not_unary_operator = `~` cannot be used as a unary operator
+    .suggestion = use `!` to perform bitwise not
+
+parser_unexpected_token_after_not = unexpected {$negated_desc} after identifier
+    .suggestion = use `!` to perform logical negation
+
+parser_malformed_loop_label = malformed loop label
+    .suggestion = use the correct loop label format
+
+parser_lifetime_in_borrow_expression = borrow expressions cannot be annotated with lifetimes
+    .suggestion = remove the lifetime annotation
+    .label = annotated with lifetime here
+
+parser_field_expression_with_generic = field expressions cannot have generic arguments
+
+parser_macro_invocation_with_qualified_path = macros cannot use qualified paths
+
+parser_unexpected_token_after_label = expected `while`, `for`, `loop` or `{"{"}` after a label
+
+parser_require_colon_after_labeled_expression = labeled expression must be followed by `:`
+    .note = labels are used before loops and blocks, allowing e.g., `break 'label` to them
+    .label = the label
+    .suggestion = add `:` after the label
+
+parser_do_catch_syntax_removed = found removed `do catch` syntax
+    .note = following RFC #2388, the new non-placeholder syntax is `try`
+    .suggestion = replace with the new syntax
+
+parser_float_literal_requires_integer_part = float literals must have an integer part
+    .suggestion = must have an integer part
+
+parser_invalid_int_literal_width = invalid width `{$width}` for integer literal
+    .help = valid widths are 8, 16, 32, 64 and 128
+
+parser_invalid_num_literal_base_prefix = invalid base prefix for number literal
+    .note = base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase
+    .suggestion = try making the prefix lowercase
+
+parser_invalid_num_literal_suffix = invalid suffix `{$suffix}` for number literal
+    .label = invalid suffix `{$suffix}`
+    .help = the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)
+
+parser_invalid_float_literal_width = invalid width `{$width}` for float literal
+    .help = valid widths are 32 and 64
+
+parser_invalid_float_literal_suffix = invalid suffix `{$suffix}` for float literal
+    .label = invalid suffix `{$suffix}`
+    .help = valid suffixes are `f32` and `f64`
+
+parser_int_literal_too_large = integer literal is too large
+
+parser_missing_semicolon_before_array = expected `;`, found `[`
+    .suggestion = consider adding `;` here
+
+parser_invalid_block_macro_segment = cannot use a `block` macro fragment here
+    .label = the `block` fragment is within this context
+
+parser_if_expression_missing_then_block = this `if` expression is missing a block after the condition
+    .add_then_block = add a block here
+    .condition_possibly_unfinished = this binary operation is possibly unfinished
+
+parser_if_expression_missing_condition = missing condition for `if` expression
+    .condition_label = expected condition here
+    .block_label = if this block is the condition of the `if` expression, then it must be followed by another block
+
+parser_expected_expression_found_let = expected expression, found `let` statement
+
+parser_expected_else_block = expected `{"{"}`, found {$first_tok}
+    .label = expected an `if` or a block after this `else`
+    .suggestion = add an `if` if this is the condition of a chained `else if` statement
+
+parser_outer_attribute_not_allowed_on_if_else = outer attributes are not allowed on `if` and `else` branches
+    .branch_label = the attributes are attached to this branch
+    .ctx_label = the branch belongs to this `{$ctx}`
+    .suggestion = remove the attributes
+
+parser_missing_in_in_for_loop = missing `in` in `for` loop
+    .use_in_not_of = try using `in` here instead
+    .add_in = try adding `in` here
+
+parser_missing_comma_after_match_arm = expected `,` following `match` arm
+    .suggestion = missing a comma here to end this `match` arm
+
+parser_catch_after_try = keyword `catch` cannot follow a `try` block
+    .help = try using `match` on the result of the `try` block instead
+
+parser_comma_after_base_struct = cannot use a comma after the base struct
+    .note = the base struct must always be the last field
+    .suggestion = remove this comma
+
+parser_eq_field_init = expected `:`, found `=`
+    .suggestion = replace equals symbol with a colon
+
+parser_dotdotdot = unexpected token: `...`
+    .suggest_exclusive_range = use `..` for an exclusive range
+    .suggest_inclusive_range = or `..=` for an inclusive range
+
+parser_left_arrow_operator = unexpected token: `<-`
+    .suggestion = if you meant to write a comparison against a negative value, add a space in between `<` and `-`
diff --git a/compiler/rustc_error_messages/locales/en-US/typeck.ftl b/compiler/rustc_error_messages/locales/en-US/typeck.ftl
index 494b8f91393..272731d9914 100644
--- a/compiler/rustc_error_messages/locales/en-US/typeck.ftl
+++ b/compiler/rustc_error_messages/locales/en-US/typeck.ftl
@@ -24,8 +24,8 @@ typeck_lifetimes_or_bounds_mismatch_on_trait =
     .generics_label = lifetimes in impl do not match this {$item_kind} in trait
 
 typeck_drop_impl_on_wrong_item =
-    the `Drop` trait may only be implemented for structs, enums, and unions
-    .label = must be a struct, enum, or union
+    the `Drop` trait may only be implemented for local structs, enums, and unions
+    .label = must be a struct, enum, or union in the current crate
 
 typeck_field_already_declared =
     field `{$field_name}` is already declared
@@ -123,3 +123,13 @@ typeck_manual_implementation =
     .help = add `#![feature(unboxed_closures)]` to the crate attributes to enable
 
 typeck_substs_on_overridden_impl = could not resolve substs on overridden impl
+
+typeck_unused_extern_crate =
+    unused extern crate
+    .suggestion = remove it
+
+typeck_extern_crate_not_idiomatic =
+    `extern crate` is not idiomatic in the new edition
+    .suggestion = convert it to a `{$msg_code}`
+
+typeck_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index 6ae4dab3a35..3569c7f0630 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -1,6 +1,8 @@
 #![feature(once_cell)]
 #![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 use fluent_bundle::FluentResource;
 use fluent_syntax::parser::ParserError;
@@ -30,6 +32,7 @@ pub use unic_langid::{langid, LanguageIdentifier};
 
 // Generates `DEFAULT_LOCALE_RESOURCES` static and `fluent_generated` module.
 fluent_messages! {
+    ast_passes => "../locales/en-US/ast_passes.ftl",
     borrowck => "../locales/en-US/borrowck.ftl",
     builtin_macros => "../locales/en-US/builtin_macros.ftl",
     const_eval => "../locales/en-US/const_eval.ftl",
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 17e6c9e9575..356f9dfdb3b 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -8,7 +8,7 @@ use rustc_error_messages::FluentValue;
 use rustc_hir as hir;
 use rustc_lint_defs::{Applicability, LintExpectationId};
 use rustc_span::edition::LATEST_STABLE_EDITION;
-use rustc_span::symbol::{Ident, Symbol};
+use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent, Symbol};
 use rustc_span::{edition::Edition, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::fmt;
@@ -87,6 +87,7 @@ into_diagnostic_arg_using_display!(
     hir::Target,
     Edition,
     Ident,
+    MacroRulesNormalizedIdent,
 );
 
 impl IntoDiagnosticArg for bool {
diff --git a/compiler/rustc_errors/src/diagnostic_builder.rs b/compiler/rustc_errors/src/diagnostic_builder.rs
index 9e68ee282e6..61d767a1cc6 100644
--- a/compiler/rustc_errors/src/diagnostic_builder.rs
+++ b/compiler/rustc_errors/src/diagnostic_builder.rs
@@ -84,6 +84,13 @@ pub trait EmissionGuarantee: Sized {
     /// of `Self` without actually performing the emission.
     #[track_caller]
     fn diagnostic_builder_emit_producing_guarantee(db: &mut DiagnosticBuilder<'_, Self>) -> Self;
+
+    /// Creates a new `DiagnosticBuilder` that will return this type of guarantee.
+    #[track_caller]
+    fn make_diagnostic_builder(
+        handler: &Handler,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, Self>;
 }
 
 /// Private module for sealing the `IsError` helper trait.
@@ -166,6 +173,15 @@ impl EmissionGuarantee for ErrorGuaranteed {
             }
         }
     }
+
+    fn make_diagnostic_builder(
+        handler: &Handler,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, Self> {
+        DiagnosticBuilder::new_guaranteeing_error::<_, { Level::Error { lint: false } }>(
+            handler, msg,
+        )
+    }
 }
 
 impl<'a> DiagnosticBuilder<'a, ()> {
@@ -208,6 +224,13 @@ impl EmissionGuarantee for () {
             DiagnosticBuilderState::AlreadyEmittedOrDuringCancellation => {}
         }
     }
+
+    fn make_diagnostic_builder(
+        handler: &Handler,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, Self> {
+        DiagnosticBuilder::new(handler, Level::Warning(None), msg)
+    }
 }
 
 impl<'a> DiagnosticBuilder<'a, !> {
@@ -247,6 +270,13 @@ impl EmissionGuarantee for ! {
         // Then fatally error, returning `!`
         crate::FatalError.raise()
     }
+
+    fn make_diagnostic_builder(
+        handler: &Handler,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, Self> {
+        DiagnosticBuilder::new_fatal(handler, msg)
+    }
 }
 
 /// In general, the `DiagnosticBuilder` uses deref to allow access to
@@ -566,7 +596,7 @@ impl Drop for DiagnosticBuilderInner<'_> {
                         ),
                     ));
                     handler.emit_diagnostic(&mut self.diagnostic);
-                    panic!();
+                    panic!("error was constructed but not emitted");
                 }
             }
             // `.emit()` was previously called, or maybe we're during `.cancel()`.
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 6555b93ac0b..9b9c334d4df 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -459,6 +459,7 @@ struct HandlerInner {
 pub enum StashKey {
     ItemNoType,
     UnderscoreForArrayLengths,
+    EarlySyntaxWarning,
 }
 
 fn default_track_diagnostic(_: &Diagnostic) {}
@@ -626,19 +627,13 @@ impl Handler {
     /// Stash a given diagnostic with the given `Span` and `StashKey` as the key for later stealing.
     pub fn stash_diagnostic(&self, span: Span, key: StashKey, diag: Diagnostic) {
         let mut inner = self.inner.borrow_mut();
-        // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
-        // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
-        // See the PR for a discussion.
-        inner.stashed_diagnostics.insert((span, key), diag);
+        inner.stash((span, key), diag);
     }
 
     /// Steal a previously stashed diagnostic with the given `Span` and `StashKey` as the key.
     pub fn steal_diagnostic(&self, span: Span, key: StashKey) -> Option<DiagnosticBuilder<'_, ()>> {
-        self.inner
-            .borrow_mut()
-            .stashed_diagnostics
-            .remove(&(span, key))
-            .map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
+        let mut inner = self.inner.borrow_mut();
+        inner.steal((span, key)).map(|diag| DiagnosticBuilder::new_diagnostic(self, diag))
     }
 
     /// Emit all stashed diagnostics.
@@ -646,6 +641,15 @@ impl Handler {
         self.inner.borrow_mut().emit_stashed_diagnostics()
     }
 
+    /// Construct a builder with the `msg` at the level appropriate for the specific `EmissionGuarantee`.
+    #[rustc_lint_diagnostics]
+    pub fn struct_diagnostic<G: EmissionGuarantee>(
+        &self,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, G> {
+        G::make_diagnostic_builder(self, msg)
+    }
+
     /// Construct a builder at the `Warning` level at the given `span` and with the `msg`.
     ///
     /// Attempting to `.emit()` the builder will only emit if either:
@@ -1106,13 +1110,31 @@ impl HandlerInner {
 
     /// Emit all stashed diagnostics.
     fn emit_stashed_diagnostics(&mut self) -> Option<ErrorGuaranteed> {
+        let has_errors = self.has_errors();
         let diags = self.stashed_diagnostics.drain(..).map(|x| x.1).collect::<Vec<_>>();
         let mut reported = None;
         for mut diag in diags {
+            // Decrement the count tracking the stash; emitting will increment it.
             if diag.is_error() {
-                reported = Some(ErrorGuaranteed(()));
+                if matches!(diag.level, Level::Error { lint: true }) {
+                    self.lint_err_count -= 1;
+                } else {
+                    self.err_count -= 1;
+                }
+            } else {
+                if diag.is_force_warn() {
+                    self.warn_count -= 1;
+                } else {
+                    // Unless they're forced, don't flush stashed warnings when
+                    // there are errors, to avoid causing warning overload. The
+                    // stash would've been stolen already if it were important.
+                    if has_errors {
+                        continue;
+                    }
+                }
             }
-            self.emit_diagnostic(&mut diag);
+            let reported_this = self.emit_diagnostic(&mut diag);
+            reported = reported.or(reported_this);
         }
         reported
     }
@@ -1302,9 +1324,47 @@ impl HandlerInner {
         }
     }
 
+    fn stash(&mut self, key: (Span, StashKey), diagnostic: Diagnostic) {
+        // Track the diagnostic for counts, but don't panic-if-treat-err-as-bug
+        // yet; that happens when we actually emit the diagnostic.
+        if diagnostic.is_error() {
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.lint_err_count += 1;
+            } else {
+                self.err_count += 1;
+            }
+        } else {
+            // Warnings are only automatically flushed if they're forced.
+            if diagnostic.is_force_warn() {
+                self.warn_count += 1;
+            }
+        }
+
+        // FIXME(Centril, #69537): Consider reintroducing panic on overwriting a stashed diagnostic
+        // if/when we have a more robust macro-friendly replacement for `(span, key)` as a key.
+        // See the PR for a discussion.
+        self.stashed_diagnostics.insert(key, diagnostic);
+    }
+
+    fn steal(&mut self, key: (Span, StashKey)) -> Option<Diagnostic> {
+        let diagnostic = self.stashed_diagnostics.remove(&key)?;
+        if diagnostic.is_error() {
+            if matches!(diagnostic.level, Level::Error { lint: true }) {
+                self.lint_err_count -= 1;
+            } else {
+                self.err_count -= 1;
+            }
+        } else {
+            if diagnostic.is_force_warn() {
+                self.warn_count -= 1;
+            }
+        }
+        Some(diagnostic)
+    }
+
     #[inline]
     fn err_count(&self) -> usize {
-        self.err_count + self.stashed_diagnostics.len()
+        self.err_count
     }
 
     fn has_errors(&self) -> bool {
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 852ea806b20..df56e032988 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -6,7 +6,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Nonterminal};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{AssocCtxt, Visitor};
-use rustc_ast::{self as ast, Attribute, HasAttrs, Item, NodeId, PatKind};
+use rustc_ast::{self as ast, AttrVec, Attribute, HasAttrs, Item, NodeId, PatKind};
 use rustc_attr::{self as attr, Deprecation, Stability};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_data_structures::sync::{self, Lrc};
@@ -71,7 +71,7 @@ impl Annotatable {
         }
     }
 
-    pub fn visit_attrs(&mut self, f: impl FnOnce(&mut Vec<Attribute>)) {
+    pub fn visit_attrs(&mut self, f: impl FnOnce(&mut AttrVec)) {
         match self {
             Annotatable::Item(item) => item.visit_attrs(f),
             Annotatable::TraitItem(trait_item) => trait_item.visit_attrs(f),
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index b971a63ec89..c4890b4a9c4 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -107,14 +107,13 @@ impl<'a> ExtCtxt<'a> {
         &self,
         span: Span,
         ident: Ident,
-        attrs: Vec<ast::Attribute>,
         bounds: ast::GenericBounds,
         default: Option<P<ast::Ty>>,
     ) -> ast::GenericParam {
         ast::GenericParam {
             ident: ident.with_span_pos(span),
             id: ast::DUMMY_NODE_ID,
-            attrs: attrs.into(),
+            attrs: AttrVec::new(),
             bounds,
             kind: ast::GenericParamKind::Type { default },
             is_placeholder: false,
@@ -576,7 +575,7 @@ impl<'a> ExtCtxt<'a> {
         &self,
         span: Span,
         name: Ident,
-        attrs: Vec<ast::Attribute>,
+        attrs: ast::AttrVec,
         kind: ast::ItemKind,
     ) -> P<ast::Item> {
         // FIXME: Would be nice if our generated code didn't violate
@@ -604,7 +603,7 @@ impl<'a> ExtCtxt<'a> {
         mutbl: ast::Mutability,
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
-        self.item(span, name, Vec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
+        self.item(span, name, AttrVec::new(), ast::ItemKind::Static(ty, mutbl, Some(expr)))
     }
 
     pub fn item_const(
@@ -615,7 +614,7 @@ impl<'a> ExtCtxt<'a> {
         expr: P<ast::Expr>,
     ) -> P<ast::Item> {
         let def = ast::Defaultness::Final;
-        self.item(span, name, Vec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
+        self.item(span, name, AttrVec::new(), ast::ItemKind::Const(def, ty, Some(expr)))
     }
 
     pub fn attribute(&self, mi: ast::MetaItem) -> ast::Attribute {
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 3e1acf4382d..48ee23d2c3d 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -215,7 +215,7 @@ pub fn features(
     let features = match strip_unconfigured.configure_krate_attrs(krate.attrs) {
         None => {
             // The entire crate is unconfigured.
-            krate.attrs = Vec::new();
+            krate.attrs = ast::AttrVec::new();
             krate.items = Vec::new();
             Features::default()
         }
@@ -265,7 +265,7 @@ impl<'a> StripUnconfigured<'a> {
         }
     }
 
-    fn configure_krate_attrs(&self, mut attrs: Vec<ast::Attribute>) -> Option<Vec<ast::Attribute>> {
+    fn configure_krate_attrs(&self, mut attrs: ast::AttrVec) -> Option<ast::AttrVec> {
         attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
         if self.in_cfg(&attrs) { Some(attrs) } else { None }
     }
@@ -292,9 +292,7 @@ impl<'a> StripUnconfigured<'a> {
             .iter()
             .flat_map(|(tree, spacing)| match tree.clone() {
                 AttrAnnotatedTokenTree::Attributes(mut data) => {
-                    let mut attrs: Vec<_> = std::mem::take(&mut data.attrs).into();
-                    attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
-                    data.attrs = attrs.into();
+                    data.attrs.flat_map_in_place(|attr| self.process_cfg_attr(attr));
 
                     if self.in_cfg(&data.attrs) {
                         data.tokens = LazyTokenStream::new(
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
new file mode 100644
index 00000000000..0feae0debd2
--- /dev/null
+++ b/compiler/rustc_expand/src/errors.rs
@@ -0,0 +1,48 @@
+use rustc_macros::SessionDiagnostic;
+use rustc_span::symbol::MacroRulesNormalizedIdent;
+use rustc_span::Span;
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::expr_repeat_no_syntax_vars)]
+pub(crate) struct NoSyntaxVarsExprRepeat {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::must_repeat_once)]
+pub(crate) struct MustRepeatOnce {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::count_repetition_misplaced)]
+pub(crate) struct CountRepetitionMisplaced {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::meta_var_expr_unrecognized_var)]
+pub(crate) struct MetaVarExprUnrecognizedVar {
+    #[primary_span]
+    pub span: Span,
+    pub key: MacroRulesNormalizedIdent,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::var_still_repeating)]
+pub(crate) struct VarStillRepeating {
+    #[primary_span]
+    pub span: Span,
+    pub ident: MacroRulesNormalizedIdent,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(expand::meta_var_dif_seq_matchers)]
+pub(crate) struct MetaVarsDifSeqMatchers {
+    #[primary_span]
+    pub span: Span,
+    pub msg: String,
+}
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index 93eeca5b289..c2add852a06 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -11,7 +11,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::tokenstream::TokenStream;
 use rustc_ast::visit::{self, AssocCtxt, Visitor};
-use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, ExprKind, ForeignItemKind};
+use rustc_ast::{AssocItemKind, AstNodeWrapper, AttrStyle, AttrVec, ExprKind, ForeignItemKind};
 use rustc_ast::{HasAttrs, HasNodeId};
 use rustc_ast::{Inline, ItemKind, MacArgs, MacStmtStyle, MetaItemKind, ModKind};
 use rustc_ast::{NestedMetaItem, NodeId, PatKind, StmtKind, TyKind};
@@ -306,7 +306,7 @@ pub struct Invocation {
 
 pub enum InvocationKind {
     Bang {
-        mac: ast::MacCall,
+        mac: P<ast::MacCall>,
         span: Span,
     },
     Attr {
@@ -1001,7 +1001,7 @@ enum AddSemicolon {
 /// of functionality used by `InvocationCollector`.
 trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     type OutputTy = SmallVec<[Self; 1]>;
-    type AttrsTy: Deref<Target = [ast::Attribute]> = Vec<ast::Attribute>;
+    type AttrsTy: Deref<Target = [ast::Attribute]> = ast::AttrVec;
     const KIND: AstFragmentKind;
     fn to_annotatable(self) -> Annotatable;
     fn fragment_to_output(fragment: AstFragment) -> Self::OutputTy;
@@ -1017,7 +1017,7 @@ trait InvocationCollectorNode: HasAttrs + HasNodeId + Sized {
     fn is_mac_call(&self) -> bool {
         false
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         unreachable!()
     }
     fn pre_flat_map_node_collect_attr(_cfg: &StripUnconfigured<'_>, _attr: &ast::Attribute) {}
@@ -1046,7 +1046,7 @@ impl InvocationCollectorNode for P<ast::Item> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
             ItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1154,7 +1154,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, TraitItemTag>
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let item = self.wrapped.into_inner();
         match item.kind {
             AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
@@ -1179,7 +1179,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::AssocItem>, ImplItemTag>
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, AssocItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let item = self.wrapped.into_inner();
         match item.kind {
             AssocItemKind::MacCall(mac) => (mac, item.attrs, AddSemicolon::No),
@@ -1202,7 +1202,7 @@ impl InvocationCollectorNode for P<ast::ForeignItem> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ForeignItemKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
             ForeignItemKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1323,7 +1323,7 @@ impl InvocationCollectorNode for ast::Stmt {
             StmtKind::Local(..) | StmtKind::Empty => false,
         }
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         // We pull macro invocations (both attributes and fn-like macro calls) out of their
         // `StmtKind`s and treat them as statement macro invocations, not as items or expressions.
         let (add_semicolon, mac, attrs) = match self.kind {
@@ -1333,7 +1333,7 @@ impl InvocationCollectorNode for ast::Stmt {
             }
             StmtKind::Item(item) => match item.into_inner() {
                 ast::Item { kind: ItemKind::MacCall(mac), attrs, .. } => {
-                    (mac.args.need_semicolon(), mac, attrs.into())
+                    (mac.args.need_semicolon(), mac, attrs)
                 }
                 _ => unreachable!(),
             },
@@ -1387,10 +1387,10 @@ impl InvocationCollectorNode for P<ast::Ty> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ast::TyKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
-            TyKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
+            TyKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
         }
     }
@@ -1411,10 +1411,10 @@ impl InvocationCollectorNode for P<ast::Pat> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, PatKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
-            PatKind::MacCall(mac) => (mac, Vec::new(), AddSemicolon::No),
+            PatKind::MacCall(mac) => (mac, AttrVec::new(), AddSemicolon::No),
             _ => unreachable!(),
         }
     }
@@ -1439,7 +1439,7 @@ impl InvocationCollectorNode for P<ast::Expr> {
     fn is_mac_call(&self) -> bool {
         matches!(self.kind, ExprKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.into_inner();
         match node.kind {
             ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1466,7 +1466,7 @@ impl InvocationCollectorNode for AstNodeWrapper<P<ast::Expr>, OptExprTag> {
     fn is_mac_call(&self) -> bool {
         matches!(self.wrapped.kind, ast::ExprKind::MacCall(..))
     }
-    fn take_mac_call(self) -> (ast::MacCall, Self::AttrsTy, AddSemicolon) {
+    fn take_mac_call(self) -> (P<ast::MacCall>, Self::AttrsTy, AddSemicolon) {
         let node = self.wrapped.into_inner();
         match node.kind {
             ExprKind::MacCall(mac) => (mac, node.attrs, AddSemicolon::No),
@@ -1512,7 +1512,7 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
         placeholder(fragment_kind, NodeId::placeholder_from_expn_id(expn_id), vis)
     }
 
-    fn collect_bang(&mut self, mac: ast::MacCall, kind: AstFragmentKind) -> AstFragment {
+    fn collect_bang(&mut self, mac: P<ast::MacCall>, kind: AstFragmentKind) -> AstFragment {
         // cache the macro call span so that it can be
         // easily adjusted for incremental compilation
         let span = mac.span();
@@ -1646,7 +1646,11 @@ impl<'a, 'b> InvocationCollector<'a, 'b> {
 
     fn expand_cfg_attr(&self, node: &mut impl HasAttrs, attr: ast::Attribute, pos: usize) {
         node.visit_attrs(|attrs| {
-            attrs.splice(pos..pos, self.cfg().expand_cfg_attr(attr, false));
+            // Repeated `insert` calls is inefficient, but the number of
+            // insertions is almost always 0 or 1 in practice.
+            for cfg in self.cfg().expand_cfg_attr(attr, false).into_iter().rev() {
+                attrs.insert(pos, cfg)
+            }
         });
     }
 
diff --git a/compiler/rustc_expand/src/lib.rs b/compiler/rustc_expand/src/lib.rs
index 91a18342784..e1dde1672c1 100644
--- a/compiler/rustc_expand/src/lib.rs
+++ b/compiler/rustc_expand/src/lib.rs
@@ -25,6 +25,7 @@ pub mod base;
 pub mod build;
 #[macro_use]
 pub mod config;
+pub mod errors;
 pub mod expand;
 pub mod module;
 pub mod proc_macro;
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index e47ea83ac38..bec6d1a2df7 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -1,4 +1,8 @@
 use crate::base::ExtCtxt;
+use crate::errors::{
+    CountRepetitionMisplaced, MetaVarExprUnrecognizedVar, MetaVarsDifSeqMatchers, MustRepeatOnce,
+    NoSyntaxVarsExprRepeat, VarStillRepeating,
+};
 use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree, NamedMatch};
 use crate::mbe::{self, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
@@ -165,11 +169,7 @@ pub(super) fn transcribe<'a>(
             seq @ mbe::TokenTree::Sequence(_, delimited) => {
                 match lockstep_iter_size(&seq, interp, &repeats) {
                     LockstepIterSize::Unconstrained => {
-                        return Err(cx.struct_span_err(
-                            seq.span(), /* blame macro writer */
-                            "attempted to repeat an expression containing no syntax variables \
-                             matched as repeating at this depth",
-                        ));
+                        return Err(cx.create_err(NoSyntaxVarsExprRepeat { span: seq.span() }));
                     }
 
                     LockstepIterSize::Contradiction(msg) => {
@@ -177,7 +177,7 @@ pub(super) fn transcribe<'a>(
                         // happens when two meta-variables are used in the same repetition in a
                         // sequence, but they come from different sequence matchers and repeat
                         // different amounts.
-                        return Err(cx.struct_span_err(seq.span(), &msg));
+                        return Err(cx.create_err(MetaVarsDifSeqMatchers { span: seq.span(), msg }));
                     }
 
                     LockstepIterSize::Constraint(len, _) => {
@@ -193,10 +193,7 @@ pub(super) fn transcribe<'a>(
                                 // FIXME: this really ought to be caught at macro definition
                                 // time... It happens when the Kleene operator in the matcher and
                                 // the body for the same meta-variable do not match.
-                                return Err(cx.struct_span_err(
-                                    sp.entire(),
-                                    "this must repeat at least once",
-                                ));
+                                return Err(cx.create_err(MustRepeatOnce { span: sp.entire() }));
                             }
                         } else {
                             // 0 is the initial counter (we have done 0 repetitions so far). `len`
@@ -239,10 +236,7 @@ pub(super) fn transcribe<'a>(
                         }
                         MatchedSeq(..) => {
                             // We were unable to descend far enough. This is an error.
-                            return Err(cx.struct_span_err(
-                                sp, /* blame the macro writer */
-                                &format!("variable '{}' is still repeating at this depth", ident),
-                            ));
+                            return Err(cx.create_err(VarStillRepeating { span: sp, ident }));
                         }
                     }
                 } else {
@@ -448,10 +442,7 @@ fn count_repetitions<'a>(
         match matched {
             MatchedTokenTree(_) | MatchedNonterminal(_) => {
                 if declared_lhs_depth == 0 {
-                    return Err(cx.struct_span_err(
-                        sp.entire(),
-                        "`count` can not be placed inside the inner-most repetition",
-                    ));
+                    return Err(cx.create_err(CountRepetitionMisplaced { span: sp.entire() }));
                 }
                 match depth_opt {
                     None => Ok(1),
@@ -499,12 +490,7 @@ where
 {
     let span = ident.span;
     let key = MacroRulesNormalizedIdent::new(ident);
-    interp.get(&key).ok_or_else(|| {
-        cx.struct_span_err(
-            span,
-            &format!("variable `{}` is not recognized in meta-variable expression", key),
-        )
-    })
+    interp.get(&key).ok_or_else(|| cx.create_err(MetaVarExprUnrecognizedVar { span, key }))
 }
 
 /// Used by meta-variable expressions when an user input is out of the actual declared bounds. For
diff --git a/compiler/rustc_expand/src/module.rs b/compiler/rustc_expand/src/module.rs
index 0315d11634c..9002a24e42f 100644
--- a/compiler/rustc_expand/src/module.rs
+++ b/compiler/rustc_expand/src/module.rs
@@ -1,6 +1,6 @@
 use crate::base::ModuleData;
 use rustc_ast::ptr::P;
-use rustc_ast::{token, Attribute, Inline, Item, ModSpans};
+use rustc_ast::{token, AttrVec, Attribute, Inline, Item, ModSpans};
 use rustc_errors::{struct_span_err, DiagnosticBuilder, ErrorGuaranteed};
 use rustc_parse::new_parser_from_file;
 use rustc_parse::validate_attr;
@@ -48,7 +48,7 @@ pub(crate) fn parse_external_mod(
     span: Span, // The span to blame on errors.
     module: &ModuleData,
     mut dir_ownership: DirOwnership,
-    attrs: &mut Vec<Attribute>,
+    attrs: &mut AttrVec,
 ) -> ParsedExternalMod {
     // We bail on the first error, but that error does not cause a fatal error... (1)
     let result: Result<_, ModError<'_>> = try {
@@ -63,9 +63,9 @@ pub(crate) fn parse_external_mod(
 
         // Actually parse the external file as a module.
         let mut parser = new_parser_from_file(&sess.parse_sess, &mp.file_path, Some(span));
-        let (mut inner_attrs, items, inner_span) =
+        let (inner_attrs, items, inner_span) =
             parser.parse_mod(&token::Eof).map_err(|err| ModError::ParserError(err))?;
-        attrs.append(&mut inner_attrs);
+        attrs.extend(inner_attrs);
         (items, inner_span, mp.file_path)
     };
     // (1) ...instead, we return a dummy module.
diff --git a/compiler/rustc_expand/src/placeholders.rs b/compiler/rustc_expand/src/placeholders.rs
index 0d5d6ee0794..3b0d5ddb97b 100644
--- a/compiler/rustc_expand/src/placeholders.rs
+++ b/compiler/rustc_expand/src/placeholders.rs
@@ -15,16 +15,16 @@ pub fn placeholder(
     id: ast::NodeId,
     vis: Option<ast::Visibility>,
 ) -> AstFragment {
-    fn mac_placeholder() -> ast::MacCall {
-        ast::MacCall {
+    fn mac_placeholder() -> P<ast::MacCall> {
+        P(ast::MacCall {
             path: ast::Path { span: DUMMY_SP, segments: Vec::new(), tokens: None },
             args: P(ast::MacArgs::Empty),
             prior_type_ascription: None,
-        }
+        })
     }
 
     let ident = Ident::empty();
-    let attrs = Vec::new();
+    let attrs = ast::AttrVec::new();
     let vis = vis.unwrap_or(ast::Visibility {
         span: DUMMY_SP,
         kind: ast::VisibilityKind::Inherited,
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index efb83052768..e44c9291f84 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -12,6 +12,8 @@
 //! symbol to the `accepted` or `removed` modules respectively.
 
 #![feature(once_cell)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 mod accepted;
 mod active;
diff --git a/compiler/rustc_fs_util/src/lib.rs b/compiler/rustc_fs_util/src/lib.rs
index 87e97c746ef..63998bb6b00 100644
--- a/compiler/rustc_fs_util/src/lib.rs
+++ b/compiler/rustc_fs_util/src/lib.rs
@@ -1,3 +1,6 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
 use std::ffi::CString;
 use std::fs;
 use std::io;
diff --git a/compiler/rustc_graphviz/src/lib.rs b/compiler/rustc_graphviz/src/lib.rs
index 6eaff5c2f74..3c1bb553266 100644
--- a/compiler/rustc_graphviz/src/lib.rs
+++ b/compiler/rustc_graphviz/src/lib.rs
@@ -273,6 +273,8 @@
     html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/",
     test(attr(allow(unused_variables), deny(warnings)))
 )]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 use LabelText::*;
 
diff --git a/compiler/rustc_hir/src/lib.rs b/compiler/rustc_hir/src/lib.rs
index 0f9e6fa7b98..7097f998beb 100644
--- a/compiler/rustc_hir/src/lib.rs
+++ b/compiler/rustc_hir/src/lib.rs
@@ -11,6 +11,8 @@
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 0f754dddbec..42663da8a3f 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -1,4 +1,6 @@
 #![recursion_limit = "256"]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 use rustc_ast as ast;
 use rustc_ast::util::parser::{self, AssocOp, Fixity};
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 33c3c536f11..aa34673de81 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 #![feature(allow_internal_unstable)]
 #![feature(bench_black_box)]
 #![feature(extend_one)]
diff --git a/compiler/rustc_infer/src/infer/error_reporting/mod.rs b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
index 3c7dac2bfd8..59ea1f3f9de 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/mod.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/mod.rs
@@ -66,6 +66,7 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::Node;
 use rustc_middle::dep_graph::DepContext;
 use rustc_middle::ty::print::with_no_trimmed_paths;
+use rustc_middle::ty::relate::{self, RelateResult, TypeRelation};
 use rustc_middle::ty::{
     self, error::TypeError, Binder, List, Region, Subst, Ty, TyCtxt, TypeFoldable,
     TypeSuperVisitable, TypeVisitable,
@@ -739,12 +740,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 err.help("...or use `match` instead of `let...else`");
             }
             _ => {
-                if let ObligationCauseCode::BindingObligation(_, binding_span) =
-                    cause.code().peel_derives()
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..)
+                    = cause.code().peel_derives()
+                    && let TypeError::RegionsPlaceholderMismatch = terr
                 {
-                    if matches!(terr, TypeError::RegionsPlaceholderMismatch) {
-                        err.span_note(*binding_span, "the lifetime requirement is introduced here");
-                    }
+                    err.span_note(*span, "the lifetime requirement is introduced here");
                 }
             }
         }
@@ -2079,7 +2080,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                             diag.span_suggestion(
                                 span,
                                 *msg,
-                                format!("{}.as_ref()", snippet),
+                                // HACK: fix issue# 100605, suggesting convert from &Option<T> to Option<&T>, remove the extra `&`
+                                format!("{}.as_ref()", snippet.trim_start_matches('&')),
                                 Applicability::MachineApplicable,
                             );
                         }
@@ -2660,67 +2662,92 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     /// Float types, respectively). When comparing two ADTs, these rules apply recursively.
     pub fn same_type_modulo_infer(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
         let (a, b) = self.resolve_vars_if_possible((a, b));
-        match (a.kind(), b.kind()) {
-            (&ty::Adt(def_a, substs_a), &ty::Adt(def_b, substs_b)) => {
-                if def_a != def_b {
-                    return false;
-                }
+        SameTypeModuloInfer(self).relate(a, b).is_ok()
+    }
+}
 
-                substs_a
-                    .types()
-                    .zip(substs_b.types())
-                    .all(|(a, b)| self.same_type_modulo_infer(a, b))
-            }
-            (&ty::FnDef(did_a, substs_a), &ty::FnDef(did_b, substs_b)) => {
-                if did_a != did_b {
-                    return false;
-                }
+struct SameTypeModuloInfer<'a, 'tcx>(&'a InferCtxt<'a, 'tcx>);
 
-                substs_a
-                    .types()
-                    .zip(substs_b.types())
-                    .all(|(a, b)| self.same_type_modulo_infer(a, b))
-            }
-            (&ty::Int(_) | &ty::Uint(_), &ty::Infer(ty::InferTy::IntVar(_)))
+impl<'tcx> TypeRelation<'tcx> for SameTypeModuloInfer<'_, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'tcx> {
+        self.0.tcx
+    }
+
+    fn param_env(&self) -> ty::ParamEnv<'tcx> {
+        // Unused, only for consts which we treat as always equal
+        ty::ParamEnv::empty()
+    }
+
+    fn tag(&self) -> &'static str {
+        "SameTypeModuloInfer"
+    }
+
+    fn a_is_expected(&self) -> bool {
+        true
+    }
+
+    fn relate_with_variance<T: relate::Relate<'tcx>>(
+        &mut self,
+        _variance: ty::Variance,
+        _info: ty::VarianceDiagInfo<'tcx>,
+        a: T,
+        b: T,
+    ) -> relate::RelateResult<'tcx, T> {
+        self.relate(a, b)
+    }
+
+    fn tys(&mut self, a: Ty<'tcx>, b: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
+        match (a.kind(), b.kind()) {
+            (ty::Int(_) | ty::Uint(_), ty::Infer(ty::InferTy::IntVar(_)))
             | (
-                &ty::Infer(ty::InferTy::IntVar(_)),
-                &ty::Int(_) | &ty::Uint(_) | &ty::Infer(ty::InferTy::IntVar(_)),
+                ty::Infer(ty::InferTy::IntVar(_)),
+                ty::Int(_) | ty::Uint(_) | ty::Infer(ty::InferTy::IntVar(_)),
             )
-            | (&ty::Float(_), &ty::Infer(ty::InferTy::FloatVar(_)))
+            | (ty::Float(_), ty::Infer(ty::InferTy::FloatVar(_)))
             | (
-                &ty::Infer(ty::InferTy::FloatVar(_)),
-                &ty::Float(_) | &ty::Infer(ty::InferTy::FloatVar(_)),
+                ty::Infer(ty::InferTy::FloatVar(_)),
+                ty::Float(_) | ty::Infer(ty::InferTy::FloatVar(_)),
             )
-            | (&ty::Infer(ty::InferTy::TyVar(_)), _)
-            | (_, &ty::Infer(ty::InferTy::TyVar(_))) => true,
-            (&ty::Ref(_, ty_a, mut_a), &ty::Ref(_, ty_b, mut_b)) => {
-                mut_a == mut_b && self.same_type_modulo_infer(ty_a, ty_b)
-            }
-            (&ty::RawPtr(a), &ty::RawPtr(b)) => {
-                a.mutbl == b.mutbl && self.same_type_modulo_infer(a.ty, b.ty)
-            }
-            (&ty::Slice(a), &ty::Slice(b)) => self.same_type_modulo_infer(a, b),
-            (&ty::Array(a_ty, a_ct), &ty::Array(b_ty, b_ct)) => {
-                self.same_type_modulo_infer(a_ty, b_ty) && a_ct == b_ct
-            }
-            (&ty::Tuple(a), &ty::Tuple(b)) => {
-                if a.len() != b.len() {
-                    return false;
-                }
-                std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
-            }
-            (&ty::FnPtr(a), &ty::FnPtr(b)) => {
-                let a = a.skip_binder().inputs_and_output;
-                let b = b.skip_binder().inputs_and_output;
-                if a.len() != b.len() {
-                    return false;
-                }
-                std::iter::zip(a.iter(), b.iter()).all(|(a, b)| self.same_type_modulo_infer(a, b))
-            }
-            // FIXME(compiler-errors): This needs to be generalized more
-            _ => a == b,
+            | (ty::Infer(ty::InferTy::TyVar(_)), _)
+            | (_, ty::Infer(ty::InferTy::TyVar(_))) => Ok(a),
+            (ty::Infer(_), _) | (_, ty::Infer(_)) => Err(TypeError::Mismatch),
+            _ => relate::super_relate_tys(self, a, b),
         }
     }
+
+    fn regions(
+        &mut self,
+        a: ty::Region<'tcx>,
+        b: ty::Region<'tcx>,
+    ) -> RelateResult<'tcx, ty::Region<'tcx>> {
+        if (a.is_var() && b.is_free_or_static()) || (b.is_var() && a.is_free_or_static()) || a == b
+        {
+            Ok(a)
+        } else {
+            Err(TypeError::Mismatch)
+        }
+    }
+
+    fn binders<T>(
+        &mut self,
+        a: ty::Binder<'tcx, T>,
+        b: ty::Binder<'tcx, T>,
+    ) -> relate::RelateResult<'tcx, ty::Binder<'tcx, T>>
+    where
+        T: relate::Relate<'tcx>,
+    {
+        Ok(ty::Binder::dummy(self.relate(a.skip_binder(), b.skip_binder())?))
+    }
+
+    fn consts(
+        &mut self,
+        a: ty::Const<'tcx>,
+        _b: ty::Const<'tcx>,
+    ) -> relate::RelateResult<'tcx, ty::Const<'tcx>> {
+        // FIXME(compiler-errors): This could at least do some first-order
+        // relation
+        Ok(a)
+    }
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
index 893ca3cf79d..c20b96cae2e 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/mismatched_static_lifetime.rs
@@ -35,7 +35,8 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
         let ObligationCauseCode::MatchImpl(parent, impl_def_id) = code else {
             return None;
         };
-        let ObligationCauseCode::BindingObligation(_def_id, binding_span) = *parent.code() else {
+        let (ObligationCauseCode::BindingObligation(_, binding_span) | ObligationCauseCode::ExprBindingObligation(_, binding_span, ..))
+            = *parent.code() else {
             return None;
         };
         let mut err = self.tcx().sess.struct_span_err(cause.span, "incompatible lifetime on type");
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
index 998699158ff..d4db0751212 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/placeholder_error.rs
@@ -211,7 +211,10 @@ impl<'tcx> NiceRegionError<'_, 'tcx> {
         );
         let mut err = self.tcx().sess.struct_span_err(span, &msg);
 
-        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id) = *cause.code() {
+        let leading_ellipsis = if let ObligationCauseCode::ItemObligation(def_id)
+        | ObligationCauseCode::ExprItemObligation(def_id, ..) =
+            *cause.code()
+        {
             err.span_label(span, "doesn't satisfy where-clause");
             err.span_label(
                 self.tcx().def_span(def_id),
diff --git a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
index 9886c572a8a..f804569b074 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/nice_region_error/static_impl_trait.rs
@@ -232,7 +232,7 @@ impl<'a, 'tcx> NiceRegionError<'a, 'tcx> {
                 ObligationCauseCode::MatchImpl(parent, ..) => parent.code(),
                 _ => cause.code(),
             }
-            && let (&ObligationCauseCode::ItemObligation(item_def_id), None) = (code, override_error_code)
+            && let (&ObligationCauseCode::ItemObligation(item_def_id) | &ObligationCauseCode::ExprItemObligation(item_def_id, ..), None) = (code, override_error_code)
         {
             // Same case of `impl Foo for dyn Bar { fn qux(&self) {} }` introducing a `'static`
             // lifetime as above, but called using a fully-qualified path to the method:
diff --git a/compiler/rustc_infer/src/infer/error_reporting/note.rs b/compiler/rustc_infer/src/infer/error_reporting/note.rs
index 8dabdfd55c7..8c465b08760 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/note.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/note.rs
@@ -390,10 +390,12 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 if matches!(
                     &trace.cause.code().peel_derives(),
                     ObligationCauseCode::BindingObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
                 ) =>
             {
                 // Hack to get around the borrow checker because trace.cause has an `Rc`.
-                if let ObligationCauseCode::BindingObligation(_, span) =
+                if let ObligationCauseCode::BindingObligation(_, span)
+                | ObligationCauseCode::ExprBindingObligation(_, span, ..) =
                     &trace.cause.code().peel_derives()
                 {
                     let span = *span;
diff --git a/compiler/rustc_infer/src/infer/free_regions.rs b/compiler/rustc_infer/src/infer/free_regions.rs
index d566634a492..728d691a2be 100644
--- a/compiler/rustc_infer/src/infer/free_regions.rs
+++ b/compiler/rustc_infer/src/infer/free_regions.rs
@@ -27,13 +27,13 @@ impl<'a, 'tcx> RegionRelations<'a, 'tcx> {
     }
 }
 
-#[derive(Clone, Debug, Default)]
+#[derive(Clone, Debug)]
 pub struct FreeRegionMap<'tcx> {
     // Stores the relation `a < b`, where `a` and `b` are regions.
     //
     // Invariant: only free regions like `'x` or `'static` are stored
     // in this relation, not scopes.
-    relation: TransitiveRelation<Region<'tcx>>,
+    pub(crate) relation: TransitiveRelation<Region<'tcx>>,
 }
 
 impl<'tcx> FreeRegionMap<'tcx> {
@@ -45,15 +45,6 @@ impl<'tcx> FreeRegionMap<'tcx> {
         self.relation.is_empty()
     }
 
-    // Record that `'sup:'sub`. Or, put another way, `'sub <= 'sup`.
-    // (with the exception that `'static: 'x` is not notable)
-    pub fn relate_regions(&mut self, sub: Region<'tcx>, sup: Region<'tcx>) {
-        debug!("relate_regions(sub={:?}, sup={:?})", sub, sup);
-        if sub.is_free_or_static() && sup.is_free() {
-            self.relation.add(sub, sup)
-        }
-    }
-
     /// Tests whether `r_a <= r_b`.
     ///
     /// Both regions must meet `is_free_or_static`.
diff --git a/compiler/rustc_infer/src/infer/opaque_types.rs b/compiler/rustc_infer/src/infer/opaque_types.rs
index a1c7b70bd9c..e579afbf389 100644
--- a/compiler/rustc_infer/src/infer/opaque_types.rs
+++ b/compiler/rustc_infer/src/infer/opaque_types.rs
@@ -40,15 +40,17 @@ pub struct OpaqueTypeDecl<'tcx> {
 }
 
 impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn replace_opaque_types_with_inference_vars(
+    /// This is a backwards compatibility hack to prevent breaking changes from
+    /// lazy TAIT around RPIT handling.
+    pub fn replace_opaque_types_with_inference_vars<T: TypeFoldable<'tcx>>(
         &self,
-        ty: Ty<'tcx>,
+        value: T,
         body_id: HirId,
         span: Span,
         param_env: ty::ParamEnv<'tcx>,
-    ) -> InferOk<'tcx, Ty<'tcx>> {
-        if !ty.has_opaque_types() {
-            return InferOk { value: ty, obligations: vec![] };
+    ) -> InferOk<'tcx, T> {
+        if !value.has_opaque_types() {
+            return InferOk { value, obligations: vec![] };
         }
         let mut obligations = vec![];
         let replace_opaque_type = |def_id: DefId| {
@@ -56,7 +58,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                 .as_local()
                 .map_or(false, |def_id| self.opaque_type_origin(def_id, span).is_some())
         };
-        let value = ty.fold_with(&mut ty::fold::BottomUpFolder {
+        let value = value.fold_with(&mut ty::fold::BottomUpFolder {
             tcx: self.tcx,
             lt_op: |lt| lt,
             ct_op: |ct| ct,
diff --git a/compiler/rustc_infer/src/infer/outlives/env.rs b/compiler/rustc_infer/src/infer/outlives/env.rs
index b2decd64f0f..872886da362 100644
--- a/compiler/rustc_infer/src/infer/outlives/env.rs
+++ b/compiler/rustc_infer/src/infer/outlives/env.rs
@@ -2,6 +2,7 @@ use crate::infer::free_regions::FreeRegionMap;
 use crate::infer::{GenericKind, InferCtxt};
 use crate::traits::query::OutlivesBound;
 use rustc_data_structures::fx::FxIndexSet;
+use rustc_data_structures::transitive_relation::TransitiveRelationBuilder;
 use rustc_middle::ty::{self, ReEarlyBound, ReFree, ReVar, Region};
 
 use super::explicit_outlives_bounds;
@@ -51,23 +52,48 @@ pub struct OutlivesEnvironment<'tcx> {
     region_bound_pairs: RegionBoundPairs<'tcx>,
 }
 
+/// Builder of OutlivesEnvironment.
+struct OutlivesEnvironmentBuilder<'tcx> {
+    param_env: ty::ParamEnv<'tcx>,
+    region_relation: TransitiveRelationBuilder<Region<'tcx>>,
+    region_bound_pairs: RegionBoundPairs<'tcx>,
+}
+
 /// "Region-bound pairs" tracks outlives relations that are known to
 /// be true, either because of explicit where-clauses like `T: 'a` or
 /// because of implied bounds.
 pub type RegionBoundPairs<'tcx> =
     FxIndexSet<ty::OutlivesPredicate<GenericKind<'tcx>, Region<'tcx>>>;
 
-impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
-    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
-        let mut env = OutlivesEnvironment {
+impl<'tcx> OutlivesEnvironment<'tcx> {
+    /// Create a builder using `ParamEnv` and add explicit outlives bounds into it.
+    fn builder(param_env: ty::ParamEnv<'tcx>) -> OutlivesEnvironmentBuilder<'tcx> {
+        let mut builder = OutlivesEnvironmentBuilder {
             param_env,
-            free_region_map: Default::default(),
+            region_relation: Default::default(),
             region_bound_pairs: Default::default(),
         };
 
-        env.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
+        builder.add_outlives_bounds(None, explicit_outlives_bounds(param_env));
 
-        env
+        builder
+    }
+
+    #[inline]
+    /// Create a new `OutlivesEnvironment` without extra outlives bounds.
+    pub fn new(param_env: ty::ParamEnv<'tcx>) -> Self {
+        Self::builder(param_env).build()
+    }
+
+    /// Create a new `OutlivesEnvironment` with extra outlives bounds.
+    pub fn with_bounds<'a>(
+        param_env: ty::ParamEnv<'tcx>,
+        infcx: Option<&InferCtxt<'a, 'tcx>>,
+        extra_bounds: impl IntoIterator<Item = OutlivesBound<'tcx>>,
+    ) -> Self {
+        let mut builder = Self::builder(param_env);
+        builder.add_outlives_bounds(infcx, extra_bounds);
+        builder.build()
     }
 
     /// Borrows current value of the `free_region_map`.
@@ -79,6 +105,17 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
     pub fn region_bound_pairs(&self) -> &RegionBoundPairs<'tcx> {
         &self.region_bound_pairs
     }
+}
+
+impl<'a, 'tcx> OutlivesEnvironmentBuilder<'tcx> {
+    #[inline]
+    fn build(self) -> OutlivesEnvironment<'tcx> {
+        OutlivesEnvironment {
+            param_env: self.param_env,
+            free_region_map: FreeRegionMap { relation: self.region_relation.freeze() },
+            region_bound_pairs: self.region_bound_pairs,
+        }
+    }
 
     /// Processes outlives bounds that are known to hold, whether from implied or other sources.
     ///
@@ -86,11 +123,8 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
     /// contain inference variables, it must be supplied, in which
     /// case we will register "givens" on the inference context. (See
     /// `RegionConstraintData`.)
-    pub fn add_outlives_bounds<I>(
-        &mut self,
-        infcx: Option<&InferCtxt<'a, 'tcx>>,
-        outlives_bounds: I,
-    ) where
+    fn add_outlives_bounds<I>(&mut self, infcx: Option<&InferCtxt<'a, 'tcx>>, outlives_bounds: I)
+    where
         I: IntoIterator<Item = OutlivesBound<'tcx>>,
     {
         // Record relationships such as `T:'x` that don't go into the
@@ -122,7 +156,9 @@ impl<'a, 'tcx> OutlivesEnvironment<'tcx> {
                         // system to be more general and to make use
                         // of *every* relationship that arises here,
                         // but presently we do not.)
-                        self.free_region_map.relate_regions(r_a, r_b);
+                        if r_a.is_free_or_static() && r_b.is_free() {
+                            self.region_relation.add(r_a, r_b)
+                        }
                     }
                 }
             }
diff --git a/compiler/rustc_infer/src/infer/outlives/obligations.rs b/compiler/rustc_infer/src/infer/outlives/obligations.rs
index ad052f58ca8..dded0a0a6b1 100644
--- a/compiler/rustc_infer/src/infer/outlives/obligations.rs
+++ b/compiler/rustc_infer/src/infer/outlives/obligations.rs
@@ -97,7 +97,8 @@ impl<'cx, 'tcx> InferCtxt<'cx, 'tcx> {
                 cause.span,
                 sup_type,
                 match cause.code().peel_derives() {
-                    ObligationCauseCode::BindingObligation(_, span) => Some(*span),
+                    ObligationCauseCode::BindingObligation(_, span)
+                    | ObligationCauseCode::ExprBindingObligation(_, span, ..) => Some(*span),
                     _ => None,
                 },
             )
diff --git a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
index 772e297b7b4..be03c8b5bae 100644
--- a/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
+++ b/compiler/rustc_infer/src/infer/outlives/test_type_match.rs
@@ -174,7 +174,14 @@ impl<'tcx> TypeRelation<'tcx> for Match<'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     fn tys(&mut self, pattern: Ty<'tcx>, value: Ty<'tcx>) -> RelateResult<'tcx, Ty<'tcx>> {
-        if pattern == value { Ok(pattern) } else { relate::super_relate_tys(self, pattern, value) }
+        if let ty::Error(_) = pattern.kind() {
+            // Unlike normal `TypeRelation` rules, `ty::Error` does not equal any type.
+            self.no_match()
+        } else if pattern == value {
+            Ok(pattern)
+        } else {
+            relate::super_relate_tys(self, pattern, value)
+        }
     }
 
     #[instrument(skip(self), level = "debug")]
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index e00d0b7d0d8..014cf88389e 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -265,7 +265,7 @@ impl LintStoreExpand for LintStoreExpandImpl<'_> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(interface::ferris_identifier)]
+#[diag(interface::ferris_identifier)]
 struct FerrisIdentifier {
     #[primary_span]
     spans: Vec<Span>,
@@ -274,7 +274,7 @@ struct FerrisIdentifier {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(interface::emoji_identifier)]
+#[diag(interface::emoji_identifier)]
 struct EmojiIdentifier {
     #[primary_span]
     spans: Vec<Span>,
diff --git a/compiler/rustc_lexer/src/lib.rs b/compiler/rustc_lexer/src/lib.rs
index 6d311af9007..178366f7d80 100644
--- a/compiler/rustc_lexer/src/lib.rs
+++ b/compiler/rustc_lexer/src/lib.rs
@@ -18,6 +18,8 @@
 //! lexeme types.
 //!
 //! [`rustc_parse::lexer`]: ../rustc_parse/lexer/index.html
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 // We want to be able to build this crate with a stable compiler, so no
 // `#![feature]` attributes should be added.
 
diff --git a/compiler/rustc_lint/src/early.rs b/compiler/rustc_lint/src/early.rs
index 580a4566869..cdb5b3c4284 100644
--- a/compiler/rustc_lint/src/early.rs
+++ b/compiler/rustc_lint/src/early.rs
@@ -45,7 +45,7 @@ impl<'a, T: EarlyLintPass> EarlyContextAndPass<'a, T> {
                 lint_id.lint,
                 Some(span),
                 |lint| {
-                    lint.build(&msg).emit();
+                    lint.build(msg).emit();
                 },
                 diagnostic,
             );
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index cafd2c6e679..484e541afc5 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1546,7 +1546,7 @@ impl InvalidAtomicOrdering {
 
         if matches!(fail_ordering, sym::Release | sym::AcqRel) {
             #[derive(LintDiagnostic)]
-            #[lint(lint::atomic_ordering_invalid)]
+            #[diag(lint::atomic_ordering_invalid)]
             #[help]
             struct InvalidAtomicOrderingDiag {
                 method: Symbol,
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index f00165cd3b3..95e34da734d 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3212,6 +3212,56 @@ declare_lint! {
     };
 }
 
+declare_lint! {
+    /// The `unstable_syntax_pre_expansion` lint detects the use of unstable
+    /// syntax that is discarded during attribute expansion.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// #[cfg(FALSE)]
+    /// macro foo() {}
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The input to active attributes such as `#[cfg]` or procedural macro
+    /// attributes is required to be valid syntax. Previously, the compiler only
+    /// gated the use of unstable syntax features after resolving `#[cfg]` gates
+    /// and expanding procedural macros.
+    ///
+    /// To avoid relying on unstable syntax, move the use of unstable syntax
+    /// into a position where the compiler does not parse the syntax, such as a
+    /// functionlike macro.
+    ///
+    /// ```rust
+    /// # #![deny(unstable_syntax_pre_expansion)]
+    ///
+    /// macro_rules! identity {
+    ///    ( $($tokens:tt)* ) => { $($tokens)* }
+    /// }
+    ///
+    /// #[cfg(FALSE)]
+    /// identity! {
+    ///    macro foo() {}
+    /// }
+    /// ```
+    ///
+    /// This is a [future-incompatible] lint to transition this
+    /// to a hard error in the future. See [issue #65860] for more details.
+    ///
+    /// [issue #65860]: https://github.com/rust-lang/rust/issues/65860
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub UNSTABLE_SYNTAX_PRE_EXPANSION,
+    Warn,
+    "unstable syntax can change at any point in the future, causing a hard error!",
+    @future_incompatible = FutureIncompatibleInfo {
+        reference: "issue #65860 <https://github.com/rust-lang/rust/issues/65860>",
+    };
+}
+
 declare_lint_pass! {
     /// Does nothing as a lint pass, but registers some `Lint`s
     /// that are used by other parts of the compiler.
@@ -3280,6 +3330,7 @@ declare_lint_pass! {
         POINTER_STRUCTURAL_MATCH,
         NONTRIVIAL_STRUCTURAL_MATCH,
         SOFT_UNSTABLE,
+        UNSTABLE_SYNTAX_PRE_EXPANSION,
         INLINE_NO_SANITIZE,
         BAD_ASM_STYLE,
         ASM_SUB_REGISTER,
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index 6acbe97a7a1..9e7cbba9511 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -1,4 +1,6 @@
 #![feature(min_specialization)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -7,7 +9,7 @@ pub use self::Level::*;
 use rustc_ast::node_id::{NodeId, NodeMap};
 use rustc_ast::{AttrId, Attribute};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
-use rustc_error_messages::MultiSpan;
+use rustc_error_messages::{DiagnosticMessage, MultiSpan};
 use rustc_hir::HashStableContext;
 use rustc_hir::HirId;
 use rustc_span::edition::Edition;
@@ -489,7 +491,7 @@ pub struct BufferedEarlyLint {
     pub span: MultiSpan,
 
     /// The lint message.
-    pub msg: String,
+    pub msg: DiagnosticMessage,
 
     /// The `NodeId` of the AST node that generated the lint.
     pub node_id: NodeId,
@@ -518,11 +520,11 @@ impl LintBuffer {
         lint: &'static Lint,
         node_id: NodeId,
         span: MultiSpan,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         let lint_id = LintId::of(lint);
-        let msg = msg.to_string();
+        let msg = msg.into();
         self.add_early_lint(BufferedEarlyLint { lint_id, node_id, span, msg, diagnostic });
     }
 
@@ -535,7 +537,7 @@ impl LintBuffer {
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
     ) {
         self.add_lint(lint, id, sp.into(), msg, BuiltinLintDiagnostics::Normal)
     }
@@ -545,7 +547,7 @@ impl LintBuffer {
         lint: &'static Lint,
         id: NodeId,
         sp: impl Into<MultiSpan>,
-        msg: &str,
+        msg: impl Into<DiagnosticMessage>,
         diagnostic: BuiltinLintDiagnostics,
     ) {
         self.add_lint(lint, id, sp.into(), msg, diagnostic)
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index b4314223722..05d2a214d0b 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -31,6 +31,9 @@
 #include "llvm/Transforms/IPO/PassManagerBuilder.h"
 #include "llvm/Transforms/IPO/AlwaysInliner.h"
 #include "llvm/Transforms/IPO/FunctionImport.h"
+#if LLVM_VERSION_GE(15, 0)
+#include "llvm/Transforms/IPO/ThinLTOBitcodeWriter.h"
+#endif
 #include "llvm/Transforms/Utils/AddDiscriminators.h"
 #include "llvm/Transforms/Utils/FunctionImportUtils.h"
 #include "llvm/LTO/LTO.h"
@@ -1587,13 +1590,31 @@ LLVMRustThinLTOBufferCreate(LLVMModuleRef M, bool is_thin) {
   {
     raw_string_ostream OS(Ret->data);
     {
-      legacy::PassManager PM;
       if (is_thin) {
+#if LLVM_VERSION_LT(15, 0)
+        legacy::PassManager PM;
         PM.add(createWriteThinLTOBitcodePass(OS));
+        PM.run(*unwrap(M));
+#else
+        PassBuilder PB;
+        LoopAnalysisManager LAM;
+        FunctionAnalysisManager FAM;
+        CGSCCAnalysisManager CGAM;
+        ModuleAnalysisManager MAM;
+        PB.registerModuleAnalyses(MAM);
+        PB.registerCGSCCAnalyses(CGAM);
+        PB.registerFunctionAnalyses(FAM);
+        PB.registerLoopAnalyses(LAM);
+        PB.crossRegisterProxies(LAM, FAM, CGAM, MAM);
+        ModulePassManager MPM;
+        MPM.addPass(ThinLTOBitcodeWriterPass(OS, nullptr));
+        MPM.run(*unwrap(M), MAM);
+#endif
       } else {
+        legacy::PassManager PM;
         PM.add(createBitcodeWriterPass(OS));
+        PM.run(*unwrap(M));
       }
-      PM.run(*unwrap(M));
     }
   }
   return Ret.release();
diff --git a/compiler/rustc_llvm/src/lib.rs b/compiler/rustc_llvm/src/lib.rs
index 8eade02a408..8542dcf5bf0 100644
--- a/compiler/rustc_llvm/src/lib.rs
+++ b/compiler/rustc_llvm/src/lib.rs
@@ -1,3 +1,5 @@
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 
 // NOTE: This crate only exists to allow linking on mingw targets.
diff --git a/compiler/rustc_log/src/lib.rs b/compiler/rustc_log/src/lib.rs
index f2ec80b0c1b..458f5e87bae 100644
--- a/compiler/rustc_log/src/lib.rs
+++ b/compiler/rustc_log/src/lib.rs
@@ -38,6 +38,9 @@
 //! debugging, you can make changes inside those crates and quickly run main.rs
 //! to read the debug logs.
 
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
+
 use std::env::{self, VarError};
 use std::fmt::{self, Display};
 use std::io;
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic.rs b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
index 6b5b8b59320..244edec2841 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic.rs
@@ -21,7 +21,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
             builder: DiagnosticDeriveBuilder {
                 diag,
                 fields: build_field_mapping(&structure),
-                kind: None,
+                kind: DiagnosticDeriveKind::SessionDiagnostic,
                 code: None,
                 slug: None,
             },
@@ -34,49 +34,31 @@ impl<'a> SessionDiagnosticDerive<'a> {
         let SessionDiagnosticDerive { mut structure, sess, mut builder } = self;
 
         let ast = structure.ast();
-        let (implementation, param_ty) = {
+        let implementation = {
             if let syn::Data::Struct(..) = ast.data {
                 let preamble = builder.preamble(&structure);
                 let (attrs, args) = builder.body(&mut structure);
 
                 let span = ast.span().unwrap();
                 let diag = &builder.diag;
-                let init = match (builder.kind.value(), builder.slug.value()) {
-                    (None, _) => {
-                        span_err(span, "diagnostic kind not specified")
-                            .help("use the `#[error(...)]` attribute to create an error")
-                            .emit();
-                        return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                    }
-                    (Some(kind), None) => {
+                let init = match builder.slug.value() {
+                    None => {
                         span_err(span, "diagnostic slug not specified")
                             .help(&format!(
-                                "specify the slug as the first argument to the attribute, such as \
-                                 `#[{}(typeck::example_error)]`",
-                                kind.descr()
+                                "specify the slug as the first argument to the `#[diag(...)]` attribute, \
+                                such as `#[diag(typeck::example_error)]`",
                             ))
                             .emit();
                         return DiagnosticDeriveError::ErrorHandled.to_compile_error();
                     }
-                    (Some(DiagnosticDeriveKind::Lint), _) => {
-                        span_err(span, "only `#[error(..)]` and `#[warning(..)]` are supported")
-                            .help("use the `#[error(...)]` attribute to create a error")
-                            .emit();
-                        return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                    }
-                    (Some(DiagnosticDeriveKind::Error), Some(slug)) => {
-                        quote! {
-                            let mut #diag = #sess.struct_err(rustc_errors::fluent::#slug);
-                        }
-                    }
-                    (Some(DiagnosticDeriveKind::Warn), Some(slug)) => {
+                    Some(slug) => {
                         quote! {
-                            let mut #diag = #sess.struct_warn(rustc_errors::fluent::#slug);
+                            let mut #diag = #sess.struct_diagnostic(rustc_errors::fluent::#slug);
                         }
                     }
                 };
 
-                let implementation = quote! {
+                quote! {
                     #init
                     #preamble
                     match self {
@@ -86,18 +68,7 @@ impl<'a> SessionDiagnosticDerive<'a> {
                         #args
                     }
                     #diag
-                };
-                let param_ty = match builder.kind {
-                    Some((DiagnosticDeriveKind::Error, _)) => {
-                        quote! { rustc_errors::ErrorGuaranteed }
-                    }
-                    Some((DiagnosticDeriveKind::Lint | DiagnosticDeriveKind::Warn, _)) => {
-                        quote! { () }
-                    }
-                    _ => unreachable!(),
-                };
-
-                (implementation, param_ty)
+                }
             } else {
                 span_err(
                     ast.span().unwrap(),
@@ -105,20 +76,20 @@ impl<'a> SessionDiagnosticDerive<'a> {
                 )
                 .emit();
 
-                let implementation = DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                let param_ty = quote! { rustc_errors::ErrorGuaranteed };
-                (implementation, param_ty)
+                DiagnosticDeriveError::ErrorHandled.to_compile_error()
             }
         };
 
         structure.gen_impl(quote! {
-            gen impl<'__session_diagnostic_sess> rustc_session::SessionDiagnostic<'__session_diagnostic_sess, #param_ty>
+            gen impl<'__session_diagnostic_sess, G>
+                    rustc_session::SessionDiagnostic<'__session_diagnostic_sess, G>
                     for @Self
+                where G: rustc_errors::EmissionGuarantee
             {
                 fn into_diagnostic(
                     self,
                     #sess: &'__session_diagnostic_sess rustc_session::parse::ParseSess
-                ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, #param_ty> {
+                ) -> rustc_errors::DiagnosticBuilder<'__session_diagnostic_sess, G> {
                     use rustc_errors::IntoDiagnosticArg;
                     #implementation
                 }
@@ -139,7 +110,7 @@ impl<'a> LintDiagnosticDerive<'a> {
             builder: DiagnosticDeriveBuilder {
                 diag,
                 fields: build_field_mapping(&structure),
-                kind: None,
+                kind: DiagnosticDeriveKind::LintDiagnostic,
                 code: None,
                 slug: None,
             },
@@ -158,30 +129,17 @@ impl<'a> LintDiagnosticDerive<'a> {
 
                 let diag = &builder.diag;
                 let span = ast.span().unwrap();
-                let init = match (builder.kind.value(), builder.slug.value()) {
-                    (None, _) => {
-                        span_err(span, "diagnostic kind not specified")
-                            .help("use the `#[error(...)]` attribute to create an error")
-                            .emit();
-                        return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                    }
-                    (Some(kind), None) => {
+                let init = match builder.slug.value() {
+                    None => {
                         span_err(span, "diagnostic slug not specified")
                             .help(&format!(
                                 "specify the slug as the first argument to the attribute, such as \
-                                 `#[{}(typeck::example_error)]`",
-                                kind.descr()
+                                 `#[diag(typeck::example_error)]`",
                             ))
                             .emit();
                         return DiagnosticDeriveError::ErrorHandled.to_compile_error();
                     }
-                    (Some(DiagnosticDeriveKind::Error | DiagnosticDeriveKind::Warn), _) => {
-                        span_err(span, "only `#[lint(..)]` is supported")
-                            .help("use the `#[lint(...)]` attribute to create a lint")
-                            .emit();
-                        return DiagnosticDeriveError::ErrorHandled.to_compile_error();
-                    }
-                    (Some(DiagnosticDeriveKind::Lint), Some(slug)) => {
+                    Some(slug) => {
                         quote! {
                             let mut #diag = #diag.build(rustc_errors::fluent::#slug);
                         }
diff --git a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
index 6c9561925fe..9df9fa4e9bf 100644
--- a/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
+++ b/compiler/rustc_macros/src/diagnostics/diagnostic_builder.rs
@@ -18,30 +18,15 @@ use syn::{
 };
 use synstructure::{BindingInfo, Structure};
 
-/// What kind of diagnostic is being derived - an error, a warning or a lint?
-#[derive(Copy, Clone)]
+/// What kind of diagnostic is being derived - a fatal/error/warning or a lint?
+#[derive(Copy, Clone, PartialEq, Eq)]
 pub(crate) enum DiagnosticDeriveKind {
-    /// `#[error(..)]`
-    Error,
-    /// `#[warn(..)]`
-    Warn,
-    /// `#[lint(..)]`
-    Lint,
-}
-
-impl DiagnosticDeriveKind {
-    /// Returns human-readable string corresponding to the kind.
-    pub fn descr(&self) -> &'static str {
-        match self {
-            DiagnosticDeriveKind::Error => "error",
-            DiagnosticDeriveKind::Warn => "warning",
-            DiagnosticDeriveKind::Lint => "lint",
-        }
-    }
+    SessionDiagnostic,
+    LintDiagnostic,
 }
 
 /// Tracks persistent information required for building up individual calls to diagnostic methods
-/// for generated diagnostic derives - both `SessionDiagnostic` for errors/warnings and
+/// for generated diagnostic derives - both `SessionDiagnostic` for fatal/errors/warnings and
 /// `LintDiagnostic` for lints.
 pub(crate) struct DiagnosticDeriveBuilder {
     /// The identifier to use for the generated `DiagnosticBuilder` instance.
@@ -51,8 +36,8 @@ pub(crate) struct DiagnosticDeriveBuilder {
     /// derive builder.
     pub fields: HashMap<String, TokenStream>,
 
-    /// Kind of diagnostic requested via the struct attribute.
-    pub kind: Option<(DiagnosticDeriveKind, proc_macro::Span)>,
+    /// Kind of diagnostic that should be derived.
+    pub kind: DiagnosticDeriveKind,
     /// Slug is a mandatory part of the struct attribute as corresponds to the Fluent message that
     /// has the actual diagnostic message.
     pub slug: Option<(Path, proc_macro::Span)>,
@@ -143,7 +128,7 @@ impl DiagnosticDeriveBuilder {
     }
 
     /// Establishes state in the `DiagnosticDeriveBuilder` resulting from the struct
-    /// attributes like `#[error(..)`, such as the diagnostic kind and slug. Generates
+    /// attributes like `#[diag(..)]`, such as the slug and error code. Generates
     /// diagnostic builder calls for setting error code and creating note/help messages.
     fn generate_structure_code_for_attr(
         &mut self,
@@ -156,15 +141,15 @@ impl DiagnosticDeriveBuilder {
         let name = name.as_str();
         let meta = attr.parse_meta()?;
 
-        let is_help_note_or_warn = matches!(name, "help" | "note" | "warn_");
+        let is_diag = name == "diag";
 
         let nested = match meta {
-            // Most attributes are lists, like `#[error(..)]`/`#[warning(..)]` for most cases or
+            // Most attributes are lists, like `#[diag(..)]` for most cases or
             // `#[help(..)]`/`#[note(..)]` when the user is specifying a alternative slug.
             Meta::List(MetaList { ref nested, .. }) => nested,
             // Subdiagnostics without spans can be applied to the type too, and these are just
-            // paths: `#[help]` and `#[note]`
-            Meta::Path(_) if is_help_note_or_warn => {
+            // paths: `#[help]`, `#[note]` and `#[warn_]`
+            Meta::Path(_) if !is_diag => {
                 let fn_name = if name == "warn_" {
                     Ident::new("warn", attr.span())
                 } else {
@@ -178,23 +163,21 @@ impl DiagnosticDeriveBuilder {
         // Check the kind before doing any further processing so that there aren't misleading
         // "no kind specified" errors if there are failures later.
         match name {
-            "error" => self.kind.set_once((DiagnosticDeriveKind::Error, span)),
-            "warning" => self.kind.set_once((DiagnosticDeriveKind::Warn, span)),
-            "lint" => self.kind.set_once((DiagnosticDeriveKind::Lint, span)),
-            "help" | "note" | "warn_" => (),
+            "error" | "warning" | "lint" => throw_invalid_attr!(attr, &meta, |diag| {
+                diag.help("`error`, `warning` and `lint` have been replaced by `diag`")
+            }),
+            "diag" | "help" | "note" | "warn_" => (),
             _ => throw_invalid_attr!(attr, &meta, |diag| {
-                diag.help(
-                    "only `error`, `warning`, `help`, `note` and `warn_` are valid attributes",
-                )
+                diag.help("only `diag`, `help`, `note` and `warn_` are valid attributes")
             }),
         }
 
-        // First nested element should always be the path, e.g. `#[error(typeck::invalid)]` or
+        // First nested element should always be the path, e.g. `#[diag(typeck::invalid)]` or
         // `#[help(typeck::another_help)]`.
         let mut nested_iter = nested.into_iter();
         if let Some(nested_attr) = nested_iter.next() {
             // Report an error if there are any other list items after the path.
-            if is_help_note_or_warn && nested_iter.next().is_some() {
+            if !is_diag && nested_iter.next().is_some() {
                 throw_invalid_nested_attr!(attr, &nested_attr, |diag| {
                     diag.help(
                         "`help`, `note` and `warn_` struct attributes can only have one argument",
@@ -203,16 +186,16 @@ impl DiagnosticDeriveBuilder {
             }
 
             match nested_attr {
-                NestedMeta::Meta(Meta::Path(path)) if is_help_note_or_warn => {
-                    let fn_name = proc_macro2::Ident::new(name, attr.span());
-                    return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); });
-                }
                 NestedMeta::Meta(Meta::Path(path)) => {
-                    self.slug.set_once((path.clone(), span));
+                    if is_diag {
+                        self.slug.set_once((path.clone(), span));
+                    } else {
+                        let fn_name = proc_macro2::Ident::new(name, attr.span());
+                        return Ok(quote! { #diag.#fn_name(rustc_errors::fluent::#path); });
+                    }
                 }
                 NestedMeta::Meta(meta @ Meta::NameValue(_))
-                    if !is_help_note_or_warn
-                        && meta.path().segments.last().unwrap().ident == "code" =>
+                    if is_diag && meta.path().segments.last().unwrap().ident == "code" =>
                 {
                     // don't error for valid follow-up attributes
                 }
@@ -346,10 +329,20 @@ impl DiagnosticDeriveBuilder {
                 Ok(quote! {})
             }
             "primary_span" => {
-                report_error_if_not_applied_to_span(attr, &info)?;
-                Ok(quote! {
-                    #diag.set_span(#binding);
-                })
+                match self.kind {
+                    DiagnosticDeriveKind::SessionDiagnostic => {
+                        report_error_if_not_applied_to_span(attr, &info)?;
+
+                        Ok(quote! {
+                            #diag.set_span(#binding);
+                        })
+                    }
+                    DiagnosticDeriveKind::LintDiagnostic => {
+                        throw_invalid_attr!(attr, &meta, |diag| {
+                            diag.help("the `primary_span` field attribute is not valid for lint diagnostics")
+                        })
+                    }
+                }
             }
             "label" => {
                 report_error_if_not_applied_to_span(attr, &info)?;
diff --git a/compiler/rustc_macros/src/diagnostics/mod.rs b/compiler/rustc_macros/src/diagnostics/mod.rs
index 733454cb2a7..2ff21e18ff8 100644
--- a/compiler/rustc_macros/src/diagnostics/mod.rs
+++ b/compiler/rustc_macros/src/diagnostics/mod.rs
@@ -23,7 +23,7 @@ use synstructure::Structure;
 /// # extern crate rust_middle;
 /// # use rustc_middle::ty::Ty;
 /// #[derive(SessionDiagnostic)]
-/// #[error(borrowck::move_out_of_borrow, code = "E0505")]
+/// #[diag(borrowck::move_out_of_borrow, code = "E0505")]
 /// pub struct MoveOutOfBorrowError<'tcx> {
 ///     pub name: Ident,
 ///     pub ty: Ty<'tcx>,
@@ -67,7 +67,7 @@ pub fn session_diagnostic_derive(s: Structure<'_>) -> TokenStream {
 ///
 /// ```ignore (rust)
 /// #[derive(LintDiagnostic)]
-/// #[lint(lint::atomic_ordering_invalid_fail_success)]
+/// #[diag(lint::atomic_ordering_invalid_fail_success)]
 /// pub struct AtomicOrderingInvalidLint {
 ///     method: Symbol,
 ///     success_ordering: Symbol,
diff --git a/compiler/rustc_macros/src/diagnostics/utils.rs b/compiler/rustc_macros/src/diagnostics/utils.rs
index 002abb152f7..ad9ecd39b9e 100644
--- a/compiler/rustc_macros/src/diagnostics/utils.rs
+++ b/compiler/rustc_macros/src/diagnostics/utils.rs
@@ -235,35 +235,40 @@ pub(crate) trait HasFieldMap {
         // the referenced fields. Leaves `it` sitting on the closing brace of the format string, so
         // the next call to `it.next()` retrieves the next character.
         while let Some(c) = it.next() {
-            if c == '{' && *it.peek().unwrap_or(&'\0') != '{' {
-                let mut eat_argument = || -> Option<String> {
-                    let mut result = String::new();
-                    // Format specifiers look like:
-                    //
-                    //   format   := '{' [ argument ] [ ':' format_spec ] '}' .
-                    //
-                    // Therefore, we only need to eat until ':' or '}' to find the argument.
-                    while let Some(c) = it.next() {
-                        result.push(c);
-                        let next = *it.peek().unwrap_or(&'\0');
-                        if next == '}' {
-                            break;
-                        } else if next == ':' {
-                            // Eat the ':' character.
-                            assert_eq!(it.next().unwrap(), ':');
-                            break;
-                        }
-                    }
-                    // Eat until (and including) the matching '}'
-                    while it.next()? != '}' {
-                        continue;
+            if c != '{' {
+                continue;
+            }
+            if *it.peek().unwrap_or(&'\0') == '{' {
+                assert_eq!(it.next().unwrap(), '{');
+                continue;
+            }
+            let mut eat_argument = || -> Option<String> {
+                let mut result = String::new();
+                // Format specifiers look like:
+                //
+                //   format   := '{' [ argument ] [ ':' format_spec ] '}' .
+                //
+                // Therefore, we only need to eat until ':' or '}' to find the argument.
+                while let Some(c) = it.next() {
+                    result.push(c);
+                    let next = *it.peek().unwrap_or(&'\0');
+                    if next == '}' {
+                        break;
+                    } else if next == ':' {
+                        // Eat the ':' character.
+                        assert_eq!(it.next().unwrap(), ':');
+                        break;
                     }
-                    Some(result)
-                };
-
-                if let Some(referenced_field) = eat_argument() {
-                    referenced_fields.insert(referenced_field);
                 }
+                // Eat until (and including) the matching '}'
+                while it.next()? != '}' {
+                    continue;
+                }
+                Some(result)
+            };
+
+            if let Some(referenced_field) = eat_argument() {
+                referenced_fields.insert(referenced_field);
             }
         }
 
diff --git a/compiler/rustc_macros/src/lib.rs b/compiler/rustc_macros/src/lib.rs
index 2f9c13cf817..87d7ab6ed51 100644
--- a/compiler/rustc_macros/src/lib.rs
+++ b/compiler/rustc_macros/src/lib.rs
@@ -4,6 +4,8 @@
 #![feature(proc_macro_diagnostic)]
 #![feature(proc_macro_span)]
 #![allow(rustc::default_hash_types)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 #![recursion_limit = "128"]
 
 use synstructure::decl_derive;
@@ -127,9 +129,7 @@ decl_derive!([Lift, attributes(lift)] => lift::lift_derive);
 decl_derive!(
     [SessionDiagnostic, attributes(
         // struct attributes
-        warning,
-        error,
-        lint,
+        diag,
         help,
         note,
         warn_,
@@ -146,9 +146,7 @@ decl_derive!(
 decl_derive!(
     [LintDiagnostic, attributes(
         // struct attributes
-        warning,
-        error,
-        lint,
+        diag,
         help,
         note,
         warn_,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 40dc4fb052d..889001d0a84 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -99,7 +99,7 @@ pub(crate) struct CrateMetadata {
     /// Proc macro descriptions for this crate, if it's a proc macro crate.
     raw_proc_macros: Option<&'static [ProcMacro]>,
     /// Source maps for code from the crate.
-    source_map_import_info: OnceCell<Vec<ImportedSourceFile>>,
+    source_map_import_info: Lock<Vec<Option<ImportedSourceFile>>>,
     /// For every definition in this crate, maps its `DefPathHash` to its `DefIndex`.
     def_path_hash_map: DefPathHashMapRef<'static>,
     /// Likewise for ExpnHash.
@@ -143,7 +143,8 @@ pub(crate) struct CrateMetadata {
 }
 
 /// Holds information about a rustc_span::SourceFile imported from another crate.
-/// See `imported_source_files()` for more information.
+/// See `imported_source_file()` for more information.
+#[derive(Clone)]
 struct ImportedSourceFile {
     /// This SourceFile's byte-offset within the source_map of its original crate
     original_start_pos: rustc_span::BytePos,
@@ -160,9 +161,6 @@ pub(super) struct DecodeContext<'a, 'tcx> {
     sess: Option<&'tcx Session>,
     tcx: Option<TyCtxt<'tcx>>,
 
-    // Cache the last used source_file for translating spans as an optimization.
-    last_source_file_index: usize,
-
     lazy_state: LazyState,
 
     // Used for decoding interpret::AllocIds in a cached & thread-safe manner.
@@ -191,7 +189,6 @@ pub(super) trait Metadata<'a, 'tcx>: Copy {
             blob: self.blob(),
             sess: self.sess().or(tcx.map(|tcx| tcx.sess)),
             tcx,
-            last_source_file_index: 0,
             lazy_state: LazyState::NoNode,
             alloc_decoding_session: self
                 .cdata()
@@ -527,6 +524,9 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
             bug!("Cannot decode Span without Session.")
         };
 
+        // Index of the file in the corresponding crate's list of encoded files.
+        let metadata_index = u32::decode(decoder);
+
         // There are two possibilities here:
         // 1. This is a 'local span', which is located inside a `SourceFile`
         // that came from this crate. In this case, we use the source map data
@@ -553,10 +553,10 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
         // to be based on the *foreign* crate (e.g. crate C), not the crate
         // we are writing metadata for (e.g. crate B). This allows us to
         // treat the 'local' and 'foreign' cases almost identically during deserialization:
-        // we can call `imported_source_files` for the proper crate, and binary search
+        // we can call `imported_source_file` for the proper crate, and binary search
         // through the returned slice using our span.
-        let imported_source_files = if tag == TAG_VALID_SPAN_LOCAL {
-            decoder.cdata().imported_source_files(sess)
+        let source_file = if tag == TAG_VALID_SPAN_LOCAL {
+            decoder.cdata().imported_source_file(metadata_index, sess)
         } else {
             // When we encode a proc-macro crate, all `Span`s should be encoded
             // with `TAG_VALID_SPAN_LOCAL`
@@ -577,66 +577,65 @@ impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Span {
                 cnum
             );
 
-            // Decoding 'foreign' spans should be rare enough that it's
-            // not worth it to maintain a per-CrateNum cache for `last_source_file_index`.
-            // We just set it to 0, to ensure that we don't try to access something out
-            // of bounds for our initial 'guess'
-            decoder.last_source_file_index = 0;
-
             let foreign_data = decoder.cdata().cstore.get_crate_data(cnum);
-            foreign_data.imported_source_files(sess)
+            foreign_data.imported_source_file(metadata_index, sess)
         };
 
-        let source_file = {
-            // Optimize for the case that most spans within a translated item
-            // originate from the same source_file.
-            let last_source_file = &imported_source_files[decoder.last_source_file_index];
-
-            if lo >= last_source_file.original_start_pos && lo <= last_source_file.original_end_pos
-            {
-                last_source_file
-            } else {
-                let index = imported_source_files
-                    .binary_search_by_key(&lo, |source_file| source_file.original_start_pos)
-                    .unwrap_or_else(|index| index - 1);
-
-                // Don't try to cache the index for foreign spans,
-                // as this would require a map from CrateNums to indices
-                if tag == TAG_VALID_SPAN_LOCAL {
-                    decoder.last_source_file_index = index;
-                }
-                &imported_source_files[index]
-            }
-        };
-
-        // Make sure our binary search above is correct.
+        // Make sure our span is well-formed.
         debug_assert!(
-            lo >= source_file.original_start_pos && lo <= source_file.original_end_pos,
-            "Bad binary search: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            lo + source_file.original_start_pos <= source_file.original_end_pos,
+            "Malformed encoded span: lo={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
             lo,
             source_file.original_start_pos,
             source_file.original_end_pos
         );
 
-        // Make sure we correctly filtered out invalid spans during encoding
+        // Make sure we correctly filtered out invalid spans during encoding.
         debug_assert!(
-            hi >= source_file.original_start_pos && hi <= source_file.original_end_pos,
-            "Bad binary search: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
+            hi + source_file.original_start_pos <= source_file.original_end_pos,
+            "Malformed encoded span: hi={:?} source_file.original_start_pos={:?} source_file.original_end_pos={:?}",
             hi,
             source_file.original_start_pos,
             source_file.original_end_pos
         );
 
-        let lo =
-            (lo + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
-        let hi =
-            (hi + source_file.translated_source_file.start_pos) - source_file.original_start_pos;
+        let lo = lo + source_file.translated_source_file.start_pos;
+        let hi = hi + source_file.translated_source_file.start_pos;
 
         // Do not try to decode parent for foreign spans.
         Span::new(lo, hi, ctxt, None)
     }
 }
 
+impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for Symbol {
+    fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
+        let tag = d.read_u8();
+
+        match tag {
+            SYMBOL_STR => {
+                let s = d.read_str();
+                Symbol::intern(s)
+            }
+            SYMBOL_OFFSET => {
+                // read str offset
+                let pos = d.read_usize();
+                let old_pos = d.opaque.position();
+
+                // move to str ofset and read
+                d.opaque.set_position(pos);
+                let s = d.read_str();
+                let sym = Symbol::intern(s);
+
+                // restore position
+                d.opaque.set_position(old_pos);
+
+                sym
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
 impl<'a, 'tcx> Decodable<DecodeContext<'a, 'tcx>> for &'tcx [ty::abstract_const::Node<'tcx>] {
     fn decode(d: &mut DecodeContext<'a, 'tcx>) -> Self {
         ty::codec::RefDecodable::decode(d)
@@ -1453,7 +1452,7 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
     ///
     /// Proc macro crates don't currently export spans, so this function does not have
     /// to work for them.
-    fn imported_source_files(self, sess: &Session) -> &'a [ImportedSourceFile] {
+    fn imported_source_file(self, source_file_index: u32, sess: &Session) -> ImportedSourceFile {
         fn filter<'a>(sess: &Session, path: Option<&'a Path>) -> Option<&'a Path> {
             path.filter(|_| {
                 // Only spend time on further checks if we have what to translate *to*.
@@ -1541,90 +1540,96 @@ impl<'a, 'tcx> CrateMetadataRef<'a> {
             }
         };
 
-        self.cdata.source_map_import_info.get_or_init(|| {
-            let external_source_map = self.root.source_map.decode(self);
-
-            external_source_map
-                .map(|source_file_to_import| {
-                    // We can't reuse an existing SourceFile, so allocate a new one
-                    // containing the information we need.
-                    let rustc_span::SourceFile {
-                        mut name,
-                        src_hash,
-                        start_pos,
-                        end_pos,
-                        lines,
-                        multibyte_chars,
-                        non_narrow_chars,
-                        normalized_pos,
-                        name_hash,
-                        ..
-                    } = source_file_to_import;
-
-                    // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
-                    // during rust bootstrapping by `remap-debuginfo = true`, and the user
-                    // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
-                    // then we change `name` to a similar state as if the rust was bootstrapped
-                    // with `remap-debuginfo = true`.
-                    // This is useful for testing so that tests about the effects of
-                    // `try_to_translate_virtual_to_real` don't have to worry about how the
-                    // compiler is bootstrapped.
-                    if let Some(virtual_dir) =
-                        &sess.opts.unstable_opts.simulate_remapped_rust_src_base
-                    {
-                        if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
-                            if let rustc_span::FileName::Real(ref mut old_name) = name {
-                                if let rustc_span::RealFileName::LocalPath(local) = old_name {
-                                    if let Ok(rest) = local.strip_prefix(real_dir) {
-                                        *old_name = rustc_span::RealFileName::Remapped {
-                                            local_path: None,
-                                            virtual_name: virtual_dir.join(rest),
-                                        };
-                                    }
+        let mut import_info = self.cdata.source_map_import_info.lock();
+        for _ in import_info.len()..=(source_file_index as usize) {
+            import_info.push(None);
+        }
+        import_info[source_file_index as usize]
+            .get_or_insert_with(|| {
+                let source_file_to_import = self
+                    .root
+                    .source_map
+                    .get(self, source_file_index)
+                    .expect("missing source file")
+                    .decode(self);
+
+                // We can't reuse an existing SourceFile, so allocate a new one
+                // containing the information we need.
+                let rustc_span::SourceFile {
+                    mut name,
+                    src_hash,
+                    start_pos,
+                    end_pos,
+                    lines,
+                    multibyte_chars,
+                    non_narrow_chars,
+                    normalized_pos,
+                    name_hash,
+                    ..
+                } = source_file_to_import;
+
+                // If this file is under $sysroot/lib/rustlib/src/ but has not been remapped
+                // during rust bootstrapping by `remap-debuginfo = true`, and the user
+                // wish to simulate that behaviour by -Z simulate-remapped-rust-src-base,
+                // then we change `name` to a similar state as if the rust was bootstrapped
+                // with `remap-debuginfo = true`.
+                // This is useful for testing so that tests about the effects of
+                // `try_to_translate_virtual_to_real` don't have to worry about how the
+                // compiler is bootstrapped.
+                if let Some(virtual_dir) = &sess.opts.unstable_opts.simulate_remapped_rust_src_base
+                {
+                    if let Some(real_dir) = &sess.opts.real_rust_source_base_dir {
+                        if let rustc_span::FileName::Real(ref mut old_name) = name {
+                            if let rustc_span::RealFileName::LocalPath(local) = old_name {
+                                if let Ok(rest) = local.strip_prefix(real_dir) {
+                                    *old_name = rustc_span::RealFileName::Remapped {
+                                        local_path: None,
+                                        virtual_name: virtual_dir.join(rest),
+                                    };
                                 }
                             }
                         }
                     }
+                }
 
-                    // If this file's path has been remapped to `/rustc/$hash`,
-                    // we might be able to reverse that (also see comments above,
-                    // on `try_to_translate_virtual_to_real`).
-                    try_to_translate_virtual_to_real(&mut name);
-
-                    let source_length = (end_pos - start_pos).to_usize();
-
-                    let local_version = sess.source_map().new_imported_source_file(
-                        name,
-                        src_hash,
-                        name_hash,
-                        source_length,
-                        self.cnum,
-                        lines,
-                        multibyte_chars,
-                        non_narrow_chars,
-                        normalized_pos,
-                        start_pos,
-                        end_pos,
-                    );
-                    debug!(
-                        "CrateMetaData::imported_source_files alloc \
+                // If this file's path has been remapped to `/rustc/$hash`,
+                // we might be able to reverse that (also see comments above,
+                // on `try_to_translate_virtual_to_real`).
+                try_to_translate_virtual_to_real(&mut name);
+
+                let source_length = (end_pos - start_pos).to_usize();
+
+                let local_version = sess.source_map().new_imported_source_file(
+                    name,
+                    src_hash,
+                    name_hash,
+                    source_length,
+                    self.cnum,
+                    lines,
+                    multibyte_chars,
+                    non_narrow_chars,
+                    normalized_pos,
+                    start_pos,
+                    source_file_index,
+                );
+                debug!(
+                    "CrateMetaData::imported_source_files alloc \
                          source_file {:?} original (start_pos {:?} end_pos {:?}) \
                          translated (start_pos {:?} end_pos {:?})",
-                        local_version.name,
-                        start_pos,
-                        end_pos,
-                        local_version.start_pos,
-                        local_version.end_pos
-                    );
+                    local_version.name,
+                    start_pos,
+                    end_pos,
+                    local_version.start_pos,
+                    local_version.end_pos
+                );
 
-                    ImportedSourceFile {
-                        original_start_pos: start_pos,
-                        original_end_pos: end_pos,
-                        translated_source_file: local_version,
-                    }
-                })
-                .collect()
-        })
+                ImportedSourceFile {
+                    original_start_pos: start_pos,
+                    original_end_pos: end_pos,
+                    translated_source_file: local_version,
+                }
+            })
+            .clone()
     }
 
     fn get_generator_diagnostic_data(
@@ -1687,7 +1692,7 @@ impl CrateMetadata {
             trait_impls,
             incoherent_impls: Default::default(),
             raw_proc_macros,
-            source_map_import_info: OnceCell::new(),
+            source_map_import_info: Lock::new(Vec::new()),
             def_path_hash_map,
             expn_hash_map: Default::default(),
             alloc_decoding_state,
diff --git a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
index 61f16be1d6b..ad2b6846a4b 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder/cstore_impl.rs
@@ -676,6 +676,9 @@ impl CrateStore for CStore {
     }
 
     fn import_source_files(&self, sess: &Session, cnum: CrateNum) {
-        self.get_crate_data(cnum).imported_source_files(sess);
+        let cdata = self.get_crate_data(cnum);
+        for file_index in 0..cdata.root.source_map.size() {
+            cdata.imported_source_file(file_index as u32, sess);
+        }
     }
 }
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index f68005c0526..0d3a3efb0d3 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -17,7 +17,6 @@ use rustc_hir::definitions::DefPathData;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::lang_items;
 use rustc_hir::{AnonConst, GenericParamKind};
-use rustc_index::bit_set::GrowableBitSet;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::middle::dependency_format::Linkage;
 use rustc_middle::middle::exported_symbols::{
@@ -39,6 +38,7 @@ use rustc_span::{
 };
 use rustc_target::abi::VariantIdx;
 use std::borrow::Borrow;
+use std::collections::hash_map::Entry;
 use std::hash::Hash;
 use std::io::{Read, Seek, Write};
 use std::iter;
@@ -66,15 +66,13 @@ pub(super) struct EncodeContext<'a, 'tcx> {
     // The indices (into the `SourceMap`'s `MonotonicVec`)
     // of all of the `SourceFiles` that we need to serialize.
     // When we serialize a `Span`, we insert the index of its
-    // `SourceFile` into the `GrowableBitSet`.
-    //
-    // This needs to be a `GrowableBitSet` and not a
-    // regular `BitSet` because we may actually import new `SourceFiles`
-    // during metadata encoding, due to executing a query
-    // with a result containing a foreign `Span`.
-    required_source_files: Option<GrowableBitSet<usize>>,
+    // `SourceFile` into the `FxIndexSet`.
+    // The order inside the `FxIndexSet` is used as on-disk
+    // order of `SourceFiles`, and encoded inside `Span`s.
+    required_source_files: Option<FxIndexSet<usize>>,
     is_proc_macro: bool,
     hygiene_ctxt: &'a HygieneEncodeContext,
+    symbol_table: FxHashMap<Symbol, usize>,
 }
 
 /// If the current crate is a proc-macro, returns early with `Lazy:empty()`.
@@ -238,17 +236,15 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
             s.source_file_cache =
                 (source_map.files()[source_file_index].clone(), source_file_index);
         }
+        let (ref source_file, source_file_index) = s.source_file_cache;
+        debug_assert!(source_file.contains(span.lo));
 
-        if !s.source_file_cache.0.contains(span.hi) {
+        if !source_file.contains(span.hi) {
             // Unfortunately, macro expansion still sometimes generates Spans
             // that malformed in this way.
             return TAG_PARTIAL_SPAN.encode(s);
         }
 
-        let source_files = s.required_source_files.as_mut().expect("Already encoded SourceMap!");
-        // Record the fact that we need to encode the data for this `SourceFile`
-        source_files.insert(s.source_file_cache.1);
-
         // There are two possible cases here:
         // 1. This span comes from a 'foreign' crate - e.g. some crate upstream of the
         // crate we are writing metadata for. When the metadata for *this* crate gets
@@ -265,7 +261,7 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
         // if we're a proc-macro crate.
         // This allows us to avoid loading the dependencies of proc-macro crates: all of
         // the information we need to decode `Span`s is stored in the proc-macro crate.
-        let (tag, lo, hi) = if s.source_file_cache.0.is_imported() && !s.is_proc_macro {
+        let (tag, metadata_index) = if source_file.is_imported() && !s.is_proc_macro {
             // To simplify deserialization, we 'rebase' this span onto the crate it originally came from
             // (the crate that 'owns' the file it references. These rebased 'lo' and 'hi' values
             // are relative to the source map information for the 'foreign' crate whose CrateNum
@@ -275,29 +271,41 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
             //
             // All of this logic ensures that the final result of deserialization is a 'normal'
             // Span that can be used without any additional trouble.
-            let external_start_pos = {
+            let metadata_index = {
                 // Introduce a new scope so that we drop the 'lock()' temporary
-                match &*s.source_file_cache.0.external_src.lock() {
-                    ExternalSource::Foreign { original_start_pos, .. } => *original_start_pos,
+                match &*source_file.external_src.lock() {
+                    ExternalSource::Foreign { metadata_index, .. } => *metadata_index,
                     src => panic!("Unexpected external source {:?}", src),
                 }
             };
-            let lo = (span.lo - s.source_file_cache.0.start_pos) + external_start_pos;
-            let hi = (span.hi - s.source_file_cache.0.start_pos) + external_start_pos;
 
-            (TAG_VALID_SPAN_FOREIGN, lo, hi)
+            (TAG_VALID_SPAN_FOREIGN, metadata_index)
         } else {
-            (TAG_VALID_SPAN_LOCAL, span.lo, span.hi)
+            // Record the fact that we need to encode the data for this `SourceFile`
+            let source_files =
+                s.required_source_files.as_mut().expect("Already encoded SourceMap!");
+            let (metadata_index, _) = source_files.insert_full(source_file_index);
+            let metadata_index: u32 =
+                metadata_index.try_into().expect("cannot export more than U32_MAX files");
+
+            (TAG_VALID_SPAN_LOCAL, metadata_index)
         };
 
-        tag.encode(s);
-        lo.encode(s);
+        // Encode the start position relative to the file start, so we profit more from the
+        // variable-length integer encoding.
+        let lo = span.lo - source_file.start_pos;
 
         // Encode length which is usually less than span.hi and profits more
         // from the variable-length integer encoding that we use.
-        let len = hi - lo;
+        let len = span.hi - span.lo;
+
+        tag.encode(s);
+        lo.encode(s);
         len.encode(s);
 
+        // Encode the index of the `SourceFile` for the span, in order to make decoding faster.
+        metadata_index.encode(s);
+
         if tag == TAG_VALID_SPAN_FOREIGN {
             // This needs to be two lines to avoid holding the `s.source_file_cache`
             // while calling `cnum.encode(s)`
@@ -307,6 +315,24 @@ impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Span {
     }
 }
 
+impl<'a, 'tcx> Encodable<EncodeContext<'a, 'tcx>> for Symbol {
+    fn encode(&self, s: &mut EncodeContext<'a, 'tcx>) {
+        match s.symbol_table.entry(*self) {
+            Entry::Vacant(o) => {
+                s.opaque.emit_u8(SYMBOL_STR);
+                let pos = s.opaque.position();
+                o.insert(pos);
+                s.emit_str(self.as_str());
+            }
+            Entry::Occupied(o) => {
+                let x = o.get().clone();
+                s.emit_u8(SYMBOL_OFFSET);
+                s.emit_usize(x);
+            }
+        }
+    }
+}
+
 impl<'a, 'tcx> TyEncoder for EncodeContext<'a, 'tcx> {
     const CLEAR_CROSS_CRATE: bool = true;
 
@@ -449,7 +475,7 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
         self.lazy(DefPathHashMapRef::BorrowedFromTcx(self.tcx.def_path_hash_to_def_index_map()))
     }
 
-    fn encode_source_map(&mut self) -> LazyArray<rustc_span::SourceFile> {
+    fn encode_source_map(&mut self) -> LazyTable<u32, LazyValue<rustc_span::SourceFile>> {
         let source_map = self.tcx.sess.source_map();
         let all_source_files = source_map.files();
 
@@ -460,66 +486,64 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
 
         let working_directory = &self.tcx.sess.opts.working_dir;
 
-        let adapted = all_source_files
-            .iter()
-            .enumerate()
-            .filter(|(idx, source_file)| {
-                // Only serialize `SourceFile`s that were used
-                // during the encoding of a `Span`
-                required_source_files.contains(*idx) &&
-                // Don't serialize imported `SourceFile`s, unless
-                // we're in a proc-macro crate.
-                (!source_file.is_imported() || self.is_proc_macro)
-            })
-            .map(|(_, source_file)| {
-                // At export time we expand all source file paths to absolute paths because
-                // downstream compilation sessions can have a different compiler working
-                // directory, so relative paths from this or any other upstream crate
-                // won't be valid anymore.
-                //
-                // At this point we also erase the actual on-disk path and only keep
-                // the remapped version -- as is necessary for reproducible builds.
-                match source_file.name {
-                    FileName::Real(ref original_file_name) => {
-                        let adapted_file_name =
-                            source_map.path_mapping().to_embeddable_absolute_path(
-                                original_file_name.clone(),
-                                working_directory,
-                            );
-
-                        if adapted_file_name != *original_file_name {
-                            let mut adapted: SourceFile = (**source_file).clone();
-                            adapted.name = FileName::Real(adapted_file_name);
-                            adapted.name_hash = {
-                                let mut hasher: StableHasher = StableHasher::new();
-                                adapted.name.hash(&mut hasher);
-                                hasher.finish::<u128>()
-                            };
-                            Lrc::new(adapted)
-                        } else {
-                            // Nothing to adapt
-                            source_file.clone()
-                        }
+        let mut adapted = TableBuilder::default();
+
+        // Only serialize `SourceFile`s that were used during the encoding of a `Span`.
+        //
+        // The order in which we encode source files is important here: the on-disk format for
+        // `Span` contains the index of the corresponding `SourceFile`.
+        for (on_disk_index, &source_file_index) in required_source_files.iter().enumerate() {
+            let source_file = &all_source_files[source_file_index];
+            // Don't serialize imported `SourceFile`s, unless we're in a proc-macro crate.
+            assert!(!source_file.is_imported() || self.is_proc_macro);
+
+            // At export time we expand all source file paths to absolute paths because
+            // downstream compilation sessions can have a different compiler working
+            // directory, so relative paths from this or any other upstream crate
+            // won't be valid anymore.
+            //
+            // At this point we also erase the actual on-disk path and only keep
+            // the remapped version -- as is necessary for reproducible builds.
+            let mut source_file = match source_file.name {
+                FileName::Real(ref original_file_name) => {
+                    let adapted_file_name = source_map
+                        .path_mapping()
+                        .to_embeddable_absolute_path(original_file_name.clone(), working_directory);
+
+                    if adapted_file_name != *original_file_name {
+                        let mut adapted: SourceFile = (**source_file).clone();
+                        adapted.name = FileName::Real(adapted_file_name);
+                        adapted.name_hash = {
+                            let mut hasher: StableHasher = StableHasher::new();
+                            adapted.name.hash(&mut hasher);
+                            hasher.finish::<u128>()
+                        };
+                        Lrc::new(adapted)
+                    } else {
+                        // Nothing to adapt
+                        source_file.clone()
                     }
-                    // expanded code, not from a file
-                    _ => source_file.clone(),
-                }
-            })
-            .map(|mut source_file| {
-                // We're serializing this `SourceFile` into our crate metadata,
-                // so mark it as coming from this crate.
-                // This also ensures that we don't try to deserialize the
-                // `CrateNum` for a proc-macro dependency - since proc macro
-                // dependencies aren't loaded when we deserialize a proc-macro,
-                // trying to remap the `CrateNum` would fail.
-                if self.is_proc_macro {
-                    Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE;
                 }
-                source_file
-            })
-            .collect::<Vec<_>>();
+                // expanded code, not from a file
+                _ => source_file.clone(),
+            };
+
+            // We're serializing this `SourceFile` into our crate metadata,
+            // so mark it as coming from this crate.
+            // This also ensures that we don't try to deserialize the
+            // `CrateNum` for a proc-macro dependency - since proc macro
+            // dependencies aren't loaded when we deserialize a proc-macro,
+            // trying to remap the `CrateNum` would fail.
+            if self.is_proc_macro {
+                Lrc::make_mut(&mut source_file).cnum = LOCAL_CRATE;
+            }
+
+            let on_disk_index: u32 =
+                on_disk_index.try_into().expect("cannot export more than U32_MAX files");
+            adapted.set(on_disk_index, self.lazy(source_file));
+        }
 
-        self.lazy_array(adapted.iter().map(|rc| &**rc))
+        adapted.encode(&mut self.opaque)
     }
 
     fn encode_crate_root(&mut self) -> LazyValue<CrateRoot> {
@@ -2241,7 +2265,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
 
     let source_map_files = tcx.sess.source_map().files();
     let source_file_cache = (source_map_files[0].clone(), 0);
-    let required_source_files = Some(GrowableBitSet::with_capacity(source_map_files.len()));
+    let required_source_files = Some(FxIndexSet::default());
     drop(source_map_files);
 
     let hygiene_ctxt = HygieneEncodeContext::default();
@@ -2259,6 +2283,7 @@ fn encode_metadata_impl(tcx: TyCtxt<'_>, path: &Path) {
         required_source_files,
         is_proc_macro: tcx.sess.crate_types().contains(&CrateType::ProcMacro),
         hygiene_ctxt: &hygiene_ctxt,
+        symbol_table: Default::default(),
     };
 
     // Encode the rustc version string in a predictable location.
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index 8efe5051b01..91d744879fd 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -249,7 +249,7 @@ pub(crate) struct CrateRoot {
 
     def_path_hash_map: LazyValue<DefPathHashMapRef<'static>>,
 
-    source_map: LazyArray<rustc_span::SourceFile>,
+    source_map: LazyTable<u32, LazyValue<rustc_span::SourceFile>>,
 
     compiler_builtins: bool,
     needs_allocator: bool,
@@ -445,6 +445,10 @@ const TAG_VALID_SPAN_LOCAL: u8 = 0;
 const TAG_VALID_SPAN_FOREIGN: u8 = 1;
 const TAG_PARTIAL_SPAN: u8 = 2;
 
+// Tags for encoding Symbol's
+const SYMBOL_STR: u8 = 0;
+const SYMBOL_OFFSET: u8 = 1;
+
 pub fn provide(providers: &mut Providers) {
     encoder::provide(providers);
     decoder::provide(providers);
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 79e6804a289..85642bf82cc 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -146,10 +146,12 @@ impl<'hir> Iterator for ParentOwnerIterator<'hir> {
 }
 
 impl<'hir> Map<'hir> {
+    #[inline]
     pub fn krate(self) -> &'hir Crate<'hir> {
         self.tcx.hir_crate(())
     }
 
+    #[inline]
     pub fn root_module(self) -> &'hir Mod<'hir> {
         match self.tcx.hir_owner(CRATE_DEF_ID).map(|o| o.node) {
             Some(OwnerNode::Crate(item)) => item,
@@ -157,14 +159,17 @@ impl<'hir> Map<'hir> {
         }
     }
 
+    #[inline]
     pub fn items(self) -> impl Iterator<Item = ItemId> + 'hir {
         self.tcx.hir_crate_items(()).items.iter().copied()
     }
 
+    #[inline]
     pub fn module_items(self, module: LocalDefId) -> impl Iterator<Item = ItemId> + 'hir {
         self.tcx.hir_module_items(module).items()
     }
 
+    #[inline]
     pub fn par_for_each_item(self, f: impl Fn(ItemId) + Sync + Send) {
         par_for_each_in(&self.tcx.hir_crate_items(()).items[..], |id| f(*id));
     }
@@ -489,11 +494,13 @@ impl<'hir> Map<'hir> {
     /// Returns an iterator of the `DefId`s for all body-owners in this
     /// crate. If you would prefer to iterate over the bodies
     /// themselves, you can do `self.hir().krate().body_ids.iter()`.
+    #[inline]
     pub fn body_owners(self) -> impl Iterator<Item = LocalDefId> + 'hir {
         self.tcx.hir_crate_items(()).body_owners.iter().copied()
     }
 
-    pub fn par_body_owners<F: Fn(LocalDefId) + Sync + Send>(self, f: F) {
+    #[inline]
+    pub fn par_body_owners(self, f: impl Fn(LocalDefId) + Sync + Send) {
         par_for_each_in(&self.tcx.hir_crate_items(()).body_owners[..], |&def_id| f(def_id));
     }
 
@@ -626,35 +633,22 @@ impl<'hir> Map<'hir> {
         }
     }
 
-    #[cfg(not(parallel_compiler))]
     #[inline]
-    pub fn par_for_each_module(self, f: impl Fn(LocalDefId)) {
-        self.for_each_module(f)
-    }
-
-    #[cfg(parallel_compiler)]
-    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync) {
-        use rustc_data_structures::sync::{par_iter, ParallelIterator};
-        par_iter_submodules(self.tcx, CRATE_DEF_ID, &f);
-
-        fn par_iter_submodules<F>(tcx: TyCtxt<'_>, module: LocalDefId, f: &F)
-        where
-            F: Fn(LocalDefId) + Sync,
-        {
-            (*f)(module);
-            let items = tcx.hir_module_items(module);
-            par_iter(&items.submodules[..]).for_each(|&sm| par_iter_submodules(tcx, sm, f));
-        }
+    pub fn par_for_each_module(self, f: impl Fn(LocalDefId) + Sync + Send) {
+        let crate_items = self.tcx.hir_crate_items(());
+        par_for_each_in(&crate_items.submodules[..], |module| f(*module))
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
     /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    #[inline]
     pub fn parent_iter(self, current_id: HirId) -> ParentHirIterator<'hir> {
         ParentHirIterator { current_id, map: self }
     }
 
     /// Returns an iterator for the nodes in the ancestor tree of the `current_id`
     /// until the crate root is reached. Prefer this over your own loop using `get_parent_node`.
+    #[inline]
     pub fn parent_owner_iter(self, current_id: HirId) -> ParentOwnerIterator<'hir> {
         ParentOwnerIterator { current_id, map: self }
     }
diff --git a/compiler/rustc_middle/src/mir/interpret/value.rs b/compiler/rustc_middle/src/mir/interpret/value.rs
index 834c114ee1c..a1c111ae372 100644
--- a/compiler/rustc_middle/src/mir/interpret/value.rs
+++ b/compiler/rustc_middle/src/mir/interpret/value.rs
@@ -79,7 +79,7 @@ impl<'tcx> ConstValue<'tcx> {
     }
 
     pub fn try_to_scalar_int(&self) -> Option<ScalarInt> {
-        Some(self.try_to_scalar()?.assert_int())
+        self.try_to_scalar()?.try_to_int().ok()
     }
 
     pub fn try_to_bits(&self, size: Size) -> Option<u128> {
@@ -368,6 +368,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
     }
 
     #[inline(always)]
+    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
     pub fn assert_int(self) -> ScalarInt {
         self.try_to_int().unwrap()
     }
@@ -389,6 +390,7 @@ impl<'tcx, Prov: Provenance> Scalar<Prov> {
     }
 
     #[inline(always)]
+    #[cfg_attr(debug_assertions, track_caller)] // only in debug builds due to perf (see #98980)
     pub fn assert_bits(self, target_size: Size) -> u128 {
         self.to_bits(target_size).unwrap()
     }
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index dd9f8795f94..594c14a642d 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -2,7 +2,7 @@
 
 use crate::mir::{Body, ConstantKind, Promoted};
 use crate::ty::{self, OpaqueHiddenType, Ty, TyCtxt};
-use rustc_data_structures::fx::FxHashMap;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::vec_map::VecMap;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
@@ -115,21 +115,6 @@ pub enum UnusedUnsafe {
     /// `unsafe` block nested under another (used) `unsafe` block
     /// > ``… because it's nested under this `unsafe` block``
     InUnsafeBlock(hir::HirId),
-    /// `unsafe` block nested under `unsafe fn`
-    /// > ``… because it's nested under this `unsafe fn` ``
-    ///
-    /// the second HirId here indicates the first usage of the `unsafe` block,
-    /// which allows retrieval of the LintLevelSource for why that operation would
-    /// have been permitted without the block
-    InUnsafeFn(hir::HirId, hir::HirId),
-}
-
-#[derive(Copy, Clone, PartialEq, TyEncodable, TyDecodable, HashStable, Debug)]
-pub enum UsedUnsafeBlockData {
-    SomeDisallowedInUnsafeFn,
-    // the HirId here indicates the first usage of the `unsafe` block
-    // (i.e. the one that's first encountered in the MIR traversal of the unsafety check)
-    AllAllowedInUnsafeFn(hir::HirId),
 }
 
 #[derive(TyEncodable, TyDecodable, HashStable, Debug)]
@@ -138,10 +123,7 @@ pub struct UnsafetyCheckResult {
     pub violations: Vec<UnsafetyViolation>,
 
     /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
-    ///
-    /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether
-    /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`.
-    pub used_unsafe_blocks: FxHashMap<hir::HirId, UsedUnsafeBlockData>,
+    pub used_unsafe_blocks: FxHashSet<hir::HirId>,
 
     /// This is `Some` iff the item is not a closure.
     pub unused_unsafes: Option<Vec<(hir::HirId, UnusedUnsafe)>>,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 8a727d9a182..f78f62e31d2 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -765,6 +765,14 @@ rustc_queries! {
         desc { |tcx| "processing `{}`", tcx.def_path_str(key.to_def_id()) }
     }
 
+    /// Returns the types assumed to be well formed while "inside" of the given item.
+    ///
+    /// Note that we've liberated the late bound regions of function signatures, so
+    /// this can not be used to check whether these types are well formed.
+    query assumed_wf_types(key: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+        desc { |tcx| "computing the implied bounds of {}", tcx.def_path_str(key) }
+    }
+
     /// Computes the signature of the function.
     query fn_sig(key: DefId) -> ty::PolyFnSig<'tcx> {
         desc { |tcx| "computing function signature of `{}`", tcx.def_path_str(key) }
diff --git a/compiler/rustc_middle/src/traits/mod.rs b/compiler/rustc_middle/src/traits/mod.rs
index 72b848c3ee2..9b82320e556 100644
--- a/compiler/rustc_middle/src/traits/mod.rs
+++ b/compiler/rustc_middle/src/traits/mod.rs
@@ -234,13 +234,23 @@ pub enum ObligationCauseCode<'tcx> {
     /// This is the trait reference from the given projection.
     ProjectionWf(ty::ProjectionTy<'tcx>),
 
-    /// In an impl of trait `X` for type `Y`, type `Y` must
-    /// also implement all supertraits of `X`.
+    /// Must satisfy all of the where-clause predicates of the
+    /// given item.
     ItemObligation(DefId),
 
-    /// Like `ItemObligation`, but with extra detail on the source of the obligation.
+    /// Like `ItemObligation`, but carries the span of the
+    /// predicate when it can be identified.
     BindingObligation(DefId, Span),
 
+    /// Like `ItemObligation`, but carries the `HirId` of the
+    /// expression that caused the obligation, and the `usize`
+    /// indicates exactly which predicate it is in the list of
+    /// instantiated predicates.
+    ExprItemObligation(DefId, rustc_hir::HirId, usize),
+
+    /// Combines `ExprItemObligation` and `BindingObligation`.
+    ExprBindingObligation(DefId, Span, rustc_hir::HirId, usize),
+
     /// A type like `&'a T` is WF only if `T: 'a`.
     ReferenceOutlivesReferent(Ty<'tcx>),
 
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index add2df25884..823e7f22af2 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -122,6 +122,21 @@ pub struct Generics {
 }
 
 impl<'tcx> Generics {
+    /// Looks through the generics and all parents to find the index of the
+    /// given param def-id. This is in comparison to the `param_def_id_to_index`
+    /// struct member, which only stores information about this item's own
+    /// generics.
+    pub fn param_def_id_to_index(&self, tcx: TyCtxt<'tcx>, def_id: DefId) -> Option<u32> {
+        if let Some(idx) = self.param_def_id_to_index.get(&def_id) {
+            Some(*idx)
+        } else if let Some(parent) = self.parent {
+            let parent = tcx.generics_of(parent);
+            parent.param_def_id_to_index(tcx, def_id)
+        } else {
+            None
+        }
+    }
+
     #[inline]
     pub fn count(&self) -> usize {
         self.parent_count + self.params.len()
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index db3b5cfd180..79365ef281b 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -65,6 +65,10 @@ impl<T> List<T> {
     pub fn len(&self) -> usize {
         self.len
     }
+
+    pub fn as_slice(&self) -> &[T] {
+        self
+    }
 }
 
 impl<T: Copy> List<T> {
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 52c3a38861e..0070575f213 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -1617,6 +1617,10 @@ impl<'tcx> Region<'tcx> {
             _ => self.is_free(),
         }
     }
+
+    pub fn is_var(self) -> bool {
+        matches!(self.kind(), ty::ReVar(_))
+    }
 }
 
 /// Type utilities
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index 12b8ceede0f..461c837f6df 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -250,7 +250,18 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
             // of `mir_build`, so now we can steal it
             let thir = thir.steal();
 
-            build::construct_const(&thir, &infcx, expr, def, id, return_ty, return_ty_span)
+            let span_with_body = span_with_body.to(tcx.hir().span(body_id.hir_id));
+
+            build::construct_const(
+                &thir,
+                &infcx,
+                expr,
+                def,
+                id,
+                return_ty,
+                return_ty_span,
+                span_with_body,
+            )
         };
 
         lints::check(tcx, &body);
@@ -705,9 +716,8 @@ fn construct_const<'a, 'tcx>(
     hir_id: hir::HirId,
     const_ty: Ty<'tcx>,
     const_ty_span: Span,
+    span: Span,
 ) -> Body<'tcx> {
-    let tcx = infcx.tcx;
-    let span = tcx.hir().span(hir_id);
     let mut builder = Builder::new(
         thir,
         infcx,
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 864caf0ba31..f0b0456c4b9 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -75,10 +75,11 @@ impl<'tcx> UnsafetyVisitor<'_, 'tcx> {
         match self.safety_context {
             SafetyContext::BuiltinUnsafeBlock => {}
             SafetyContext::UnsafeBlock { ref mut used, .. } => {
-                if !self.body_unsafety.is_unsafe() || !unsafe_op_in_unsafe_fn_allowed {
-                    // Mark this block as useful
-                    *used = true;
-                }
+                // Mark this block as useful (even inside `unsafe fn`, where it is technically
+                // redundant -- but we want to eventually enable `unsafe_op_in_unsafe_fn` by
+                // default which will require those blocks:
+                // https://github.com/rust-lang/rust/issues/71668#issuecomment-1203075594).
+                *used = true;
             }
             SafetyContext::UnsafeFn if unsafe_op_in_unsafe_fn_allowed => {}
             SafetyContext::UnsafeFn => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index 0a660ef30c8..443626d14b9 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -364,8 +364,8 @@ impl<'a, 'p, 'tcx> fmt::Debug for PatCtxt<'a, 'p, 'tcx> {
 /// A row of a matrix. Rows of len 1 are very common, which is why `SmallVec[_; 2]`
 /// works well.
 #[derive(Clone)]
-struct PatStack<'p, 'tcx> {
-    pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
+pub(crate) struct PatStack<'p, 'tcx> {
+    pub(crate) pats: SmallVec<[&'p DeconstructedPat<'p, 'tcx>; 2]>,
 }
 
 impl<'p, 'tcx> PatStack<'p, 'tcx> {
@@ -403,6 +403,21 @@ impl<'p, 'tcx> PatStack<'p, 'tcx> {
         })
     }
 
+    // Recursively expand all patterns into their subpatterns and push each `PatStack` to matrix.
+    fn expand_and_extend<'a>(&'a self, matrix: &mut Matrix<'p, 'tcx>) {
+        if !self.is_empty() && self.head().is_or_pat() {
+            for pat in self.head().iter_fields() {
+                let mut new_patstack = PatStack::from_pattern(pat);
+                new_patstack.pats.extend_from_slice(&self.pats[1..]);
+                if !new_patstack.is_empty() && new_patstack.head().is_or_pat() {
+                    new_patstack.expand_and_extend(matrix);
+                } else if !new_patstack.is_empty() {
+                    matrix.push(new_patstack);
+                }
+            }
+        }
+    }
+
     /// This computes `S(self.head().ctor(), self)`. See top of the file for explanations.
     ///
     /// Structure patterns with a partial wild pattern (Foo { a: 42, .. }) have their missing
@@ -436,7 +451,7 @@ impl<'p, 'tcx> fmt::Debug for PatStack<'p, 'tcx> {
 /// A 2D matrix.
 #[derive(Clone)]
 pub(super) struct Matrix<'p, 'tcx> {
-    patterns: Vec<PatStack<'p, 'tcx>>,
+    pub patterns: Vec<PatStack<'p, 'tcx>>,
 }
 
 impl<'p, 'tcx> Matrix<'p, 'tcx> {
@@ -453,7 +468,7 @@ impl<'p, 'tcx> Matrix<'p, 'tcx> {
     /// expands it.
     fn push(&mut self, row: PatStack<'p, 'tcx>) {
         if !row.is_empty() && row.head().is_or_pat() {
-            self.patterns.extend(row.expand_or_pat());
+            row.expand_and_extend(self);
         } else {
             self.patterns.push(row);
         }
diff --git a/compiler/rustc_mir_dataflow/src/framework/mod.rs b/compiler/rustc_mir_dataflow/src/framework/mod.rs
index f9fd6c9c56b..d9aff94fef2 100644
--- a/compiler/rustc_mir_dataflow/src/framework/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/mod.rs
@@ -256,6 +256,7 @@ pub trait Analysis<'tcx>: AnalysisDomain<'tcx> {
     ///     .iterate_to_fixpoint()
     ///     .into_results_cursor(body);
     /// ```
+    #[inline]
     fn into_engine<'mir>(
         self,
         tcx: TyCtxt<'tcx>,
@@ -413,7 +414,7 @@ where
     }
 
     /* Extension methods */
-
+    #[inline]
     fn into_engine<'mir>(
         self,
         tcx: TyCtxt<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index d564f480166..0f5fd77f7ab 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -1,17 +1,16 @@
-use rustc_data_structures::fx::FxHashMap;
+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_middle::mir::visit::{MutatingUseContext, PlaceContext, Visitor};
+use rustc_middle::mir::*;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::{self, TyCtxt};
-use rustc_middle::{lint, mir::*};
 use rustc_session::lint::builtin::{UNSAFE_OP_IN_UNSAFE_FN, UNUSED_UNSAFE};
 use rustc_session::lint::Level;
 
-use std::collections::hash_map;
 use std::ops::Bound;
 
 pub struct UnsafetyChecker<'a, 'tcx> {
@@ -23,10 +22,7 @@ pub struct UnsafetyChecker<'a, 'tcx> {
     param_env: ty::ParamEnv<'tcx>,
 
     /// Used `unsafe` blocks in this function. This is used for the "unused_unsafe" lint.
-    ///
-    /// The keys are the used `unsafe` blocks, the UnusedUnsafeKind indicates whether
-    /// or not any of the usages happen at a place that doesn't allow `unsafe_op_in_unsafe_fn`.
-    used_unsafe_blocks: FxHashMap<HirId, UsedUnsafeBlockData>,
+    used_unsafe_blocks: FxHashSet<HirId>,
 }
 
 impl<'a, 'tcx> UnsafetyChecker<'a, 'tcx> {
@@ -130,10 +126,7 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
                 &AggregateKind::Closure(def_id, _) | &AggregateKind::Generator(def_id, _, _) => {
                     let UnsafetyCheckResult { violations, used_unsafe_blocks, .. } =
                         self.tcx.unsafety_check_result(def_id);
-                    self.register_violations(
-                        violations,
-                        used_unsafe_blocks.iter().map(|(&h, &d)| (h, d)),
-                    );
+                    self.register_violations(violations, used_unsafe_blocks.iter().copied());
                 }
             },
             _ => {}
@@ -257,22 +250,8 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
     fn register_violations<'a>(
         &mut self,
         violations: impl IntoIterator<Item = &'a UnsafetyViolation>,
-        new_used_unsafe_blocks: impl IntoIterator<Item = (HirId, UsedUnsafeBlockData)>,
+        new_used_unsafe_blocks: impl IntoIterator<Item = HirId>,
     ) {
-        use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn};
-
-        let update_entry = |this: &mut Self, hir_id, new_usage| {
-            match this.used_unsafe_blocks.entry(hir_id) {
-                hash_map::Entry::Occupied(mut entry) => {
-                    if new_usage == SomeDisallowedInUnsafeFn {
-                        *entry.get_mut() = SomeDisallowedInUnsafeFn;
-                    }
-                }
-                hash_map::Entry::Vacant(entry) => {
-                    entry.insert(new_usage);
-                }
-            };
-        };
         let safety = self.body.source_scopes[self.source_info.scope]
             .local_data
             .as_ref()
@@ -299,22 +278,14 @@ impl<'tcx> UnsafetyChecker<'_, 'tcx> {
                 }
             }),
             Safety::BuiltinUnsafe => {}
-            Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|violation| {
-                update_entry(
-                    self,
-                    hir_id,
-                    match self.tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, violation.lint_root).0
-                    {
-                        Level::Allow => AllAllowedInUnsafeFn(violation.lint_root),
-                        _ => SomeDisallowedInUnsafeFn,
-                    },
-                )
+            Safety::ExplicitUnsafe(hir_id) => violations.into_iter().for_each(|_violation| {
+                self.used_unsafe_blocks.insert(hir_id);
             }),
         };
 
-        new_used_unsafe_blocks
-            .into_iter()
-            .for_each(|(hir_id, usage_data)| update_entry(self, hir_id, usage_data));
+        new_used_unsafe_blocks.into_iter().for_each(|hir_id| {
+            self.used_unsafe_blocks.insert(hir_id);
+        });
     }
     fn check_mut_borrowing_layout_constrained_field(
         &mut self,
@@ -411,34 +382,28 @@ enum Context {
 
 struct UnusedUnsafeVisitor<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    used_unsafe_blocks: &'a FxHashMap<HirId, UsedUnsafeBlockData>,
+    used_unsafe_blocks: &'a FxHashSet<HirId>,
     context: Context,
     unused_unsafes: &'a mut Vec<(HirId, UnusedUnsafe)>,
 }
 
 impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
     fn visit_block(&mut self, block: &'tcx hir::Block<'tcx>) {
-        use UsedUnsafeBlockData::{AllAllowedInUnsafeFn, SomeDisallowedInUnsafeFn};
-
         if let hir::BlockCheckMode::UnsafeBlock(hir::UnsafeSource::UserProvided) = block.rules {
             let used = match self.tcx.lint_level_at_node(UNUSED_UNSAFE, block.hir_id) {
-                (Level::Allow, _) => Some(SomeDisallowedInUnsafeFn),
-                _ => self.used_unsafe_blocks.get(&block.hir_id).copied(),
+                (Level::Allow, _) => true,
+                _ => self.used_unsafe_blocks.contains(&block.hir_id),
             };
             let unused_unsafe = match (self.context, used) {
-                (_, None) => UnusedUnsafe::Unused,
-                (Context::Safe, Some(_))
-                | (Context::UnsafeFn(_), Some(SomeDisallowedInUnsafeFn)) => {
+                (_, false) => UnusedUnsafe::Unused,
+                (Context::Safe, true) | (Context::UnsafeFn(_), true) => {
                     let previous_context = self.context;
                     self.context = Context::UnsafeBlock(block.hir_id);
                     intravisit::walk_block(self, block);
                     self.context = previous_context;
                     return;
                 }
-                (Context::UnsafeFn(hir_id), Some(AllAllowedInUnsafeFn(lint_root))) => {
-                    UnusedUnsafe::InUnsafeFn(hir_id, lint_root)
-                }
-                (Context::UnsafeBlock(hir_id), Some(_)) => UnusedUnsafe::InUnsafeBlock(hir_id),
+                (Context::UnsafeBlock(hir_id), true) => UnusedUnsafe::InUnsafeBlock(hir_id),
             };
             self.unused_unsafes.push((block.hir_id, unused_unsafe));
         }
@@ -462,7 +427,7 @@ impl<'tcx> intravisit::Visitor<'tcx> for UnusedUnsafeVisitor<'_, 'tcx> {
 fn check_unused_unsafe(
     tcx: TyCtxt<'_>,
     def_id: LocalDefId,
-    used_unsafe_blocks: &FxHashMap<HirId, UsedUnsafeBlockData>,
+    used_unsafe_blocks: &FxHashSet<HirId>,
 ) -> Vec<(HirId, UnusedUnsafe)> {
     let body_id = tcx.hir().maybe_body_owned_by(def_id);
 
@@ -535,25 +500,6 @@ fn report_unused_unsafe(tcx: TyCtxt<'_>, kind: UnusedUnsafe, id: HirId) {
                     "because it's nested under this `unsafe` block",
                 );
             }
-            UnusedUnsafe::InUnsafeFn(id, usage_lint_root) => {
-                db.span_label(
-                    tcx.sess.source_map().guess_head_span(tcx.hir().span(id)),
-                    "because it's nested under this `unsafe` fn",
-                )
-                .note(
-                    "this `unsafe` block does contain unsafe operations, \
-                    but those are already allowed in an `unsafe fn`",
-                );
-                let (level, source) =
-                    tcx.lint_level_at_node(UNSAFE_OP_IN_UNSAFE_FN, usage_lint_root);
-                assert_eq!(level, Level::Allow);
-                lint::explain_lint_level_source(
-                    UNSAFE_OP_IN_UNSAFE_FN,
-                    Level::Allow,
-                    source,
-                    &mut db,
-                );
-            }
         }
 
         db.emit();
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 1e46b0a0e81..6704d3462f4 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -10,6 +10,7 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::subst::Subst;
 use rustc_middle::ty::{self, ConstKind, Instance, InstanceDef, ParamEnv, Ty, TyCtxt};
 use rustc_session::config::OptLevel;
+use rustc_span::def_id::DefId;
 use rustc_span::{hygiene::ExpnKind, ExpnData, LocalExpnId, Span};
 use rustc_target::spec::abi::Abi;
 
@@ -103,8 +104,12 @@ struct Inliner<'tcx> {
     param_env: ParamEnv<'tcx>,
     /// Caller codegen attributes.
     codegen_fn_attrs: &'tcx CodegenFnAttrs,
-    /// Stack of inlined Instances.
-    history: Vec<ty::Instance<'tcx>>,
+    /// Stack of inlined instances.
+    /// We only check the `DefId` and not the substs because we want to
+    /// avoid inlining cases of polymorphic recursion.
+    /// The number of `DefId`s is finite, so checking history is enough
+    /// to ensure that we do not loop endlessly while inlining.
+    history: Vec<DefId>,
     /// Indicates that the caller body has been modified.
     changed: bool,
 }
@@ -132,7 +137,7 @@ impl<'tcx> Inliner<'tcx> {
                 Ok(new_blocks) => {
                     debug!("inlined {}", callsite.callee);
                     self.changed = true;
-                    self.history.push(callsite.callee);
+                    self.history.push(callsite.callee.def_id());
                     self.process_blocks(caller_body, new_blocks);
                     self.history.pop();
                 }
@@ -308,7 +313,7 @@ impl<'tcx> Inliner<'tcx> {
                     return None;
                 }
 
-                if self.history.contains(&callee) {
+                if self.history.contains(&callee.def_id()) {
                     return None;
                 }
 
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index f916ca36217..56d7799a125 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -12,9 +12,8 @@ pub struct UnreachablePropagation;
 
 impl MirPass<'_> for UnreachablePropagation {
     fn is_enabled(&self, sess: &rustc_session::Session) -> bool {
-        // Enable only under -Zmir-opt-level=4 as in some cases (check the deeply-nested-opt
-        // perf benchmark) LLVM may spend quite a lot of time optimizing the generated code.
-        sess.mir_opt_level() >= 4
+        // Enable only under -Zmir-opt-level=2 as this can make programs less debuggable.
+        sess.mir_opt_level() >= 2
     }
 
     fn run_pass<'tcx>(&self, tcx: TyCtxt<'tcx>, body: &mut Body<'tcx>) {
@@ -38,7 +37,19 @@ impl MirPass<'_> for UnreachablePropagation {
             }
         }
 
+        // We do want do keep some unreachable blocks, but make them empty.
+        for bb in unreachable_blocks {
+            if !tcx.consider_optimizing(|| {
+                format!("UnreachablePropagation {:?} ", body.source.def_id())
+            }) {
+                break;
+            }
+
+            body.basic_blocks_mut()[bb].statements.clear();
+        }
+
         let replaced = !replacements.is_empty();
+
         for (bb, terminator_kind) in replacements {
             if !tcx.consider_optimizing(|| {
                 format!("UnreachablePropagation {:?} ", body.source.def_id())
@@ -57,42 +68,55 @@ impl MirPass<'_> for UnreachablePropagation {
 
 fn remove_successors<'tcx, F>(
     terminator_kind: &TerminatorKind<'tcx>,
-    predicate: F,
+    is_unreachable: F,
 ) -> Option<TerminatorKind<'tcx>>
 where
     F: Fn(BasicBlock) -> bool,
 {
-    let terminator = match *terminator_kind {
-        TerminatorKind::Goto { target } if predicate(target) => TerminatorKind::Unreachable,
-        TerminatorKind::SwitchInt { ref discr, switch_ty, ref targets } => {
+    let terminator = match terminator_kind {
+        // This will unconditionally run into an unreachable and is therefore unreachable as well.
+        TerminatorKind::Goto { target } if is_unreachable(*target) => TerminatorKind::Unreachable,
+        TerminatorKind::SwitchInt { targets, discr, switch_ty } => {
             let otherwise = targets.otherwise();
 
-            let original_targets_len = targets.iter().len() + 1;
-            let (mut values, mut targets): (Vec<_>, Vec<_>) =
-                targets.iter().filter(|(_, bb)| !predicate(*bb)).unzip();
+            // If all targets are unreachable, we can be unreachable as well.
+            if targets.all_targets().iter().all(|bb| is_unreachable(*bb)) {
+                TerminatorKind::Unreachable
+            } else if is_unreachable(otherwise) {
+                // If there are multiple targets, don't delete unreachable branches (like an unreachable otherwise)
+                // unless otherwise is unrachable, in which case deleting a normal branch causes it to be merged with
+                // the otherwise, keeping its unreachable.
+                // This looses information about reachability causing worse codegen.
+                // For example (see src/test/codegen/match-optimizes-away.rs)
+                //
+                // pub enum Two { A, B }
+                // pub fn identity(x: Two) -> Two {
+                //     match x {
+                //         Two::A => Two::A,
+                //         Two::B => Two::B,
+                //     }
+                // }
+                //
+                // This generates a `switchInt() -> [0: 0, 1: 1, otherwise: unreachable]`, which allows us or LLVM to
+                // turn it into just `x` later. Without the unreachable, such a transformation would be illegal.
+                // If the otherwise branch is unreachable, we can delete all other unreacahble targets, as they will
+                // still point to the unreachable and therefore not lose reachability information.
+                let reachable_iter = targets.iter().filter(|(_, bb)| !is_unreachable(*bb));
 
-            if !predicate(otherwise) {
-                targets.push(otherwise);
-            } else {
-                values.pop();
-            }
+                let new_targets = SwitchTargets::new(reachable_iter, otherwise);
 
-            let retained_targets_len = targets.len();
+                // No unreachable branches were removed.
+                if new_targets.all_targets().len() == targets.all_targets().len() {
+                    return None;
+                }
 
-            if targets.is_empty() {
-                TerminatorKind::Unreachable
-            } else if targets.len() == 1 {
-                TerminatorKind::Goto { target: targets[0] }
-            } else if original_targets_len != retained_targets_len {
                 TerminatorKind::SwitchInt {
                     discr: discr.clone(),
-                    switch_ty,
-                    targets: SwitchTargets::new(
-                        values.iter().copied().zip(targets.iter().copied()),
-                        *targets.last().unwrap(),
-                    ),
+                    switch_ty: *switch_ty,
+                    targets: new_targets,
                 }
             } else {
+                // If the otherwise branch is reachable, we don't want to delete any unreachable branches.
                 return None;
             }
         }
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 96bbf5802e7..82ef16a7f72 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -128,7 +128,7 @@
 //! #### Unsizing Casts
 //! A subtle way of introducing neighbor edges is by casting to a trait object.
 //! Since the resulting fat-pointer contains a reference to a vtable, we need to
-//! instantiate all object-save methods of the trait, as we need to store
+//! instantiate all object-safe methods of the trait, as we need to store
 //! pointers to these functions even if they never get called anywhere. This can
 //! be seen as a special case of taking a function reference.
 //!
@@ -1044,10 +1044,12 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
 /// them.
 ///
 /// For example, the source type might be `&SomeStruct` and the target type
-/// might be `&SomeTrait` in a cast like:
+/// might be `&dyn SomeTrait` in a cast like:
 ///
+/// ```rust,ignore (not real code)
 /// let src: &SomeStruct = ...;
-/// let target = src as &SomeTrait;
+/// let target = src as &dyn SomeTrait;
+/// ```
 ///
 /// Then the output of this function would be (SomeStruct, SomeTrait) since for
 /// constructing the `target` fat-pointer we need the vtable for that pair.
@@ -1068,8 +1070,10 @@ fn should_codegen_locally<'tcx>(tcx: TyCtxt<'tcx>, instance: &Instance<'tcx>) ->
 /// for the pair of `T` (which is a trait) and the concrete type that `T` was
 /// originally coerced from:
 ///
+/// ```rust,ignore (not real code)
 /// let src: &ComplexStruct<SomeStruct> = ...;
-/// let target = src as &ComplexStruct<SomeTrait>;
+/// let target = src as &ComplexStruct<dyn SomeTrait>;
+/// ```
 ///
 /// Again, we want this `find_vtable_types_for_unsizing()` to provide the pair
 /// `(SomeStruct, SomeTrait)`.
diff --git a/compiler/rustc_parse/src/lib.rs b/compiler/rustc_parse/src/lib.rs
index 5924eba9f8b..3691d82a835 100644
--- a/compiler/rustc_parse/src/lib.rs
+++ b/compiler/rustc_parse/src/lib.rs
@@ -62,7 +62,7 @@ pub fn parse_crate_from_file<'a>(input: &Path, sess: &'a ParseSess) -> PResult<'
 pub fn parse_crate_attrs_from_file<'a>(
     input: &Path,
     sess: &'a ParseSess,
-) -> PResult<'a, Vec<ast::Attribute>> {
+) -> PResult<'a, ast::AttrVec> {
     let mut parser = new_parser_from_file(sess, input, None);
     parser.parse_inner_attributes()
 }
@@ -79,7 +79,7 @@ pub fn parse_crate_attrs_from_source_str(
     name: FileName,
     source: String,
     sess: &ParseSess,
-) -> PResult<'_, Vec<ast::Attribute>> {
+) -> PResult<'_, ast::AttrVec> {
     new_parser_from_source_str(sess, name, source).parse_inner_attributes()
 }
 
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index acdbddf4099..72ab96b5ca6 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -34,7 +34,7 @@ enum OuterAttributeType {
 impl<'a> Parser<'a> {
     /// Parses attributes that appear before an item.
     pub(super) fn parse_outer_attributes(&mut self) -> PResult<'a, AttrWrapper> {
-        let mut outer_attrs: Vec<ast::Attribute> = Vec::new();
+        let mut outer_attrs = ast::AttrVec::new();
         let mut just_parsed_doc_comment = false;
         let start_pos = self.token_cursor.num_next_calls;
         loop {
@@ -106,7 +106,7 @@ impl<'a> Parser<'a> {
                 break;
             }
         }
-        Ok(AttrWrapper::new(outer_attrs.into(), start_pos))
+        Ok(AttrWrapper::new(outer_attrs, start_pos))
     }
 
     /// Matches `attribute = # ! [ meta_item ]`.
@@ -283,8 +283,8 @@ impl<'a> Parser<'a> {
     /// terminated by a semicolon.
     ///
     /// Matches `inner_attrs*`.
-    pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, Vec<ast::Attribute>> {
-        let mut attrs: Vec<ast::Attribute> = vec![];
+    pub(crate) fn parse_inner_attributes(&mut self) -> PResult<'a, ast::AttrVec> {
+        let mut attrs = ast::AttrVec::new();
         loop {
             let start_pos: u32 = self.token_cursor.num_next_calls.try_into().unwrap();
             // Only try to parse if it is an inner attribute (has `!`).
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index 6c750ff428f..ed54af9f53f 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -15,11 +15,11 @@ use std::ops::Range;
 /// for the attribute target. This allows us to perform cfg-expansion on
 /// a token stream before we invoke a derive proc-macro.
 ///
-/// This wrapper prevents direct access to the underlying `Vec<ast::Attribute>`.
+/// This wrapper prevents direct access to the underlying `ast::AttrVec>`.
 /// Parsing code can only get access to the underlying attributes
 /// by passing an `AttrWrapper` to `collect_tokens_trailing_tokens`.
 /// This makes it difficult to accidentally construct an AST node
-/// (which stores a `Vec<ast::Attribute>`) without first collecting tokens.
+/// (which stores an `ast::AttrVec`) without first collecting tokens.
 ///
 /// This struct has its own module, to ensure that the parser code
 /// cannot directly access the `attrs` field
@@ -49,9 +49,10 @@ impl AttrWrapper {
         self.attrs
     }
 
+    // Prepend `self.attrs` to `attrs`.
     // FIXME: require passing an NT to prevent misuse of this method
-    pub(crate) fn prepend_to_nt_inner(self, attrs: &mut Vec<Attribute>) {
-        let mut self_attrs: Vec<_> = self.attrs.into();
+    pub(crate) fn prepend_to_nt_inner(self, attrs: &mut AttrVec) {
+        let mut self_attrs = self.attrs.clone();
         std::mem::swap(attrs, &mut self_attrs);
         attrs.extend(self_attrs);
     }
@@ -196,7 +197,7 @@ impl<'a> Parser<'a> {
         &mut self,
         attrs: AttrWrapper,
         force_collect: ForceCollect,
-        f: impl FnOnce(&mut Self, Vec<ast::Attribute>) -> PResult<'a, (R, TrailingToken)>,
+        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, (R, TrailingToken)>,
     ) -> PResult<'a, R> {
         // We only bail out when nothing could possibly observe the collected tokens:
         // 1. We cannot be force collecting tokens (since force-collecting requires tokens
@@ -212,7 +213,7 @@ impl<'a> Parser<'a> {
             // or `#[cfg_attr]` attributes.
             && !self.capture_cfg
         {
-            return Ok(f(self, attrs.attrs.into())?.0);
+            return Ok(f(self, attrs.attrs)?.0);
         }
 
         let start_token = (self.token.clone(), self.token_spacing);
@@ -222,7 +223,7 @@ impl<'a> Parser<'a> {
         let prev_capturing = std::mem::replace(&mut self.capture_state.capturing, Capturing::Yes);
         let replace_ranges_start = self.capture_state.replace_ranges.len();
 
-        let ret = f(self, attrs.attrs.into());
+        let ret = f(self, attrs.attrs);
 
         self.capture_state.capturing = prev_capturing;
 
@@ -352,7 +353,7 @@ impl<'a> Parser<'a> {
         // on the captured token stream.
         if self.capture_cfg
             && matches!(self.capture_state.capturing, Capturing::Yes)
-            && has_cfg_or_cfg_attr(&final_attrs)
+            && has_cfg_or_cfg_attr(final_attrs)
         {
             let attr_data = AttributesData { attrs: final_attrs.to_vec().into(), tokens };
 
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index 93e70e9abda..2c9f9a2c2c2 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -244,7 +244,7 @@ impl MultiSugg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_report_ambiguous_plus)]
+#[diag(parser::maybe_report_ambiguous_plus)]
 struct AmbiguousPlus {
     pub sum_ty: String,
     #[primary_span]
@@ -253,7 +253,7 @@ struct AmbiguousPlus {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
+#[diag(parser::maybe_recover_from_bad_type_plus, code = "E0178")]
 struct BadTypePlus {
     pub ty: String,
     #[primary_span]
@@ -287,7 +287,7 @@ pub enum BadTypePlusSub {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::maybe_recover_from_bad_qpath_stage_2)]
+#[diag(parser::maybe_recover_from_bad_qpath_stage_2)]
 struct BadQPathStage2 {
     #[primary_span]
     #[suggestion(applicability = "maybe-incorrect")]
@@ -296,7 +296,7 @@ struct BadQPathStage2 {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_semicolon)]
+#[diag(parser::incorrect_semicolon)]
 struct IncorrectSemicolon<'a> {
     #[primary_span]
     #[suggestion_short(applicability = "machine-applicable")]
@@ -307,7 +307,7 @@ struct IncorrectSemicolon<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_use_of_await)]
+#[diag(parser::incorrect_use_of_await)]
 struct IncorrectUseOfAwait {
     #[primary_span]
     #[suggestion(parser::parentheses_suggestion, applicability = "machine-applicable")]
@@ -315,7 +315,7 @@ struct IncorrectUseOfAwait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::incorrect_use_of_await)]
+#[diag(parser::incorrect_use_of_await)]
 struct IncorrectAwait {
     #[primary_span]
     span: Span,
@@ -326,7 +326,7 @@ struct IncorrectAwait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(parser::in_in_typo)]
+#[diag(parser::in_in_typo)]
 struct InInTypo {
     #[primary_span]
     span: Span,
@@ -334,6 +334,378 @@ struct InInTypo {
     sugg_span: Span,
 }
 
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_variable_declaration)]
+pub struct InvalidVariableDeclaration {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sub: InvalidVariableDeclarationSub,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub enum InvalidVariableDeclarationSub {
+    #[suggestion(
+        parser::switch_mut_let_order,
+        applicability = "maybe-incorrect",
+        code = "let mut"
+    )]
+    SwitchMutLetOrder(#[primary_span] Span),
+    #[suggestion(
+        parser::missing_let_before_mut,
+        applicability = "machine-applicable",
+        code = "let mut"
+    )]
+    MissingLet(#[primary_span] Span),
+    #[suggestion(parser::use_let_not_auto, applicability = "machine-applicable", code = "let")]
+    UseLetNotAuto(#[primary_span] Span),
+    #[suggestion(parser::use_let_not_var, applicability = "machine-applicable", code = "let")]
+    UseLetNotVar(#[primary_span] Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_comparison_operator)]
+pub(crate) struct InvalidComparisonOperator {
+    #[primary_span]
+    pub span: Span,
+    pub invalid: String,
+    #[subdiagnostic]
+    pub sub: InvalidComparisonOperatorSub,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub(crate) enum InvalidComparisonOperatorSub {
+    #[suggestion_short(
+        parser::use_instead,
+        applicability = "machine-applicable",
+        code = "{correct}"
+    )]
+    Correctable {
+        #[primary_span]
+        span: Span,
+        invalid: String,
+        correct: String,
+    },
+    #[label(parser::spaceship_operator_invalid)]
+    Spaceship(#[primary_span] Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_logical_operator)]
+#[note]
+pub(crate) struct InvalidLogicalOperator {
+    #[primary_span]
+    pub span: Span,
+    pub incorrect: String,
+    #[subdiagnostic]
+    pub sub: InvalidLogicalOperatorSub,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub(crate) enum InvalidLogicalOperatorSub {
+    #[suggestion_short(
+        parser::use_amp_amp_for_conjunction,
+        applicability = "machine-applicable",
+        code = "&&"
+    )]
+    Conjunction(#[primary_span] Span),
+    #[suggestion_short(
+        parser::use_pipe_pipe_for_disjunction,
+        applicability = "machine-applicable",
+        code = "||"
+    )]
+    Disjunction(#[primary_span] Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::tilde_is_not_unary_operator)]
+pub(crate) struct TildeAsUnaryOperator(
+    #[primary_span]
+    #[suggestion_short(applicability = "machine-applicable", code = "!")]
+    pub Span,
+);
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::unexpected_token_after_not)]
+pub(crate) struct NotAsNegationOperator {
+    #[primary_span]
+    pub negated: Span,
+    pub negated_desc: String,
+    #[suggestion_short(applicability = "machine-applicable", code = "!")]
+    pub not: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::malformed_loop_label)]
+pub(crate) struct MalformedLoopLabel {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "{correct_label}")]
+    pub span: Span,
+    pub correct_label: Ident,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::lifetime_in_borrow_expression)]
+pub(crate) struct LifetimeInBorrowExpression {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(applicability = "machine-applicable", code = "")]
+    #[label]
+    pub lifetime_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::field_expression_with_generic)]
+pub(crate) struct FieldExpressionWithGeneric(#[primary_span] pub Span);
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::macro_invocation_with_qualified_path)]
+pub(crate) struct MacroInvocationWithQualifiedPath(#[primary_span] pub Span);
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::unexpected_token_after_label)]
+pub(crate) struct UnexpectedTokenAfterLabel(
+    #[primary_span]
+    #[label(parser::unexpected_token_after_label)]
+    pub Span,
+);
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::require_colon_after_labeled_expression)]
+#[note]
+pub(crate) struct RequireColonAfterLabeledExpression {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub label: Span,
+    #[suggestion_short(applicability = "machine-applicable", code = ": ")]
+    pub label_end: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::do_catch_syntax_removed)]
+#[note]
+pub(crate) struct DoCatchSyntaxRemoved {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "try")]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::float_literal_requires_integer_part)]
+pub(crate) struct FloatLiteralRequiresIntegerPart {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = "{correct}")]
+    pub span: Span,
+    pub correct: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_int_literal_width)]
+#[help]
+pub(crate) struct InvalidIntLiteralWidth {
+    #[primary_span]
+    pub span: Span,
+    pub width: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_num_literal_base_prefix)]
+#[note]
+pub(crate) struct InvalidNumLiteralBasePrefix {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "{fixed}")]
+    pub span: Span,
+    pub fixed: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_num_literal_suffix)]
+#[help]
+pub(crate) struct InvalidNumLiteralSuffix {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub suffix: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_float_literal_width)]
+#[help]
+pub(crate) struct InvalidFloatLiteralWidth {
+    #[primary_span]
+    pub span: Span,
+    pub width: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_float_literal_suffix)]
+#[help]
+pub(crate) struct InvalidFloatLiteralSuffix {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub suffix: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::int_literal_too_large)]
+pub(crate) struct IntLiteralTooLarge {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::missing_semicolon_before_array)]
+pub(crate) struct MissingSemicolonBeforeArray {
+    #[primary_span]
+    pub open_delim: Span,
+    #[suggestion_verbose(applicability = "maybe-incorrect", code = ";")]
+    pub semicolon: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::invalid_block_macro_segment)]
+pub(crate) struct InvalidBlockMacroSegment {
+    #[primary_span]
+    pub span: Span,
+    #[label]
+    pub context: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::if_expression_missing_then_block)]
+pub(crate) struct IfExpressionMissingThenBlock {
+    #[primary_span]
+    pub if_span: Span,
+    #[subdiagnostic]
+    pub sub: IfExpressionMissingThenBlockSub,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub(crate) enum IfExpressionMissingThenBlockSub {
+    #[help(parser::condition_possibly_unfinished)]
+    UnfinishedCondition(#[primary_span] Span),
+    #[help(parser::add_then_block)]
+    AddThenBlock(#[primary_span] Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::if_expression_missing_condition)]
+pub(crate) struct IfExpressionMissingCondition {
+    #[primary_span]
+    #[label(parser::condition_label)]
+    pub if_span: Span,
+    #[label(parser::block_label)]
+    pub block_span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::expected_expression_found_let)]
+pub(crate) struct ExpectedExpressionFoundLet {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::expected_else_block)]
+pub(crate) struct ExpectedElseBlock {
+    #[primary_span]
+    pub first_tok_span: Span,
+    pub first_tok: String,
+    #[label]
+    pub else_span: Span,
+    #[suggestion(applicability = "maybe-incorrect", code = "if ")]
+    pub condition_start: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::outer_attribute_not_allowed_on_if_else)]
+pub(crate) struct OuterAttributeNotAllowedOnIfElse {
+    #[primary_span]
+    pub last: Span,
+
+    #[label(parser::branch_label)]
+    pub branch_span: Span,
+
+    #[label(parser::ctx_label)]
+    pub ctx_span: Span,
+    pub ctx: String,
+
+    #[suggestion(applicability = "machine-applicable", code = "")]
+    pub attributes: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::missing_in_in_for_loop)]
+pub(crate) struct MissingInInForLoop {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sub: MissingInInForLoopSub,
+}
+
+#[derive(SessionSubdiagnostic)]
+pub(crate) enum MissingInInForLoopSub {
+    // Has been misleading, at least in the past (closed Issue #48492), thus maybe-incorrect
+    #[suggestion_short(parser::use_in_not_of, applicability = "maybe-incorrect", code = "in")]
+    InNotOf(#[primary_span] Span),
+    #[suggestion_short(parser::add_in, applicability = "maybe-incorrect", code = " in ")]
+    AddIn(#[primary_span] Span),
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::missing_comma_after_match_arm)]
+pub(crate) struct MissingCommaAfterMatchArm {
+    #[primary_span]
+    #[suggestion(applicability = "machine-applicable", code = ",")]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::catch_after_try)]
+#[help]
+pub(crate) struct CatchAfterTry {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::comma_after_base_struct)]
+#[note]
+pub(crate) struct CommaAfterBaseStruct {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion_short(applicability = "machine-applicable", code = "")]
+    pub comma: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::eq_field_init)]
+pub(crate) struct EqFieldInit {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(applicability = "machine-applicable", code = ":")]
+    pub eq: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::dotdotdot)]
+pub(crate) struct DotDotDot {
+    #[primary_span]
+    #[suggestion(parser::suggest_exclusive_range, applicability = "maybe-incorrect", code = "..")]
+    #[suggestion(parser::suggest_inclusive_range, applicability = "maybe-incorrect", code = "..=")]
+    pub span: Span,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(parser::left_arrow_operator)]
+pub(crate) struct LeftArrowOperator {
+    #[primary_span]
+    #[suggestion(applicability = "maybe-incorrect", code = "< -")]
+    pub span: Span,
+}
+
 // SnapshotParser is used to create a snapshot of the parser
 // without causing duplicate errors being emitted when the `Parser`
 // is dropped.
@@ -611,6 +983,15 @@ impl<'a> Parser<'a> {
                     appl,
                 );
             }
+
+            if ["def", "fun", "func", "function"].contains(&symbol.as_str()) {
+                err.span_suggestion_short(
+                    self.prev_token.span,
+                    &format!("write `fn` instead of `{symbol}` to declare a function"),
+                    "fn",
+                    appl,
+                );
+            }
         }
 
         // Add suggestion for a missing closing angle bracket if '>' is included in expected_tokens
@@ -2332,7 +2713,7 @@ impl<'a> Parser<'a> {
 
     fn recover_const_param_decl(&mut self, ty_generics: Option<&Generics>) -> Option<GenericArg> {
         let snapshot = self.create_snapshot_for_diagnostic();
-        let param = match self.parse_const_param(vec![]) {
+        let param = match self.parse_const_param(AttrVec::new()) {
             Ok(param) => param,
             Err(err) => {
                 err.cancel();
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index c824566c35f..17117cbc8fb 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -1,4 +1,14 @@
-use super::diagnostics::SnapshotParser;
+use super::diagnostics::{
+    CatchAfterTry, CommaAfterBaseStruct, DoCatchSyntaxRemoved, DotDotDot, EqFieldInit,
+    ExpectedElseBlock, ExpectedExpressionFoundLet, FieldExpressionWithGeneric,
+    FloatLiteralRequiresIntegerPart, IfExpressionMissingCondition, IfExpressionMissingThenBlock,
+    IfExpressionMissingThenBlockSub, InvalidBlockMacroSegment, InvalidComparisonOperator,
+    InvalidComparisonOperatorSub, InvalidLogicalOperator, InvalidLogicalOperatorSub,
+    LeftArrowOperator, LifetimeInBorrowExpression, MacroInvocationWithQualifiedPath,
+    MalformedLoopLabel, MissingInInForLoop, MissingInInForLoopSub, MissingSemicolonBeforeArray,
+    NotAsNegationOperator, OuterAttributeNotAllowedOnIfElse, RequireColonAfterLabeledExpression,
+    SnapshotParser, TildeAsUnaryOperator, UnexpectedTokenAfterLabel,
+};
 use super::pat::{CommaRecoveryMode, RecoverColon, RecoverComma, PARAM_EXPECTED};
 use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{
@@ -6,6 +16,11 @@ use super::{
     SemiColonMode, SeqSep, TokenExpectType, TokenType, TrailingToken,
 };
 use crate::maybe_recover_from_interpolated_ty_qpath;
+use crate::parser::diagnostics::{
+    IntLiteralTooLarge, InvalidFloatLiteralSuffix, InvalidFloatLiteralWidth,
+    InvalidIntLiteralWidth, InvalidNumLiteralBasePrefix, InvalidNumLiteralSuffix,
+    MissingCommaAfterMatchArm,
+};
 
 use core::mem;
 use rustc_ast::ptr::P;
@@ -20,9 +35,10 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::{ClosureBinder, StmtKind};
 use rustc_ast_pretty::pprust;
-use rustc_errors::{Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, PResult};
+use rustc_errors::{Applicability, Diagnostic, PResult};
 use rustc_session::lint::builtin::BREAK_WITH_LABEL_AND_LOOP;
 use rustc_session::lint::BuiltinLintDiagnostics;
+use rustc_session::SessionDiagnostic;
 use rustc_span::source_map::{self, Span, Spanned};
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{BytePos, Pos};
@@ -216,15 +232,18 @@ impl<'a> Parser<'a> {
                     AssocOp::Equal => "==",
                     AssocOp::NotEqual => "!=",
                     _ => unreachable!(),
-                };
-                self.struct_span_err(sp, &format!("invalid comparison operator `{sugg}=`"))
-                    .span_suggestion_short(
-                        sp,
-                        &format!("`{s}=` is not a valid comparison operator, use `{s}`", s = sugg),
-                        sugg,
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                }
+                .into();
+                let invalid = format!("{}=", &sugg);
+                self.sess.emit_err(InvalidComparisonOperator {
+                    span: sp,
+                    invalid: invalid.clone(),
+                    sub: InvalidComparisonOperatorSub::Correctable {
+                        span: sp,
+                        invalid,
+                        correct: sugg,
+                    },
+                });
                 self.bump();
             }
 
@@ -234,14 +253,15 @@ impl<'a> Parser<'a> {
                 && self.prev_token.span.hi() == self.token.span.lo()
             {
                 let sp = op.span.to(self.token.span);
-                self.struct_span_err(sp, "invalid comparison operator `<>`")
-                    .span_suggestion_short(
-                        sp,
-                        "`<>` is not a valid comparison operator, use `!=`",
-                        "!=",
-                        Applicability::MachineApplicable,
-                    )
-                    .emit();
+                self.sess.emit_err(InvalidComparisonOperator {
+                    span: sp,
+                    invalid: "<>".into(),
+                    sub: InvalidComparisonOperatorSub::Correctable {
+                        span: sp,
+                        invalid: "<>".into(),
+                        correct: "!=".into(),
+                    },
+                });
                 self.bump();
             }
 
@@ -251,12 +271,11 @@ impl<'a> Parser<'a> {
                 && self.prev_token.span.hi() == self.token.span.lo()
             {
                 let sp = op.span.to(self.token.span);
-                self.struct_span_err(sp, "invalid comparison operator `<=>`")
-                    .span_label(
-                        sp,
-                        "`<=>` is not a valid comparison operator, use `std::cmp::Ordering`",
-                    )
-                    .emit();
+                self.sess.emit_err(InvalidComparisonOperator {
+                    span: sp,
+                    invalid: "<=>".into(),
+                    sub: InvalidComparisonOperatorSub::Spaceship(sp),
+                });
                 self.bump();
             }
 
@@ -430,11 +449,19 @@ impl<'a> Parser<'a> {
             }
             (Some(op), _) => (op, self.token.span),
             (None, Some((Ident { name: sym::and, span }, false))) => {
-                self.error_bad_logical_op("and", "&&", "conjunction");
+                self.sess.emit_err(InvalidLogicalOperator {
+                    span: self.token.span,
+                    incorrect: "and".into(),
+                    sub: InvalidLogicalOperatorSub::Conjunction(self.token.span),
+                });
                 (AssocOp::LAnd, span)
             }
             (None, Some((Ident { name: sym::or, span }, false))) => {
-                self.error_bad_logical_op("or", "||", "disjunction");
+                self.sess.emit_err(InvalidLogicalOperator {
+                    span: self.token.span,
+                    incorrect: "or".into(),
+                    sub: InvalidLogicalOperatorSub::Disjunction(self.token.span),
+                });
                 (AssocOp::LOr, span)
             }
             _ => return None,
@@ -442,19 +469,6 @@ impl<'a> Parser<'a> {
         Some(source_map::respan(span, op))
     }
 
-    /// Error on `and` and `or` suggesting `&&` and `||` respectively.
-    fn error_bad_logical_op(&self, bad: &str, good: &str, english: &str) {
-        self.struct_span_err(self.token.span, &format!("`{bad}` is not a logical operator"))
-            .span_suggestion_short(
-                self.token.span,
-                &format!("use `{good}` to perform logical {english}"),
-                good,
-                Applicability::MachineApplicable,
-            )
-            .note("unlike in e.g., python and PHP, `&&` and `||` are used for logical operators")
-            .emit();
-    }
-
     /// Checks if this expression is a successfully parsed statement.
     fn expr_is_complete(&self, e: &Expr) -> bool {
         self.restrictions.contains(Restrictions::STMT_EXPR)
@@ -619,14 +633,7 @@ impl<'a> Parser<'a> {
 
     // Recover on `!` suggesting for bitwise negation instead.
     fn recover_tilde_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
-        self.struct_span_err(lo, "`~` cannot be used as a unary operator")
-            .span_suggestion_short(
-                lo,
-                "use `!` to perform bitwise not",
-                "!",
-                Applicability::MachineApplicable,
-            )
-            .emit();
+        self.sess.emit_err(TildeAsUnaryOperator(lo));
 
         self.parse_unary_expr(lo, UnOp::Not)
     }
@@ -652,20 +659,14 @@ impl<'a> Parser<'a> {
     /// Recover on `not expr` in favor of `!expr`.
     fn recover_not_expr(&mut self, lo: Span) -> PResult<'a, (Span, ExprKind)> {
         // Emit the error...
-        let not_token = self.look_ahead(1, |t| t.clone());
-        self.struct_span_err(
-            not_token.span,
-            &format!("unexpected {} after identifier", super::token_descr(&not_token)),
-        )
-        .span_suggestion_short(
+        let negated_token = self.look_ahead(1, |t| t.clone());
+        self.sess.emit_err(NotAsNegationOperator {
+            negated: negated_token.span,
+            negated_desc: super::token_descr(&negated_token),
             // Span the `not` plus trailing whitespace to avoid
             // trailing whitespace after the `!` in our suggestion
-            self.sess.source_map().span_until_non_whitespace(lo.to(not_token.span)),
-            "use `!` to perform logical negation",
-            "!",
-            Applicability::MachineApplicable,
-        )
-        .emit();
+            not: self.sess.source_map().span_until_non_whitespace(lo.to(negated_token.span)),
+        });
 
         // ...and recover!
         self.parse_unary_expr(lo, UnOp::Not)
@@ -725,14 +726,10 @@ impl<'a> Parser<'a> {
                         match self.parse_labeled_expr(label, false) {
                             Ok(expr) => {
                                 type_err.cancel();
-                                self.struct_span_err(label.ident.span, "malformed loop label")
-                                    .span_suggestion(
-                                        label.ident.span,
-                                        "use the correct loop label format",
-                                        label.ident,
-                                        Applicability::MachineApplicable,
-                                    )
-                                    .emit();
+                                self.sess.emit_err(MalformedLoopLabel {
+                                    span: label.ident.span,
+                                    correct_label: label.ident,
+                                });
                                 return Ok(expr);
                             }
                             Err(err) => {
@@ -910,15 +907,7 @@ impl<'a> Parser<'a> {
     }
 
     fn error_remove_borrow_lifetime(&self, span: Span, lt_span: Span) {
-        self.struct_span_err(span, "borrow expressions cannot be annotated with lifetimes")
-            .span_label(lt_span, "annotated with lifetime here")
-            .span_suggestion(
-                lt_span,
-                "remove the lifetime annotation",
-                "",
-                Applicability::MachineApplicable,
-            )
-            .emit();
+        self.sess.emit_err(LifetimeInBorrowExpression { span, lifetime_span: lt_span });
     }
 
     /// Parse `mut?` or `raw [ const | mut ]`.
@@ -950,15 +939,15 @@ impl<'a> Parser<'a> {
         &mut self,
         e0: P<Expr>,
         lo: Span,
-        mut attrs: Vec<ast::Attribute>,
+        mut attrs: ast::AttrVec,
     ) -> PResult<'a, P<Expr>> {
         // Stitch the list of outer attributes onto the return value.
         // A little bit ugly, but the best way given the current code
         // structure
         self.parse_dot_or_call_expr_with_(e0, lo).map(|expr| {
             expr.map(|mut expr| {
-                attrs.extend::<Vec<_>>(expr.attrs.into());
-                expr.attrs = attrs.into();
+                attrs.extend(expr.attrs);
+                expr.attrs = attrs;
                 expr
             })
         })
@@ -1272,11 +1261,7 @@ impl<'a> Parser<'a> {
         } else {
             // Field access `expr.f`
             if let Some(args) = segment.args {
-                self.struct_span_err(
-                    args.span(),
-                    "field expressions cannot have generic arguments",
-                )
-                .emit();
+                self.sess.emit_err(FieldExpressionWithGeneric(args.span()));
             }
 
             let span = lo.to(self.prev_token.span);
@@ -1489,14 +1474,14 @@ impl<'a> Parser<'a> {
         let (span, kind) = if self.eat(&token::Not) {
             // MACRO INVOCATION expression
             if qself.is_some() {
-                self.struct_span_err(path.span, "macros cannot use qualified paths").emit();
+                self.sess.emit_err(MacroInvocationWithQualifiedPath(path.span));
             }
             let lo = path.span;
-            let mac = MacCall {
+            let mac = P(MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
-            };
+            });
             (lo.to(self.prev_token.span), ExprKind::MacCall(mac))
         } else if self.check(&token::OpenDelim(Delimiter::Brace)) &&
             let Some(expr) = self.maybe_parse_struct_expr(qself.as_ref(), &path) {
@@ -1535,11 +1520,11 @@ impl<'a> Parser<'a> {
             && (self.check_noexpect(&TokenKind::Comma) || self.check_noexpect(&TokenKind::Gt))
         {
             // We're probably inside of a `Path<'a>` that needs a turbofish
-            let msg = "expected `while`, `for`, `loop` or `{` after a label";
-            self.struct_span_err(self.token.span, msg).span_label(self.token.span, msg).emit();
+            self.sess.emit_err(UnexpectedTokenAfterLabel(self.token.span));
             consume_colon = false;
             Ok(self.mk_expr_err(lo))
         } else {
+            // FIXME: use UnexpectedTokenAfterLabel, needs multipart suggestions
             let msg = "expected `while`, `for`, `loop` or `{` after a label";
 
             let mut err = self.struct_span_err(self.token.span, msg);
@@ -1604,25 +1589,16 @@ impl<'a> Parser<'a> {
         }?;
 
         if !ate_colon && consume_colon {
-            self.error_labeled_expr_must_be_followed_by_colon(lo, expr.span);
+            self.sess.emit_err(RequireColonAfterLabeledExpression {
+                span: expr.span,
+                label: lo,
+                label_end: lo.shrink_to_hi(),
+            });
         }
 
         Ok(expr)
     }
 
-    fn error_labeled_expr_must_be_followed_by_colon(&self, lo: Span, span: Span) {
-        self.struct_span_err(span, "labeled expression must be followed by `:`")
-            .span_label(lo, "the label")
-            .span_suggestion_short(
-                lo.shrink_to_hi(),
-                "add `:` after the label",
-                ": ",
-                Applicability::MachineApplicable,
-            )
-            .note("labels are used before loops and blocks, allowing e.g., `break 'label` to them")
-            .emit();
-    }
-
     /// Recover on the syntax `do catch { ... }` suggesting `try { ... }` instead.
     fn recover_do_catch(&mut self) -> PResult<'a, P<Expr>> {
         let lo = self.token.span;
@@ -1630,16 +1606,8 @@ impl<'a> Parser<'a> {
         self.bump(); // `do`
         self.bump(); // `catch`
 
-        let span_dc = lo.to(self.prev_token.span);
-        self.struct_span_err(span_dc, "found removed `do catch` syntax")
-            .span_suggestion(
-                span_dc,
-                "replace with the new syntax",
-                "try",
-                Applicability::MachineApplicable,
-            )
-            .note("following RFC #2388, the new non-placeholder syntax is `try`")
-            .emit();
+        let span = lo.to(self.prev_token.span);
+        self.sess.emit_err(DoCatchSyntaxRemoved { span });
 
         self.parse_try_block(lo)
     }
@@ -1834,14 +1802,10 @@ impl<'a> Parser<'a> {
     }
 
     fn error_float_lits_must_have_int_part(&self, token: &Token) {
-        self.struct_span_err(token.span, "float literals must have an integer part")
-            .span_suggestion(
-                token.span,
-                "must have an integer part",
-                pprust::token_to_string(token),
-                Applicability::MachineApplicable,
-            )
-            .emit();
+        self.sess.emit_err(FloatLiteralRequiresIntegerPart {
+            span: token.span,
+            correct: pprust::token_to_string(token).into_owned(),
+        });
     }
 
     fn report_lit_error(&self, err: LitError, lit: token::Lit, span: Span) {
@@ -1883,28 +1847,11 @@ impl<'a> Parser<'a> {
                 let suf = suf.as_str();
                 if looks_like_width_suffix(&['i', 'u'], &suf) {
                     // If it looks like a width, try to be helpful.
-                    let msg = format!("invalid width `{}` for integer literal", &suf[1..]);
-                    self.struct_span_err(span, &msg)
-                        .help("valid widths are 8, 16, 32, 64 and 128")
-                        .emit();
+                    self.sess.emit_err(InvalidIntLiteralWidth { span, width: suf[1..].into() });
                 } else if let Some(fixed) = fix_base_capitalisation(suf) {
-                    let msg = "invalid base prefix for number literal";
-
-                    self.struct_span_err(span, msg)
-                        .note("base prefixes (`0xff`, `0b1010`, `0o755`) are lowercase")
-                        .span_suggestion(
-                            span,
-                            "try making the prefix lowercase",
-                            fixed,
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
+                    self.sess.emit_err(InvalidNumLiteralBasePrefix { span, fixed });
                 } else {
-                    let msg = format!("invalid suffix `{suf}` for number literal");
-                    self.struct_span_err(span, &msg)
-                        .span_label(span, format!("invalid suffix `{suf}`"))
-                        .help("the suffix must be one of the numeric types (`u32`, `isize`, `f32`, etc.)")
-                        .emit();
+                    self.sess.emit_err(InvalidNumLiteralSuffix { span, suffix: suf.to_string() });
                 }
             }
             LitError::InvalidFloatSuffix => {
@@ -1912,14 +1859,10 @@ impl<'a> Parser<'a> {
                 let suf = suf.as_str();
                 if looks_like_width_suffix(&['f'], suf) {
                     // If it looks like a width, try to be helpful.
-                    let msg = format!("invalid width `{}` for float literal", &suf[1..]);
-                    self.struct_span_err(span, &msg).help("valid widths are 32 and 64").emit();
+                    self.sess
+                        .emit_err(InvalidFloatLiteralWidth { span, width: suf[1..].to_string() });
                 } else {
-                    let msg = format!("invalid suffix `{suf}` for float literal");
-                    self.struct_span_err(span, &msg)
-                        .span_label(span, format!("invalid suffix `{suf}`"))
-                        .help("valid suffixes are `f32` and `f64`")
-                        .emit();
+                    self.sess.emit_err(InvalidFloatLiteralSuffix { span, suffix: suf.to_string() });
                 }
             }
             LitError::NonDecimalFloat(base) => {
@@ -1934,7 +1877,7 @@ impl<'a> Parser<'a> {
                     .emit();
             }
             LitError::IntTooLarge => {
-                self.struct_span_err(span, "integer literal is too large").emit();
+                self.sess.emit_err(IntLiteralTooLarge { span });
             }
         }
     }
@@ -2046,14 +1989,10 @@ impl<'a> Parser<'a> {
                         .span_to_snippet(snapshot.token.span)
                         .map_or(false, |snippet| snippet == "]") =>
                 {
-                    let mut err = self.struct_span_err(open_delim_span, "expected `;`, found `[`");
-                    err.span_suggestion_verbose(
-                        prev_span.shrink_to_hi(),
-                        "consider adding `;` here",
-                        ';',
-                        Applicability::MaybeIncorrect,
-                    );
-                    return Err(err);
+                    return Err(MissingSemicolonBeforeArray {
+                        open_delim: open_delim_span,
+                        semicolon: prev_span.shrink_to_hi(),
+                    }.into_diagnostic(self.sess));
                 }
                 Ok(_) => (),
                 Err(err) => err.cancel(),
@@ -2080,9 +2019,10 @@ impl<'a> Parser<'a> {
         }
 
         if self.token.is_whole_block() {
-            self.struct_span_err(self.token.span, "cannot use a `block` macro fragment here")
-                .span_label(lo.to(self.token.span), "the `block` fragment is within this context")
-                .emit();
+            self.sess.emit_err(InvalidBlockMacroSegment {
+                span: self.token.span,
+                context: lo.to(self.token.span),
+            });
         }
 
         let (attrs, blk) = self.parse_block_common(lo, blk_mode)?;
@@ -2224,7 +2164,7 @@ impl<'a> Parser<'a> {
 
             Ok((
                 Param {
-                    attrs: attrs.into(),
+                    attrs,
                     ty,
                     pat,
                     span: lo.to(this.prev_token.span),
@@ -2252,11 +2192,19 @@ impl<'a> Parser<'a> {
             let block = match &mut cond.kind {
                 ExprKind::Binary(Spanned { span: binop_span, .. }, _, right)
                     if let ExprKind::Block(_, None) = right.kind => {
-                        this.error_missing_if_then_block(lo, cond_span.shrink_to_lo().to(*binop_span), true).emit();
+                        self.sess.emit_err(IfExpressionMissingThenBlock {
+                            if_span: lo,
+                            sub: IfExpressionMissingThenBlockSub::UnfinishedCondition(
+                                cond_span.shrink_to_lo().to(*binop_span)
+                            ),
+                        });
                         std::mem::replace(right, this.mk_expr_err(binop_span.shrink_to_hi()))
                     },
                 ExprKind::Block(_, None) => {
-                    this.error_missing_if_cond(lo, cond_span).emit();
+                    self.sess.emit_err(IfExpressionMissingCondition {
+                        if_span: self.sess.source_map().next_point(lo),
+                        block_span: self.sess.source_map().start_point(cond_span),
+                    });
                     std::mem::replace(&mut cond, this.mk_expr_err(cond_span.shrink_to_hi()))
                 }
                 _ => {
@@ -2274,7 +2222,10 @@ impl<'a> Parser<'a> {
             if let Some(block) = recover_block_from_condition(self) {
                 block
             } else {
-                self.error_missing_if_then_block(lo, cond_span, false).emit();
+                self.sess.emit_err(IfExpressionMissingThenBlock {
+                    if_span: lo,
+                    sub: IfExpressionMissingThenBlockSub::AddThenBlock(cond_span.shrink_to_hi()),
+                });
                 self.mk_block_err(cond_span.shrink_to_hi())
             }
         } else {
@@ -2302,39 +2253,6 @@ impl<'a> Parser<'a> {
         Ok(self.mk_expr(lo.to(self.prev_token.span), ExprKind::If(cond, thn, els)))
     }
 
-    fn error_missing_if_then_block(
-        &self,
-        if_span: Span,
-        cond_span: Span,
-        is_unfinished: bool,
-    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        let mut err = self.struct_span_err(
-            if_span,
-            "this `if` expression is missing a block after the condition",
-        );
-        if is_unfinished {
-            err.span_help(cond_span, "this binary operation is possibly unfinished");
-        } else {
-            err.span_help(cond_span.shrink_to_hi(), "add a block here");
-        }
-        err
-    }
-
-    fn error_missing_if_cond(
-        &self,
-        lo: Span,
-        span: Span,
-    ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
-        let next_span = self.sess.source_map().next_point(lo);
-        let mut err = self.struct_span_err(next_span, "missing condition for `if` expression");
-        err.span_label(next_span, "expected condition here");
-        err.span_label(
-            self.sess.source_map().start_point(span),
-            "if this block is the condition of the `if` expression, then it must be followed by another block"
-        );
-        err
-    }
-
     /// Parses the condition of a `if` or `while` expression.
     fn parse_cond_expr(&mut self) -> PResult<'a, P<Expr>> {
         self.parse_expr_res(Restrictions::NO_STRUCT_LITERAL | Restrictions::ALLOW_LET, None)
@@ -2350,8 +2268,7 @@ impl<'a> Parser<'a> {
             TokenKind::AndAnd | TokenKind::Ident(kw::If, _) | TokenKind::Ident(kw::While, _)
         );
         if !self.restrictions.contains(Restrictions::ALLOW_LET) || not_in_chain {
-            self.struct_span_err(self.token.span, "expected expression, found `let` statement")
-                .emit();
+            self.sess.emit_err(ExpectedExpressionFoundLet { span: self.token.span });
         }
 
         self.bump(); // Eat `let` token
@@ -2389,15 +2306,12 @@ impl<'a> Parser<'a> {
                     if self.check(&TokenKind::OpenDelim(Delimiter::Brace))
                         && classify::expr_requires_semi_to_be_stmt(&cond) =>
                 {
-                    self.struct_span_err(first_tok_span, format!("expected `{{`, found {first_tok}"))
-                        .span_label(else_span, "expected an `if` or a block after this `else`")
-                        .span_suggestion(
-                            cond.span.shrink_to_lo(),
-                            "add an `if` if this is the condition of a chained `else if` statement",
-                            "if ",
-                            Applicability::MaybeIncorrect,
-                        )
-                        .emit();
+                    self.sess.emit_err(ExpectedElseBlock {
+                        first_tok_span,
+                        first_tok,
+                        else_span,
+                        condition_start: cond.span.shrink_to_lo(),
+                    });
                     self.parse_if_after_cond(cond.span.shrink_to_lo(), cond)?
                 }
                 Err(e) => {
@@ -2422,16 +2336,18 @@ impl<'a> Parser<'a> {
         branch_span: Span,
         attrs: &[ast::Attribute],
     ) {
-        let (span, last) = match attrs {
+        let (attributes, last) = match attrs {
             [] => return,
             [x0 @ xn] | [x0, .., xn] => (x0.span.to(xn.span), xn.span),
         };
         let ctx = if is_ctx_else { "else" } else { "if" };
-        self.struct_span_err(last, "outer attributes are not allowed on `if` and `else` branches")
-            .span_label(branch_span, "the attributes are attached to this branch")
-            .span_label(ctx_span, format!("the branch belongs to this `{ctx}`"))
-            .span_suggestion(span, "remove the attributes", "", Applicability::MachineApplicable)
-            .emit();
+        self.sess.emit_err(OuterAttributeNotAllowedOnIfElse {
+            last,
+            branch_span,
+            ctx_span,
+            ctx: ctx.to_string(),
+            attributes,
+        });
     }
 
     /// Parses `for <src_pat> in <src_expr> <src_loop_block>` (`for` token already eaten).
@@ -2465,23 +2381,16 @@ impl<'a> Parser<'a> {
     }
 
     fn error_missing_in_for_loop(&mut self) {
-        let (span, msg, sugg) = if self.token.is_ident_named(sym::of) {
+        let (span, sub): (_, fn(_) -> _) = if self.token.is_ident_named(sym::of) {
             // Possibly using JS syntax (#75311).
             let span = self.token.span;
             self.bump();
-            (span, "try using `in` here instead", "in")
+            (span, MissingInInForLoopSub::InNotOf)
         } else {
-            (self.prev_token.span.between(self.token.span), "try adding `in` here", " in ")
+            (self.prev_token.span.between(self.token.span), MissingInInForLoopSub::AddIn)
         };
-        self.struct_span_err(span, "missing `in` in `for` loop")
-            .span_suggestion_short(
-                span,
-                msg,
-                sugg,
-                // Has been misleading, at least in the past (closed Issue #48492).
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+
+        self.sess.emit_err(MissingInInForLoop { span, sub: sub(span) });
     }
 
     /// Parses a `while` or `while let` expression (`while` token already eaten).
@@ -2732,7 +2641,7 @@ impl<'a> Parser<'a> {
                     let span = body.span;
                     return Ok((
                         ast::Arm {
-                            attrs: attrs.into(),
+                            attrs,
                             pat,
                             guard,
                             body,
@@ -2787,17 +2696,9 @@ impl<'a> Parser<'a> {
                                 .is_ok();
                             if pattern_follows && snapshot.check(&TokenKind::FatArrow) {
                                 err.cancel();
-                                this.struct_span_err(
-                                    hi.shrink_to_hi(),
-                                    "expected `,` following `match` arm",
-                                )
-                                .span_suggestion(
-                                    hi.shrink_to_hi(),
-                                    "missing a comma here to end this `match` arm",
-                                    ",",
-                                    Applicability::MachineApplicable,
-                                )
-                                .emit();
+                                this.sess.emit_err(MissingCommaAfterMatchArm {
+                                    span: hi.shrink_to_hi(),
+                                });
                                 return Ok(true);
                             }
                         }
@@ -2810,7 +2711,7 @@ impl<'a> Parser<'a> {
 
             Ok((
                 ast::Arm {
-                    attrs: attrs.into(),
+                    attrs,
                     pat,
                     guard,
                     body: expr,
@@ -2827,13 +2728,7 @@ impl<'a> Parser<'a> {
     fn parse_try_block(&mut self, span_lo: Span) -> PResult<'a, P<Expr>> {
         let (attrs, body) = self.parse_inner_attrs_and_block()?;
         if self.eat_keyword(kw::Catch) {
-            let mut error = self.struct_span_err(
-                self.prev_token.span,
-                "keyword `catch` cannot follow a `try` block",
-            );
-            error.help("try using `match` on the result of the `try` block instead");
-            error.emit();
-            Err(error)
+            Err(CatchAfterTry { span: self.prev_token.span }.into_diagnostic(self.sess))
         } else {
             let span = span_lo.to(body.span);
             self.sess.gated_spans.gate(sym::try_blocks, span);
@@ -3082,18 +2977,10 @@ impl<'a> Parser<'a> {
         if self.token != token::Comma {
             return;
         }
-        self.struct_span_err(
-            span.to(self.prev_token.span),
-            "cannot use a comma after the base struct",
-        )
-        .span_suggestion_short(
-            self.token.span,
-            "remove this comma",
-            "",
-            Applicability::MachineApplicable,
-        )
-        .note("the base struct must always be the last field")
-        .emit();
+        self.sess.emit_err(CommaAfterBaseStruct {
+            span: span.to(self.prev_token.span),
+            comma: self.token.span,
+        });
         self.recover_stmt();
     }
 
@@ -3123,7 +3010,7 @@ impl<'a> Parser<'a> {
                     span: lo.to(expr.span),
                     expr,
                     is_shorthand,
-                    attrs: attrs.into(),
+                    attrs,
                     id: DUMMY_NODE_ID,
                     is_placeholder: false,
                 },
@@ -3139,43 +3026,18 @@ impl<'a> Parser<'a> {
             return;
         }
 
-        self.struct_span_err(self.token.span, "expected `:`, found `=`")
-            .span_suggestion(
-                field_name.span.shrink_to_hi().to(self.token.span),
-                "replace equals symbol with a colon",
-                ":",
-                Applicability::MachineApplicable,
-            )
-            .emit();
+        self.sess.emit_err(EqFieldInit {
+            span: self.token.span,
+            eq: field_name.span.shrink_to_hi().to(self.token.span),
+        });
     }
 
     fn err_dotdotdot_syntax(&self, span: Span) {
-        self.struct_span_err(span, "unexpected token: `...`")
-            .span_suggestion(
-                span,
-                "use `..` for an exclusive range",
-                "..",
-                Applicability::MaybeIncorrect,
-            )
-            .span_suggestion(
-                span,
-                "or `..=` for an inclusive range",
-                "..=",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+        self.sess.emit_err(DotDotDot { span });
     }
 
     fn err_larrow_operator(&self, span: Span) {
-        self.struct_span_err(span, "unexpected token: `<-`")
-            .span_suggestion(
-                span,
-                "if you meant to write a comparison against a negative value, add a \
-             space in between `<` and `-`",
-                "< -",
-                Applicability::MaybeIncorrect,
-            )
-            .emit();
+        self.sess.emit_err(LeftArrowOperator { span });
     }
 
     fn mk_assign_op(&self, binop: BinOp, lhs: P<Expr>, rhs: P<Expr>) -> ExprKind {
@@ -3219,14 +3081,10 @@ impl<'a> Parser<'a> {
         await_expr
     }
 
-    pub(crate) fn mk_expr_with_attrs<A>(&self, span: Span, kind: ExprKind, attrs: A) -> P<Expr>
-    where
-        A: Into<AttrVec>,
-    {
-        P(Expr { kind, span, attrs: attrs.into(), id: DUMMY_NODE_ID, tokens: None })
+    pub(crate) fn mk_expr_with_attrs(&self, span: Span, kind: ExprKind, attrs: AttrVec) -> P<Expr> {
+        P(Expr { kind, span, attrs, id: DUMMY_NODE_ID, tokens: None })
     }
 
-    // njn: rename
     pub(crate) fn mk_expr(&self, span: Span, kind: ExprKind) -> P<Expr> {
         P(Expr { kind, span, attrs: AttrVec::new(), id: DUMMY_NODE_ID, tokens: None })
     }
@@ -3248,7 +3106,7 @@ impl<'a> Parser<'a> {
     fn collect_tokens_for_expr(
         &mut self,
         attrs: AttrWrapper,
-        f: impl FnOnce(&mut Self, Vec<ast::Attribute>) -> PResult<'a, P<Expr>>,
+        f: impl FnOnce(&mut Self, ast::AttrVec) -> PResult<'a, P<Expr>>,
     ) -> PResult<'a, P<Expr>> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             let res = f(this, attrs)?;
diff --git a/compiler/rustc_parse/src/parser/generics.rs b/compiler/rustc_parse/src/parser/generics.rs
index 5e5f2fd7d9f..4d0a8b05eb0 100644
--- a/compiler/rustc_parse/src/parser/generics.rs
+++ b/compiler/rustc_parse/src/parser/generics.rs
@@ -1,9 +1,7 @@
 use super::{ForceCollect, Parser, TrailingToken};
 
 use rustc_ast::token;
-use rustc_ast::{
-    self as ast, Attribute, GenericBounds, GenericParam, GenericParamKind, WhereClause,
-};
+use rustc_ast::{self as ast, AttrVec, GenericBounds, GenericParam, GenericParamKind, WhereClause};
 use rustc_errors::{Applicability, PResult};
 use rustc_span::symbol::kw;
 
@@ -26,7 +24,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Matches `typaram = IDENT (`?` unbound)? optbounds ( EQ ty )?`.
-    fn parse_ty_param(&mut self, preceding_attrs: Vec<Attribute>) -> PResult<'a, GenericParam> {
+    fn parse_ty_param(&mut self, preceding_attrs: AttrVec) -> PResult<'a, GenericParam> {
         let ident = self.parse_ident()?;
 
         // Parse optional colon and param bounds.
@@ -43,7 +41,7 @@ impl<'a> Parser<'a> {
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
+            attrs: preceding_attrs,
             bounds,
             kind: GenericParamKind::Type { default },
             is_placeholder: false,
@@ -53,7 +51,7 @@ impl<'a> Parser<'a> {
 
     pub(crate) fn parse_const_param(
         &mut self,
-        preceding_attrs: Vec<Attribute>,
+        preceding_attrs: AttrVec,
     ) -> PResult<'a, GenericParam> {
         let const_span = self.token.span;
 
@@ -68,7 +66,7 @@ impl<'a> Parser<'a> {
         Ok(GenericParam {
             ident,
             id: ast::DUMMY_NODE_ID,
-            attrs: preceding_attrs.into(),
+            attrs: preceding_attrs,
             bounds: Vec::new(),
             kind: GenericParamKind::Const { ty, kw_span: const_span, default },
             is_placeholder: false,
@@ -109,7 +107,7 @@ impl<'a> Parser<'a> {
                         Some(ast::GenericParam {
                             ident: lifetime.ident,
                             id: lifetime.id,
-                            attrs: attrs.into(),
+                            attrs,
                             bounds,
                             kind: ast::GenericParamKind::Lifetime,
                             is_placeholder: false,
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index f3f070e6eb0..b743162a7e4 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -32,7 +32,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a `mod <foo> { ... }` or `mod <foo>;` item.
-    fn parse_item_mod(&mut self, attrs: &mut Vec<Attribute>) -> PResult<'a, ItemInfo> {
+    fn parse_item_mod(&mut self, attrs: &mut AttrVec) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
         self.expect_keyword(kw::Mod)?;
         let id = self.parse_ident()?;
@@ -40,9 +40,9 @@ impl<'a> Parser<'a> {
             ModKind::Unloaded
         } else {
             self.expect(&token::OpenDelim(Delimiter::Brace))?;
-            let (mut inner_attrs, items, inner_span) =
+            let (inner_attrs, items, inner_span) =
                 self.parse_mod(&token::CloseDelim(Delimiter::Brace))?;
-            attrs.append(&mut inner_attrs);
+            attrs.extend(inner_attrs);
             ModKind::Loaded(items, Inline::Yes, inner_span)
         };
         Ok((id, ItemKind::Mod(unsafety, mod_kind)))
@@ -52,7 +52,7 @@ impl<'a> Parser<'a> {
     pub fn parse_mod(
         &mut self,
         term: &TokenKind,
-    ) -> PResult<'a, (Vec<Attribute>, Vec<P<Item>>, ModSpans)> {
+    ) -> PResult<'a, (AttrVec, Vec<P<Item>>, ModSpans)> {
         let lo = self.token.span;
         let attrs = self.parse_inner_attributes()?;
 
@@ -134,7 +134,7 @@ impl<'a> Parser<'a> {
 
     fn parse_item_common_(
         &mut self,
-        mut attrs: Vec<Attribute>,
+        mut attrs: AttrVec,
         mac_allowed: bool,
         attrs_allowed: bool,
         fn_parse_mode: FnParseMode,
@@ -198,7 +198,7 @@ impl<'a> Parser<'a> {
     /// Parses one of the items allowed by the flags.
     fn parse_item_kind(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         macros_allowed: bool,
         lo: Span,
         vis: &Visibility,
@@ -287,7 +287,7 @@ impl<'a> Parser<'a> {
             return Ok(None);
         } else if macros_allowed && self.check_path() {
             // MACRO INVOCATION ITEM
-            (Ident::empty(), ItemKind::MacCall(self.parse_item_macro(vis)?))
+            (Ident::empty(), ItemKind::MacCall(P(self.parse_item_macro(vis)?)))
         } else {
             return Ok(None);
         };
@@ -534,7 +534,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_item_impl(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
@@ -661,12 +661,12 @@ impl<'a> Parser<'a> {
 
     fn parse_item_list<T>(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         mut parse_item: impl FnMut(&mut Parser<'a>) -> PResult<'a, Option<Option<T>>>,
     ) -> PResult<'a, Vec<T>> {
         let open_brace_span = self.token.span;
         self.expect(&token::OpenDelim(Delimiter::Brace))?;
-        attrs.append(&mut self.parse_inner_attributes()?);
+        attrs.extend(self.parse_inner_attributes()?);
 
         let mut items = Vec::new();
         while !self.eat(&token::CloseDelim(Delimiter::Brace)) {
@@ -775,7 +775,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses `unsafe? auto? trait Foo { ... }` or `trait Foo = Bar;`.
-    fn parse_item_trait(&mut self, attrs: &mut Vec<Attribute>, lo: Span) -> PResult<'a, ItemInfo> {
+    fn parse_item_trait(&mut self, attrs: &mut AttrVec, lo: Span) -> PResult<'a, ItemInfo> {
         let unsafety = self.parse_unsafety();
         // Parse optional `auto` prefix.
         let is_auto = if self.eat_keyword(kw::Auto) { IsAuto::Yes } else { IsAuto::No };
@@ -1061,7 +1061,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_item_foreign_mod(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         mut unsafety: Unsafe,
     ) -> PResult<'a, ItemInfo> {
         let abi = self.parse_abi(); // ABI?
@@ -1179,7 +1179,7 @@ impl<'a> Parser<'a> {
     fn recover_const_impl(
         &mut self,
         const_span: Span,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         defaultness: Defaultness,
     ) -> PResult<'a, ItemInfo> {
         let impl_span = self.token.span;
@@ -1337,7 +1337,7 @@ impl<'a> Parser<'a> {
                     ident,
                     vis,
                     id: DUMMY_NODE_ID,
-                    attrs: variant_attrs.into(),
+                    attrs: variant_attrs,
                     data: struct_def,
                     disr_expr,
                     span: vlo.to(this.prev_token.span),
@@ -1494,7 +1494,7 @@ impl<'a> Parser<'a> {
                         ident: None,
                         id: DUMMY_NODE_ID,
                         ty,
-                        attrs: attrs.into(),
+                        attrs,
                         is_placeholder: false,
                     },
                     TrailingToken::MaybeComma,
@@ -1520,7 +1520,7 @@ impl<'a> Parser<'a> {
         adt_ty: &str,
         lo: Span,
         vis: Visibility,
-        attrs: Vec<Attribute>,
+        attrs: AttrVec,
     ) -> PResult<'a, FieldDef> {
         let mut seen_comma: bool = false;
         let a_var = self.parse_name_and_ty(adt_ty, lo, vis, attrs)?;
@@ -1650,7 +1650,7 @@ impl<'a> Parser<'a> {
         adt_ty: &str,
         lo: Span,
         vis: Visibility,
-        attrs: Vec<Attribute>,
+        attrs: AttrVec,
     ) -> PResult<'a, FieldDef> {
         let name = self.parse_field_ident(adt_ty, lo)?;
         self.expect_field_ty_separator()?;
@@ -1684,7 +1684,7 @@ impl<'a> Parser<'a> {
             vis,
             id: DUMMY_NODE_ID,
             ty,
-            attrs: attrs.into(),
+            attrs,
             is_placeholder: false,
         })
     }
@@ -1703,7 +1703,7 @@ impl<'a> Parser<'a> {
                 // We use `parse_fn` to get a span for the function
                 let fn_parse_mode = FnParseMode { req_name: |_| true, req_body: true };
                 if let Err(mut db) =
-                    self.parse_fn(&mut Vec::new(), fn_parse_mode, lo, &inherited_vis)
+                    self.parse_fn(&mut AttrVec::new(), fn_parse_mode, lo, &inherited_vis)
                 {
                     db.delay_as_bug();
                 }
@@ -1979,7 +1979,7 @@ impl<'a> Parser<'a> {
     /// Parse a function starting from the front matter (`const ...`) to the body `{ ... }` or `;`.
     fn parse_fn(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         fn_parse_mode: FnParseMode,
         sig_lo: Span,
         vis: &Visibility,
@@ -2002,7 +2002,7 @@ impl<'a> Parser<'a> {
     /// or e.g. a block when the function is a provided one.
     fn parse_fn_body(
         &mut self,
-        attrs: &mut Vec<Attribute>,
+        attrs: &mut AttrVec,
         ident: &Ident,
         sig_hi: &mut Span,
         req_body: bool,
@@ -2017,7 +2017,7 @@ impl<'a> Parser<'a> {
             // Include the trailing semicolon in the span of the signature
             self.expect_semi()?;
             *sig_hi = self.prev_token.span;
-            (Vec::new(), None)
+            (AttrVec::new(), None)
         } else if self.check(&token::OpenDelim(Delimiter::Brace)) || self.token.is_whole_block() {
             self.parse_inner_attrs_and_block().map(|(attrs, body)| (attrs, Some(body)))?
         } else if self.token.kind == token::Eq {
@@ -2034,7 +2034,7 @@ impl<'a> Parser<'a> {
                     Applicability::MachineApplicable,
                 )
                 .emit();
-            (Vec::new(), Some(self.mk_block_err(span)))
+            (AttrVec::new(), Some(self.mk_block_err(span)))
         } else {
             let expected = if req_body {
                 &[token::OpenDelim(Delimiter::Brace)][..]
@@ -2051,7 +2051,7 @@ impl<'a> Parser<'a> {
                     return Err(err);
                 }
             }
-            (Vec::new(), None)
+            (AttrVec::new(), None)
         };
         attrs.extend(inner_attrs);
         Ok(body)
@@ -2280,7 +2280,7 @@ impl<'a> Parser<'a> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
             // Possibly parse `self`. Recover if we parsed it and it wasn't allowed here.
             if let Some(mut param) = this.parse_self_param()? {
-                param.attrs = attrs.into();
+                param.attrs = attrs;
                 let res = if first_param { Ok(param) } else { this.recover_bad_self_param(param) };
                 return Ok((res?, TrailingToken::None));
             }
@@ -2341,14 +2341,7 @@ impl<'a> Parser<'a> {
             let span = lo.to(this.prev_token.span);
 
             Ok((
-                Param {
-                    attrs: attrs.into(),
-                    id: ast::DUMMY_NODE_ID,
-                    is_placeholder: false,
-                    pat,
-                    span,
-                    ty,
-                },
+                Param { attrs, id: ast::DUMMY_NODE_ID, is_placeholder: false, pat, span, ty },
                 TrailingToken::None,
             ))
         })
diff --git a/compiler/rustc_parse/src/parser/pat.rs b/compiler/rustc_parse/src/parser/pat.rs
index 98c974420eb..8b3200d45fc 100644
--- a/compiler/rustc_parse/src/parser/pat.rs
+++ b/compiler/rustc_parse/src/parser/pat.rs
@@ -4,8 +4,8 @@ use rustc_ast::mut_visit::{noop_visit_pat, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter};
 use rustc_ast::{
-    self as ast, Attribute, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField,
-    PatKind, Path, QSelf, RangeEnd, RangeSyntax,
+    self as ast, AttrVec, BindingMode, Expr, ExprKind, MacCall, Mutability, Pat, PatField, PatKind,
+    Path, QSelf, RangeEnd, RangeSyntax,
 };
 use rustc_ast_pretty::pprust;
 use rustc_errors::{struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, PResult};
@@ -665,7 +665,7 @@ impl<'a> Parser<'a> {
     fn parse_pat_mac_invoc(&mut self, path: Path) -> PResult<'a, PatKind> {
         self.bump();
         let args = self.parse_mac_args()?;
-        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
+        let mac = P(MacCall { path, args, prior_type_ascription: self.last_type_ascription });
         Ok(PatKind::MacCall(mac))
     }
 
@@ -1093,7 +1093,7 @@ impl<'a> Parser<'a> {
             .emit();
     }
 
-    fn parse_pat_field(&mut self, lo: Span, attrs: Vec<Attribute>) -> PResult<'a, PatField> {
+    fn parse_pat_field(&mut self, lo: Span, attrs: AttrVec) -> PResult<'a, PatField> {
         // Check if a colon exists one ahead. This means we're parsing a fieldname.
         let hi;
         let (subpat, fieldname, is_shorthand) = if self.look_ahead(1, |t| t == &token::Colon) {
@@ -1134,7 +1134,7 @@ impl<'a> Parser<'a> {
             ident: fieldname,
             pat: subpat,
             is_shorthand,
-            attrs: attrs.into(),
+            attrs,
             id: ast::DUMMY_NODE_ID,
             span: lo.to(hi),
             is_placeholder: false,
diff --git a/compiler/rustc_parse/src/parser/stmt.rs b/compiler/rustc_parse/src/parser/stmt.rs
index ade0f4fbc86..3d957406b19 100644
--- a/compiler/rustc_parse/src/parser/stmt.rs
+++ b/compiler/rustc_parse/src/parser/stmt.rs
@@ -1,5 +1,7 @@
 use super::attr::DEFAULT_INNER_ATTR_FORBIDDEN;
-use super::diagnostics::{AttemptLocalParseRecovery, Error};
+use super::diagnostics::{
+    AttemptLocalParseRecovery, Error, InvalidVariableDeclaration, InvalidVariableDeclarationSub,
+};
 use super::expr::LhsExpr;
 use super::pat::RecoverComma;
 use super::path::PathStyle;
@@ -34,7 +36,7 @@ impl<'a> Parser<'a> {
         }))
     }
 
-    /// If `force_capture` is true, forces collection of tokens regardless of whether
+    /// If `force_collect` is [`ForceCollect::Yes`], forces collection of tokens regardless of whether
     /// or not we have attributes
     pub(crate) fn parse_stmt_without_recovery(
         &mut self,
@@ -58,28 +60,22 @@ impl<'a> Parser<'a> {
         if self.token.is_keyword(kw::Mut) && self.is_keyword_ahead(1, &[kw::Let]) {
             self.bump();
             let mut_let_span = lo.to(self.token.span);
-            self.struct_span_err(mut_let_span, "invalid variable declaration")
-                .span_suggestion(
-                    mut_let_span,
-                    "switch the order of `mut` and `let`",
-                    "let mut",
-                    Applicability::MaybeIncorrect,
-                )
-                .emit();
+            self.sess.emit_err(InvalidVariableDeclaration {
+                span: mut_let_span,
+                sub: InvalidVariableDeclarationSub::SwitchMutLetOrder(mut_let_span),
+            });
         }
 
         Ok(Some(if self.token.is_keyword(kw::Let) {
             self.parse_local_mk(lo, attrs, capture_semi, force_collect)?
         } else if self.is_kw_followed_by_ident(kw::Mut) {
-            self.recover_stmt_local(lo, attrs, "missing keyword", "let mut")?
+            self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::MissingLet)?
         } else if self.is_kw_followed_by_ident(kw::Auto) {
             self.bump(); // `auto`
-            let msg = "write `let` instead of `auto` to introduce a new variable";
-            self.recover_stmt_local(lo, attrs, msg, "let")?
+            self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotAuto)?
         } else if self.is_kw_followed_by_ident(sym::var) {
             self.bump(); // `var`
-            let msg = "write `let` instead of `var` to introduce a new variable";
-            self.recover_stmt_local(lo, attrs, msg, "let")?
+            self.recover_stmt_local(lo, attrs, InvalidVariableDeclarationSub::UseLetNotVar)?
         } else if self.check_path() && !self.token.is_qpath_start() && !self.is_path_start_item() {
             // We have avoided contextual keywords like `union`, items with `crate` visibility,
             // or `auto trait` items. We aim to parse an arbitrary path `a::b` but not something
@@ -134,7 +130,7 @@ impl<'a> Parser<'a> {
             let path = this.parse_path(PathStyle::Expr)?;
 
             if this.eat(&token::Not) {
-                let stmt_mac = this.parse_stmt_mac(lo, attrs.into(), path)?;
+                let stmt_mac = this.parse_stmt_mac(lo, attrs, path)?;
                 if this.token == token::Semi {
                     return Ok((stmt_mac, TrailingToken::Semi));
                 } else {
@@ -181,7 +177,7 @@ impl<'a> Parser<'a> {
             None => unreachable!(),
         };
 
-        let mac = MacCall { path, args, prior_type_ascription: self.last_type_ascription };
+        let mac = P(MacCall { path, args, prior_type_ascription: self.last_type_ascription });
 
         let kind = if (style == MacStmtStyle::Braces
             && self.token != token::Dot
@@ -194,7 +190,7 @@ impl<'a> Parser<'a> {
             // Since none of the above applied, this is an expression statement macro.
             let e = self.mk_expr(lo.to(hi), ExprKind::MacCall(mac));
             let e = self.maybe_recover_from_bad_qpath(e)?;
-            let e = self.parse_dot_or_call_expr_with(e, lo, attrs.into())?;
+            let e = self.parse_dot_or_call_expr_with(e, lo, attrs)?;
             let e = self.parse_assoc_expr_with(0, LhsExpr::AlreadyParsed(e))?;
             StmtKind::Expr(e)
         };
@@ -217,13 +213,10 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         attrs: AttrWrapper,
-        msg: &str,
-        sugg: &str,
+        subdiagnostic: fn(Span) -> InvalidVariableDeclarationSub,
     ) -> PResult<'a, Stmt> {
         let stmt = self.recover_local_after_let(lo, attrs)?;
-        self.struct_span_err(lo, "invalid variable declaration")
-            .span_suggestion(lo, msg, sugg, Applicability::MachineApplicable)
-            .emit();
+        self.sess.emit_err(InvalidVariableDeclaration { span: lo, sub: subdiagnostic(lo) });
         Ok(stmt)
     }
 
@@ -236,7 +229,7 @@ impl<'a> Parser<'a> {
     ) -> PResult<'a, Stmt> {
         self.collect_tokens_trailing_token(attrs, force_collect, |this, attrs| {
             this.expect_keyword(kw::Let)?;
-            let local = this.parse_local(attrs.into())?;
+            let local = this.parse_local(attrs)?;
             let trailing = if capture_semi && this.token.kind == token::Semi {
                 TrailingToken::Semi
             } else {
@@ -248,7 +241,7 @@ impl<'a> Parser<'a> {
 
     fn recover_local_after_let(&mut self, lo: Span, attrs: AttrWrapper) -> PResult<'a, Stmt> {
         self.collect_tokens_trailing_token(attrs, ForceCollect::No, |this, attrs| {
-            let local = this.parse_local(attrs.into())?;
+            let local = this.parse_local(attrs)?;
             // FIXME - maybe capture semicolon in recovery?
             Ok((
                 this.mk_stmt(lo.to(this.prev_token.span), StmtKind::Local(local)),
@@ -516,9 +509,7 @@ impl<'a> Parser<'a> {
     }
 
     /// Parses a block. Inner attributes are allowed.
-    pub(super) fn parse_inner_attrs_and_block(
-        &mut self,
-    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
+    pub(super) fn parse_inner_attrs_and_block(&mut self) -> PResult<'a, (AttrVec, P<Block>)> {
         self.parse_block_common(self.token.span, BlockCheckMode::Default)
     }
 
@@ -527,8 +518,8 @@ impl<'a> Parser<'a> {
         &mut self,
         lo: Span,
         blk_mode: BlockCheckMode,
-    ) -> PResult<'a, (Vec<Attribute>, P<Block>)> {
-        maybe_whole!(self, NtBlock, |x| (Vec::new(), x));
+    ) -> PResult<'a, (AttrVec, P<Block>)> {
+        maybe_whole!(self, NtBlock, |x| (AttrVec::new(), x));
 
         self.maybe_recover_unexpected_block_label();
         if !self.eat(&token::OpenDelim(Delimiter::Brace)) {
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 31b40a83e60..4a2cf74905b 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -598,11 +598,11 @@ impl<'a> Parser<'a> {
         let path = self.parse_path_inner(PathStyle::Type, ty_generics)?;
         if self.eat(&token::Not) {
             // Macro invocation in type position
-            Ok(TyKind::MacCall(MacCall {
+            Ok(TyKind::MacCall(P(MacCall {
                 path,
                 args: self.parse_mac_args()?,
                 prior_type_ascription: self.last_type_ascription,
-            }))
+            })))
         } else if allow_plus == AllowPlus::Yes && self.check_plus() {
             // `Trait1 + Trait2 + 'a`
             self.parse_remaining_bounds_path(Vec::new(), path, lo, true)
@@ -640,7 +640,13 @@ impl<'a> Parser<'a> {
         let mut bounds = Vec::new();
         let mut negative_bounds = Vec::new();
 
-        while self.can_begin_bound() || self.token.is_keyword(kw::Dyn) {
+        while self.can_begin_bound()
+            // Continue even if we find a keyword.
+            // This is necessary for error recover on, for example, `impl fn()`.
+            //
+            // The only keyword that can go after generic bounds is `where`, so stop if it's it.
+            || (self.token.is_reserved_ident() && !self.token.is_keyword(kw::Where))
+        {
             if self.token.is_keyword(kw::Dyn) {
                 // Account for `&dyn Trait + dyn Other`.
                 self.struct_span_err(self.token.span, "invalid `dyn` keyword")
@@ -804,6 +810,20 @@ impl<'a> Parser<'a> {
             let span = tilde.to(self.prev_token.span);
             self.sess.gated_spans.gate(sym::const_trait_impl, span);
             Some(span)
+        } else if self.eat_keyword(kw::Const) {
+            let span = self.prev_token.span;
+            self.sess.gated_spans.gate(sym::const_trait_impl, span);
+
+            self.struct_span_err(span, "const bounds must start with `~`")
+                .span_suggestion(
+                    span.shrink_to_lo(),
+                    "add `~`",
+                    "~",
+                    Applicability::MachineApplicable,
+                )
+                .emit();
+
+            Some(span)
         } else {
             None
         };
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 4890fade50f..e4842d2afb7 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -9,6 +9,8 @@
     html_playground_url = "https://play.rust-lang.org/",
     test(attr(deny(warnings)))
 )]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 // We want to be able to build this crate with a stable compiler, so no
 // `#![feature]` attributes should be added.
 
diff --git a/compiler/rustc_passes/src/errors.rs b/compiler/rustc_passes/src/errors.rs
index cd465380867..383982013d9 100644
--- a/compiler/rustc_passes/src/errors.rs
+++ b/compiler/rustc_passes/src/errors.rs
@@ -3,37 +3,37 @@ use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(LintDiagnostic)]
-#[lint(passes::outer_crate_level_attr)]
+#[diag(passes::outer_crate_level_attr)]
 pub struct OuterCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inner_crate_level_attr)]
+#[diag(passes::inner_crate_level_attr)]
 pub struct InnerCrateLevelAttr;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr_with_macro)]
+#[diag(passes::ignored_attr_with_macro)]
 pub struct IgnoredAttrWithMacro<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::ignored_attr)]
+#[diag(passes::ignored_attr)]
 pub struct IgnoredAttr<'a> {
     pub sym: &'a str,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_function_prototype)]
+#[diag(passes::inline_ignored_function_prototype)]
 pub struct IgnoredInlineAttrFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::inline_ignored_constants)]
+#[diag(passes::inline_ignored_constants)]
 #[warn_]
 #[note]
 pub struct IgnoredInlineAttrConstants;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::inline_not_fn_or_closure, code = "E0518")]
+#[diag(passes::inline_not_fn_or_closure, code = "E0518")]
 pub struct InlineNotFnOrClosure {
     #[primary_span]
     pub attr_span: Span,
@@ -42,19 +42,19 @@ pub struct InlineNotFnOrClosure {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_ignored_function_prototype)]
+#[diag(passes::no_coverage_ignored_function_prototype)]
 pub struct IgnoredNoCoverageFnProto;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_propagate)]
+#[diag(passes::no_coverage_propagate)]
 pub struct IgnoredNoCoveragePropagate;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_coverage_fn_defn)]
+#[diag(passes::no_coverage_fn_defn)]
 pub struct IgnoredNoCoverageFnDefn;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_coverage_not_coverable, code = "E0788")]
+#[diag(passes::no_coverage_not_coverable, code = "E0788")]
 pub struct IgnoredNoCoverageNotCoverable {
     #[primary_span]
     pub attr_span: Span,
@@ -63,7 +63,7 @@ pub struct IgnoredNoCoverageNotCoverable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn)]
+#[diag(passes::should_be_applied_to_fn)]
 pub struct AttrShouldBeAppliedToFn {
     #[primary_span]
     pub attr_span: Span,
@@ -72,14 +72,14 @@ pub struct AttrShouldBeAppliedToFn {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::naked_tracked_caller, code = "E0736")]
+#[diag(passes::naked_tracked_caller, code = "E0736")]
 pub struct NakedTrackedCaller {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_fn, code = "E0739")]
+#[diag(passes::should_be_applied_to_fn, code = "E0739")]
 pub struct TrackedCallerWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -88,7 +88,7 @@ pub struct TrackedCallerWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_struct_enum, code = "E0701")]
+#[diag(passes::should_be_applied_to_struct_enum, code = "E0701")]
 pub struct NonExhaustiveWrongLocation {
     #[primary_span]
     pub attr_span: Span,
@@ -97,7 +97,7 @@ pub struct NonExhaustiveWrongLocation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_trait)]
+#[diag(passes::should_be_applied_to_trait)]
 pub struct AttrShouldBeAppliedToTrait {
     #[primary_span]
     pub attr_span: Span,
@@ -106,11 +106,11 @@ pub struct AttrShouldBeAppliedToTrait {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::target_feature_on_statement)]
+#[diag(passes::target_feature_on_statement)]
 pub struct TargetFeatureOnStatement;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::should_be_applied_to_static)]
+#[diag(passes::should_be_applied_to_static)]
 pub struct AttrShouldBeAppliedToStatic {
     #[primary_span]
     pub attr_span: Span,
@@ -119,7 +119,7 @@ pub struct AttrShouldBeAppliedToStatic {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_expect_str)]
+#[diag(passes::doc_expect_str)]
 pub struct DocExpectStr<'a> {
     #[primary_span]
     pub attr_span: Span,
@@ -127,7 +127,7 @@ pub struct DocExpectStr<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_empty)]
+#[diag(passes::doc_alias_empty)]
 pub struct DocAliasEmpty<'a> {
     #[primary_span]
     pub span: Span,
@@ -135,7 +135,7 @@ pub struct DocAliasEmpty<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_char)]
+#[diag(passes::doc_alias_bad_char)]
 pub struct DocAliasBadChar<'a> {
     #[primary_span]
     pub span: Span,
@@ -144,7 +144,7 @@ pub struct DocAliasBadChar<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_start_end)]
+#[diag(passes::doc_alias_start_end)]
 pub struct DocAliasStartEnd<'a> {
     #[primary_span]
     pub span: Span,
@@ -152,7 +152,7 @@ pub struct DocAliasStartEnd<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_bad_location)]
+#[diag(passes::doc_alias_bad_location)]
 pub struct DocAliasBadLocation<'a> {
     #[primary_span]
     pub span: Span,
@@ -161,7 +161,7 @@ pub struct DocAliasBadLocation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_an_alias)]
+#[diag(passes::doc_alias_not_an_alias)]
 pub struct DocAliasNotAnAlias<'a> {
     #[primary_span]
     pub span: Span,
@@ -169,42 +169,42 @@ pub struct DocAliasNotAnAlias<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_alias_duplicated)]
+#[diag(passes::doc_alias_duplicated)]
 pub struct DocAliasDuplicated {
     #[label]
     pub first_defn: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_not_string_literal)]
+#[diag(passes::doc_alias_not_string_literal)]
 pub struct DocAliasNotStringLiteral {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_alias_malformed)]
+#[diag(passes::doc_alias_malformed)]
 pub struct DocAliasMalformed {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_empty_mod)]
+#[diag(passes::doc_keyword_empty_mod)]
 pub struct DocKeywordEmptyMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_not_mod)]
+#[diag(passes::doc_keyword_not_mod)]
 pub struct DocKeywordNotMod {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_invalid_ident)]
+#[diag(passes::doc_keyword_invalid_ident)]
 pub struct DocKeywordInvalidIdent {
     #[primary_span]
     pub span: Span,
@@ -212,21 +212,21 @@ pub struct DocKeywordInvalidIdent {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_fake_variadic_not_valid)]
+#[diag(passes::doc_fake_variadic_not_valid)]
 pub struct DocFakeVariadicNotValid {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_keyword_only_impl)]
+#[diag(passes::doc_keyword_only_impl)]
 pub struct DocKeywordOnlyImpl {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_inline_conflict)]
+#[diag(passes::doc_inline_conflict)]
 #[help]
 pub struct DocKeywordConflict {
     #[primary_span]
@@ -234,7 +234,7 @@ pub struct DocKeywordConflict {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_inline_only_use)]
+#[diag(passes::doc_inline_only_use)]
 #[note]
 pub struct DocInlineOnlyUse {
     #[label]
@@ -244,7 +244,7 @@ pub struct DocInlineOnlyUse {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::doc_attr_not_crate_level)]
+#[diag(passes::doc_attr_not_crate_level)]
 pub struct DocAttrNotCrateLevel<'a> {
     #[primary_span]
     pub span: Span,
@@ -252,27 +252,27 @@ pub struct DocAttrNotCrateLevel<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown)]
+#[diag(passes::doc_test_unknown)]
 pub struct DocTestUnknown {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_takes_list)]
+#[diag(passes::doc_test_takes_list)]
 pub struct DocTestTakesList;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_primitive)]
+#[diag(passes::doc_primitive)]
 pub struct DocPrimitive;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_any)]
+#[diag(passes::doc_test_unknown_any)]
 pub struct DocTestUnknownAny {
     pub path: String,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_spotlight)]
+#[diag(passes::doc_test_unknown_spotlight)]
 #[note]
 #[note(passes::no_op_note)]
 pub struct DocTestUnknownSpotlight {
@@ -282,7 +282,7 @@ pub struct DocTestUnknownSpotlight {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_test_unknown_include)]
+#[diag(passes::doc_test_unknown_include)]
 pub struct DocTestUnknownInclude {
     pub path: String,
     pub value: String,
@@ -292,11 +292,11 @@ pub struct DocTestUnknownInclude {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::doc_invalid)]
+#[diag(passes::doc_invalid)]
 pub struct DocInvalid;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::pass_by_value)]
+#[diag(passes::pass_by_value)]
 pub struct PassByValue {
     #[primary_span]
     pub attr_span: Span,
@@ -305,7 +305,7 @@ pub struct PassByValue {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_incoherent_impl)]
+#[diag(passes::allow_incoherent_impl)]
 pub struct AllowIncoherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -314,7 +314,7 @@ pub struct AllowIncoherentImpl {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::has_incoherent_inherent_impl)]
+#[diag(passes::has_incoherent_inherent_impl)]
 pub struct HasIncoherentInherentImpl {
     #[primary_span]
     pub attr_span: Span,
@@ -323,21 +323,21 @@ pub struct HasIncoherentInherentImpl {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_async)]
+#[diag(passes::must_use_async)]
 pub struct MustUseAsync {
     #[label]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::must_use_no_effect)]
+#[diag(passes::must_use_no_effect)]
 pub struct MustUseNoEffect {
     pub article: &'static str,
     pub target: rustc_hir::Target,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::must_not_suspend)]
+#[diag(passes::must_not_suspend)]
 pub struct MustNotSuspend {
     #[primary_span]
     pub attr_span: Span,
@@ -346,7 +346,7 @@ pub struct MustNotSuspend {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::cold)]
+#[diag(passes::cold)]
 #[warn_]
 pub struct Cold {
     #[label]
@@ -354,7 +354,7 @@ pub struct Cold {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link)]
+#[diag(passes::link)]
 #[warn_]
 pub struct Link {
     #[label]
@@ -362,7 +362,7 @@ pub struct Link {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_name)]
+#[diag(passes::link_name)]
 #[warn_]
 pub struct LinkName<'a> {
     #[help]
@@ -373,7 +373,7 @@ pub struct LinkName<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::no_link)]
+#[diag(passes::no_link)]
 pub struct NoLink {
     #[primary_span]
     pub attr_span: Span,
@@ -382,7 +382,7 @@ pub struct NoLink {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::export_name)]
+#[diag(passes::export_name)]
 pub struct ExportName {
     #[primary_span]
     pub attr_span: Span,
@@ -391,7 +391,7 @@ pub struct ExportName {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_not_struct)]
+#[diag(passes::rustc_layout_scalar_valid_range_not_struct)]
 pub struct RustcLayoutScalarValidRangeNotStruct {
     #[primary_span]
     pub attr_span: Span,
@@ -400,14 +400,14 @@ pub struct RustcLayoutScalarValidRangeNotStruct {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_layout_scalar_valid_range_arg)]
+#[diag(passes::rustc_layout_scalar_valid_range_arg)]
 pub struct RustcLayoutScalarValidRangeArg {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_only)]
+#[diag(passes::rustc_legacy_const_generics_only)]
 pub struct RustcLegacyConstGenericsOnly {
     #[primary_span]
     pub attr_span: Span,
@@ -416,7 +416,7 @@ pub struct RustcLegacyConstGenericsOnly {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index)]
+#[diag(passes::rustc_legacy_const_generics_index)]
 pub struct RustcLegacyConstGenericsIndex {
     #[primary_span]
     pub attr_span: Span,
@@ -425,7 +425,7 @@ pub struct RustcLegacyConstGenericsIndex {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_exceed)]
+#[diag(passes::rustc_legacy_const_generics_index_exceed)]
 pub struct RustcLegacyConstGenericsIndexExceed {
     #[primary_span]
     #[label]
@@ -434,21 +434,21 @@ pub struct RustcLegacyConstGenericsIndexExceed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_legacy_const_generics_index_negative)]
+#[diag(passes::rustc_legacy_const_generics_index_negative)]
 pub struct RustcLegacyConstGenericsIndexNegative {
     #[primary_span]
     pub invalid_args: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_dirty_clean)]
+#[diag(passes::rustc_dirty_clean)]
 pub struct RustcDirtyClean {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::link_section)]
+#[diag(passes::link_section)]
 #[warn_]
 pub struct LinkSection {
     #[label]
@@ -456,7 +456,7 @@ pub struct LinkSection {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle_foreign)]
+#[diag(passes::no_mangle_foreign)]
 #[warn_]
 #[note]
 pub struct NoMangleForeign {
@@ -468,7 +468,7 @@ pub struct NoMangleForeign {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::no_mangle)]
+#[diag(passes::no_mangle)]
 #[warn_]
 pub struct NoMangle {
     #[label]
@@ -476,32 +476,32 @@ pub struct NoMangle {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::repr_ident, code = "E0565")]
+#[diag(passes::repr_ident, code = "E0565")]
 pub struct ReprIdent {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::repr_conflicting, code = "E0566")]
+#[diag(passes::repr_conflicting, code = "E0566")]
 pub struct ReprConflicting;
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_static)]
+#[diag(passes::used_static)]
 pub struct UsedStatic {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::used_compiler_linker)]
+#[diag(passes::used_compiler_linker)]
 pub struct UsedCompilerLinker {
     #[primary_span]
     pub spans: Vec<Span>,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::allow_internal_unstable)]
+#[diag(passes::allow_internal_unstable)]
 pub struct AllowInternalUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -510,14 +510,14 @@ pub struct AllowInternalUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_placement)]
+#[diag(passes::debug_visualizer_placement)]
 pub struct DebugVisualizerPlacement {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::debug_visualizer_invalid)]
+#[diag(passes::debug_visualizer_invalid)]
 #[note(passes::note_1)]
 #[note(passes::note_2)]
 #[note(passes::note_3)]
@@ -527,7 +527,7 @@ pub struct DebugVisualizerInvalid {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_allow_const_fn_unstable)]
+#[diag(passes::rustc_allow_const_fn_unstable)]
 pub struct RustcAllowConstFnUnstable {
     #[primary_span]
     pub attr_span: Span,
@@ -536,7 +536,7 @@ pub struct RustcAllowConstFnUnstable {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_std_internal_symbol)]
+#[diag(passes::rustc_std_internal_symbol)]
 pub struct RustcStdInternalSymbol {
     #[primary_span]
     pub attr_span: Span,
@@ -545,42 +545,42 @@ pub struct RustcStdInternalSymbol {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::const_trait)]
+#[diag(passes::const_trait)]
 pub struct ConstTrait {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::link_ordinal)]
+#[diag(passes::link_ordinal)]
 pub struct LinkOrdinal {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::stability_promotable)]
+#[diag(passes::stability_promotable)]
 pub struct StabilityPromotable {
     #[primary_span]
     pub attr_span: Span,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::deprecated)]
+#[diag(passes::deprecated)]
 pub struct Deprecated;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_use)]
+#[diag(passes::macro_use)]
 pub struct MacroUse {
     pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::macro_export)]
+#[diag(passes::macro_export)]
 pub struct MacroExport;
 
 #[derive(LintDiagnostic)]
-#[lint(passes::plugin_registrar)]
+#[diag(passes::plugin_registrar)]
 pub struct PluginRegistrar;
 
 #[derive(SessionSubdiagnostic)]
@@ -594,7 +594,7 @@ pub enum UnusedNote {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused)]
+#[diag(passes::unused)]
 pub struct Unused {
     #[suggestion(applicability = "machine-applicable")]
     pub attr_span: Span,
@@ -603,7 +603,7 @@ pub struct Unused {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::non_exported_macro_invalid_attrs, code = "E0518")]
+#[diag(passes::non_exported_macro_invalid_attrs, code = "E0518")]
 pub struct NonExportedMacroInvalidAttrs {
     #[primary_span]
     #[label]
@@ -611,9 +611,8 @@ pub struct NonExportedMacroInvalidAttrs {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(passes::unused_duplicate)]
+#[diag(passes::unused_duplicate)]
 pub struct UnusedDuplicate {
-    #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
     pub this: Span,
     #[note]
@@ -623,7 +622,7 @@ pub struct UnusedDuplicate {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::unused_multiple)]
+#[diag(passes::unused_multiple)]
 pub struct UnusedMultiple {
     #[primary_span]
     #[suggestion(code = "", applicability = "machine-applicable")]
@@ -634,7 +633,7 @@ pub struct UnusedMultiple {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_ty)]
+#[diag(passes::rustc_lint_opt_ty)]
 pub struct RustcLintOptTy {
     #[primary_span]
     pub attr_span: Span,
@@ -643,7 +642,7 @@ pub struct RustcLintOptTy {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(passes::rustc_lint_opt_deny_field_access)]
+#[diag(passes::rustc_lint_opt_deny_field_access)]
 pub struct RustcLintOptDenyFieldAccess {
     #[primary_span]
     pub attr_span: Span,
diff --git a/compiler/rustc_privacy/src/errors.rs b/compiler/rustc_privacy/src/errors.rs
index aca7d770f34..1e423ddb710 100644
--- a/compiler/rustc_privacy/src/errors.rs
+++ b/compiler/rustc_privacy/src/errors.rs
@@ -3,7 +3,7 @@ use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_span::{Span, Symbol};
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::field_is_private, code = "E0451")]
+#[diag(privacy::field_is_private, code = "E0451")]
 pub struct FieldIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -30,7 +30,7 @@ pub enum FieldIsPrivateLabel {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::item_is_private)]
+#[diag(privacy::item_is_private)]
 pub struct ItemIsPrivate<'a> {
     #[primary_span]
     #[label]
@@ -40,7 +40,7 @@ pub struct ItemIsPrivate<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(privacy::unnamed_item_is_private)]
+#[diag(privacy::unnamed_item_is_private)]
 pub struct UnnamedItemIsPrivate {
     #[primary_span]
     pub span: Span,
@@ -49,7 +49,7 @@ pub struct UnnamedItemIsPrivate {
 
 // Duplicate of `InPublicInterface` but with a different error code, shares the same slug.
 #[derive(SessionDiagnostic)]
-#[error(privacy::in_public_interface, code = "E0445")]
+#[diag(privacy::in_public_interface, code = "E0445")]
 pub struct InPublicInterfaceTraits<'a> {
     #[primary_span]
     #[label]
@@ -63,7 +63,7 @@ pub struct InPublicInterfaceTraits<'a> {
 
 // Duplicate of `InPublicInterfaceTraits` but with a different error code, shares the same slug.
 #[derive(SessionDiagnostic)]
-#[error(privacy::in_public_interface, code = "E0446")]
+#[diag(privacy::in_public_interface, code = "E0446")]
 pub struct InPublicInterface<'a> {
     #[primary_span]
     #[label]
@@ -76,7 +76,7 @@ pub struct InPublicInterface<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(privacy::from_private_dep_in_public_interface)]
+#[diag(privacy::from_private_dep_in_public_interface)]
 pub struct FromPrivateDependencyInPublicInterface<'a> {
     pub kind: &'a str,
     pub descr: DiagnosticArgFromDisplay<'a>,
@@ -84,7 +84,7 @@ pub struct FromPrivateDependencyInPublicInterface<'a> {
 }
 
 #[derive(LintDiagnostic)]
-#[lint(privacy::private_in_public_lint)]
+#[diag(privacy::private_in_public_lint)]
 pub struct PrivateInPublicLint<'a> {
     pub vis_descr: &'static str,
     pub kind: &'a str,
diff --git a/compiler/rustc_query_impl/src/lib.rs b/compiler/rustc_query_impl/src/lib.rs
index eda61df7700..df187ea0c94 100644
--- a/compiler/rustc_query_impl/src/lib.rs
+++ b/compiler/rustc_query_impl/src/lib.rs
@@ -7,6 +7,8 @@
 #![feature(rustc_attrs)]
 #![recursion_limit = "256"]
 #![allow(rustc::potential_query_instability)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
diff --git a/compiler/rustc_query_impl/src/on_disk_cache.rs b/compiler/rustc_query_impl/src/on_disk_cache.rs
index 56fd90c9855..6711dd3d5c5 100644
--- a/compiler/rustc_query_impl/src/on_disk_cache.rs
+++ b/compiler/rustc_query_impl/src/on_disk_cache.rs
@@ -22,8 +22,9 @@ use rustc_span::hygiene::{
     ExpnId, HygieneDecodeContext, HygieneEncodeContext, SyntaxContext, SyntaxContextData,
 };
 use rustc_span::source_map::{SourceMap, StableSourceFileId};
-use rustc_span::CachingSourceMapView;
 use rustc_span::{BytePos, ExpnData, ExpnHash, Pos, SourceFile, Span};
+use rustc_span::{CachingSourceMapView, Symbol};
+use std::collections::hash_map::Entry;
 use std::io;
 use std::mem;
 
@@ -38,6 +39,10 @@ const TAG_RELATIVE_SPAN: u8 = 2;
 const TAG_SYNTAX_CONTEXT: u8 = 0;
 const TAG_EXPN_DATA: u8 = 1;
 
+// Tags for encoding Symbol's
+const SYMBOL_STR: u8 = 0;
+const SYMBOL_OFFSET: u8 = 1;
+
 /// Provides an interface to incremental compilation data cached from the
 /// previous compilation session. This data will eventually include the results
 /// of a few selected queries (like `typeck` and `mir_optimized`) and
@@ -254,6 +259,7 @@ impl<'sess> rustc_middle::ty::OnDiskCache<'sess> for OnDiskCache<'sess> {
                 source_map: CachingSourceMapView::new(tcx.sess.source_map()),
                 file_to_file_index,
                 hygiene_context: &hygiene_encode_context,
+                symbol_table: Default::default(),
             };
 
             // Encode query results.
@@ -714,6 +720,36 @@ impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Span {
     }
 }
 
+// copy&paste impl from rustc_metadata
+impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for Symbol {
+    fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
+        let tag = d.read_u8();
+
+        match tag {
+            SYMBOL_STR => {
+                let s = d.read_str();
+                Symbol::intern(s)
+            }
+            SYMBOL_OFFSET => {
+                // read str offset
+                let pos = d.read_usize();
+                let old_pos = d.opaque.position();
+
+                // move to str ofset and read
+                d.opaque.set_position(pos);
+                let s = d.read_str();
+                let sym = Symbol::intern(s);
+
+                // restore position
+                d.opaque.set_position(old_pos);
+
+                sym
+            }
+            _ => unreachable!(),
+        }
+    }
+}
+
 impl<'a, 'tcx> Decodable<CacheDecoder<'a, 'tcx>> for CrateNum {
     fn decode(d: &mut CacheDecoder<'a, 'tcx>) -> Self {
         let stable_id = StableCrateId::decode(d);
@@ -815,6 +851,7 @@ pub struct CacheEncoder<'a, 'tcx> {
     source_map: CachingSourceMapView<'tcx>,
     file_to_file_index: FxHashMap<*const SourceFile, SourceFileIndex>,
     hygiene_context: &'a HygieneEncodeContext,
+    symbol_table: FxHashMap<Symbol, usize>,
 }
 
 impl<'a, 'tcx> CacheEncoder<'a, 'tcx> {
@@ -899,6 +936,25 @@ impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Span {
     }
 }
 
+// copy&paste impl from rustc_metadata
+impl<'a, 'tcx> Encodable<CacheEncoder<'a, 'tcx>> for Symbol {
+    fn encode(&self, s: &mut CacheEncoder<'a, 'tcx>) {
+        match s.symbol_table.entry(*self) {
+            Entry::Vacant(o) => {
+                s.encoder.emit_u8(SYMBOL_STR);
+                let pos = s.encoder.position();
+                o.insert(pos);
+                s.emit_str(self.as_str());
+            }
+            Entry::Occupied(o) => {
+                let x = o.get().clone();
+                s.emit_u8(SYMBOL_OFFSET);
+                s.emit_usize(x);
+            }
+        }
+    }
+}
+
 impl<'a, 'tcx> TyEncoder for CacheEncoder<'a, 'tcx> {
     type I = TyCtxt<'tcx>;
     const CLEAR_CROSS_CRATE: bool = false;
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index b89273990d8..e0d57ded5bf 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -31,7 +31,7 @@ use std::{mem, ptr};
 type Res = def::Res<NodeId>;
 
 /// Contains data for specific kinds of imports.
-#[derive(Clone, Debug)]
+#[derive(Clone)]
 pub enum ImportKind<'a> {
     Single {
         /// `source` in `use prefix::source as target`.
@@ -62,6 +62,44 @@ pub enum ImportKind<'a> {
     MacroUse,
 }
 
+/// Manually implement `Debug` for `ImportKind` because the `source/target_bindings`
+/// contain `Cell`s which can introduce infinite loops while printing.
+impl<'a> std::fmt::Debug for ImportKind<'a> {
+    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        use ImportKind::*;
+        match self {
+            Single {
+                ref source,
+                ref target,
+                ref type_ns_only,
+                ref nested,
+                ref additional_ids,
+                // Ignore the following to avoid an infinite loop while printing.
+                source_bindings: _,
+                target_bindings: _,
+            } => f
+                .debug_struct("Single")
+                .field("source", source)
+                .field("target", target)
+                .field("type_ns_only", type_ns_only)
+                .field("nested", nested)
+                .field("additional_ids", additional_ids)
+                .finish_non_exhaustive(),
+            Glob { ref is_prelude, ref max_vis } => f
+                .debug_struct("Glob")
+                .field("is_prelude", is_prelude)
+                .field("max_vis", max_vis)
+                .finish(),
+            ExternCrate { ref source, ref target } => f
+                .debug_struct("ExternCrate")
+                .field("source", source)
+                .field("target", target)
+                .finish(),
+            MacroUse => f.debug_struct("MacroUse").finish(),
+        }
+    }
+}
+
 /// One import.
 #[derive(Debug, Clone)]
 pub(crate) struct Import<'a> {
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 09c1f44826f..4175527da47 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -161,6 +161,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
             msg: String,
             fallback_label: String,
             span: Span,
+            span_label: Option<(Span, &'a str)>,
             could_be_expr: bool,
             suggestion: Option<(Span, &'a str, String)>,
         }
@@ -172,6 +173,12 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                 msg: format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
                 fallback_label: format!("not a {expected}"),
                 span,
+                span_label: match res {
+                    Res::Def(kind, def_id) if kind == DefKind::TyParam => {
+                        self.def_span(def_id).map(|span| (span, "found this type pararmeter"))
+                    }
+                    _ => None,
+                },
                 could_be_expr: match res {
                     Res::Def(DefKind::Fn, _) => {
                         // Verify whether this is a fn call or an Fn used as a type.
@@ -251,6 +258,7 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
                     format!("not found in {mod_str}")
                 },
                 span: item_span,
+                span_label: None,
                 could_be_expr: false,
                 suggestion,
             }
@@ -262,6 +270,10 @@ impl<'a: 'ast, 'ast> LateResolutionVisitor<'a, '_, 'ast> {
 
         self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);
 
+        if let Some((span, label)) = base_error.span_label {
+            err.span_label(span, label);
+        }
+
         if let Some(sugg) = base_error.suggestion {
             err.span_suggestion_verbose(sugg.0, sugg.1, sugg.2, Applicability::MaybeIncorrect);
         }
diff --git a/compiler/rustc_serialize/src/lib.rs b/compiler/rustc_serialize/src/lib.rs
index e606f427335..079d44bac68 100644
--- a/compiler/rustc_serialize/src/lib.rs
+++ b/compiler/rustc_serialize/src/lib.rs
@@ -18,6 +18,8 @@ Core encoding and decoding interfaces.
 #![feature(new_uninit)]
 #![cfg_attr(test, feature(test))]
 #![allow(rustc::internal)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 pub use self::serialize::{Decodable, Decoder, Encodable, Encoder};
 
diff --git a/compiler/rustc_serialize/src/serialize.rs b/compiler/rustc_serialize/src/serialize.rs
index 36585b8d77e..9bd5550038f 100644
--- a/compiler/rustc_serialize/src/serialize.rs
+++ b/compiler/rustc_serialize/src/serialize.rs
@@ -273,7 +273,7 @@ impl<D: Decoder, T: Decodable<D>> Decodable<D> for Vec<T> {
         unsafe {
             let ptr: *mut T = vec.as_mut_ptr();
             for i in 0..len {
-                std::ptr::write(ptr.offset(i as isize), Decodable::decode(d));
+                std::ptr::write(ptr.add(i), Decodable::decode(d));
             }
             vec.set_len(len);
         }
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index f31d52147b4..17866dc6bdd 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -2,15 +2,17 @@
 //! It also serves as an input to the parser itself.
 
 use crate::config::CheckCfg;
-use crate::lint::{BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId};
+use crate::lint::{
+    builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
+};
 use crate::SessionDiagnostic;
 use rustc_ast::node_id::NodeId;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::sync::{Lock, Lrc};
 use rustc_errors::{emitter::SilentEmitter, ColorConfig, Handler};
 use rustc_errors::{
-    error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder,
-    DiagnosticMessage, ErrorGuaranteed, MultiSpan,
+    error_code, fallback_fluent_bundle, Applicability, Diagnostic, DiagnosticBuilder, DiagnosticId,
+    DiagnosticMessage, EmissionGuarantee, ErrorGuaranteed, MultiSpan, StashKey,
 };
 use rustc_feature::{find_feature_issue, GateIssue, UnstableFeatures};
 use rustc_span::edition::Edition;
@@ -101,11 +103,58 @@ pub fn feature_err_issue<'a>(
     issue: GateIssue,
     explain: &str,
 ) -> DiagnosticBuilder<'a, ErrorGuaranteed> {
+    let span = span.into();
+
+    // Cancel an earlier warning for this same error, if it exists.
+    if let Some(span) = span.primary_span() {
+        sess.span_diagnostic
+            .steal_diagnostic(span, StashKey::EarlySyntaxWarning)
+            .map(|err| err.cancel());
+    }
+
     let mut err = sess.span_diagnostic.struct_span_err_with_code(span, explain, error_code!(E0658));
     add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
     err
 }
 
+/// Construct a future incompatibility diagnostic for a feature gate.
+///
+/// This diagnostic is only a warning and *does not cause compilation to fail*.
+pub fn feature_warn<'a>(sess: &'a ParseSess, feature: Symbol, span: Span, explain: &str) {
+    feature_warn_issue(sess, feature, span, GateIssue::Language, explain);
+}
+
+/// Construct a future incompatibility diagnostic for a feature gate.
+///
+/// This diagnostic is only a warning and *does not cause compilation to fail*.
+///
+/// This variant allows you to control whether it is a library or language feature.
+/// Almost always, you want to use this for a language feature. If so, prefer `feature_warn`.
+pub fn feature_warn_issue<'a>(
+    sess: &'a ParseSess,
+    feature: Symbol,
+    span: Span,
+    issue: GateIssue,
+    explain: &str,
+) {
+    let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
+    add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
+
+    // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
+    let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
+    let future_incompatible = lint.future_incompatible.as_ref().unwrap();
+    err.code(DiagnosticId::Lint {
+        name: lint.name_lower(),
+        has_future_breakage: false,
+        is_force_warn: false,
+    });
+    err.warn(lint.desc);
+    err.note(format!("for more information, see {}", future_incompatible.reference));
+
+    // A later feature_err call can steal and cancel this warning.
+    err.stash(span, StashKey::EarlySyntaxWarning);
+}
+
 /// Adds the diagnostics for a feature to an existing error.
 pub fn add_feature_diagnostics<'a>(err: &mut Diagnostic, sess: &'a ParseSess, feature: Symbol) {
     add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
@@ -311,6 +360,17 @@ impl ParseSess {
         self.create_warning(warning).emit()
     }
 
+    pub fn create_fatal<'a>(
+        &'a self,
+        fatal: impl SessionDiagnostic<'a, !>,
+    ) -> DiagnosticBuilder<'a, !> {
+        fatal.into_diagnostic(self)
+    }
+
+    pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+        self.create_fatal(fatal).emit()
+    }
+
     #[rustc_lint_diagnostics]
     pub fn struct_err(
         &self,
@@ -323,4 +383,17 @@ impl ParseSess {
     pub fn struct_warn(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, ()> {
         self.span_diagnostic.struct_warn(msg)
     }
+
+    #[rustc_lint_diagnostics]
+    pub fn struct_fatal(&self, msg: impl Into<DiagnosticMessage>) -> DiagnosticBuilder<'_, !> {
+        self.span_diagnostic.struct_fatal(msg)
+    }
+
+    #[rustc_lint_diagnostics]
+    pub fn struct_diagnostic<G: EmissionGuarantee>(
+        &self,
+        msg: impl Into<DiagnosticMessage>,
+    ) -> DiagnosticBuilder<'_, G> {
+        self.span_diagnostic.struct_diagnostic(msg)
+    }
 }
diff --git a/compiler/rustc_session/src/session.rs b/compiler/rustc_session/src/session.rs
index 80de451276c..4972ae2014d 100644
--- a/compiler/rustc_session/src/session.rs
+++ b/compiler/rustc_session/src/session.rs
@@ -482,6 +482,15 @@ impl Session {
     pub fn emit_warning<'a>(&'a self, warning: impl SessionDiagnostic<'a, ()>) {
         self.parse_sess.emit_warning(warning)
     }
+    pub fn create_fatal<'a>(
+        &'a self,
+        fatal: impl SessionDiagnostic<'a, !>,
+    ) -> DiagnosticBuilder<'a, !> {
+        self.parse_sess.create_fatal(fatal)
+    }
+    pub fn emit_fatal<'a>(&'a self, fatal: impl SessionDiagnostic<'a, !>) -> ! {
+        self.parse_sess.emit_fatal(fatal)
+    }
     #[inline]
     pub fn err_count(&self) -> usize {
         self.diagnostic().err_count()
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index 5c7aaf35b90..3e93c6bba97 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -11,6 +11,8 @@
     test(attr(allow(unused_variables), deny(warnings)))
 )]
 #![cfg_attr(not(feature = "default"), feature(rustc_private))]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 pub mod mir;
 
diff --git a/compiler/rustc_span/src/lib.rs b/compiler/rustc_span/src/lib.rs
index cf306928151..860af7fe93a 100644
--- a/compiler/rustc_span/src/lib.rs
+++ b/compiler/rustc_span/src/lib.rs
@@ -20,6 +20,8 @@
 #![feature(negative_impls)]
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate rustc_macros;
@@ -662,6 +664,16 @@ impl Span {
         Some(self)
     }
 
+    /// Like `find_ancestor_inside`, but specifically for when spans might not
+    /// overlaps. Take care when using this, and prefer `find_ancestor_inside`
+    /// when you know that the spans are nested (modulo macro expansion).
+    pub fn find_ancestor_in_same_ctxt(mut self, other: Span) -> Option<Span> {
+        while !Span::eq_ctxt(self, other) {
+            self = self.parent_callsite()?;
+        }
+        Some(self)
+    }
+
     /// Edition of the crate from which this span came.
     pub fn edition(self) -> edition::Edition {
         self.ctxt().edition()
@@ -1094,10 +1106,8 @@ pub enum ExternalSource {
     Unneeded,
     Foreign {
         kind: ExternalSourceKind,
-        /// This SourceFile's byte-offset within the source_map of its original crate.
-        original_start_pos: BytePos,
-        /// The end of this SourceFile within the source_map of its original crate.
-        original_end_pos: BytePos,
+        /// Index of the file inside metadata.
+        metadata_index: u32,
     },
 }
 
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index ad9f5ba85a1..5f928707ea8 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -336,7 +336,7 @@ impl SourceMap {
         mut file_local_non_narrow_chars: Vec<NonNarrowChar>,
         mut file_local_normalized_pos: Vec<NormalizedPos>,
         original_start_pos: BytePos,
-        original_end_pos: BytePos,
+        metadata_index: u32,
     ) -> Lrc<SourceFile> {
         let start_pos = self
             .allocate_address_space(source_len)
@@ -381,8 +381,7 @@ impl SourceMap {
             src_hash,
             external_src: Lock::new(ExternalSource::Foreign {
                 kind: ExternalSourceKind::AbsentOk,
-                original_start_pos,
-                original_end_pos,
+                metadata_index,
             }),
             start_pos,
             end_pos,
@@ -473,7 +472,7 @@ impl SourceMap {
         let hi = self.lookup_char_pos(sp.hi());
         let offset = self.lookup_char_pos(relative_to.lo());
 
-        if lo.file.name != offset.file.name {
+        if lo.file.name != offset.file.name || !relative_to.contains(sp) {
             return self.span_to_embeddable_string(sp);
         }
 
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index be827cea874..3058ec45a64 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -251,7 +251,7 @@ fn t10() {
         non_narrow_chars,
         normalized_pos,
         start_pos,
-        end_pos,
+        0,
     );
 
     assert!(
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 2f3519e3edd..156f53ac486 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1852,14 +1852,14 @@ impl fmt::Display for Symbol {
 }
 
 impl<S: Encoder> Encodable<S> for Symbol {
-    fn encode(&self, s: &mut S) {
+    default fn encode(&self, s: &mut S) {
         s.emit_str(self.as_str());
     }
 }
 
 impl<D: Decoder> Decodable<D> for Symbol {
     #[inline]
-    fn decode(d: &mut D) -> Symbol {
+    default fn decode(d: &mut D) -> Symbol {
         Symbol::intern(&d.read_str())
     }
 }
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 59dbea70534..9c9e297849e 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -16,6 +16,8 @@
 #![feature(never_type)]
 #![feature(rustc_attrs)]
 #![feature(step_trait)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 use std::iter::FromIterator;
 use std::path::{Path, PathBuf};
diff --git a/compiler/rustc_target/src/spec/apple_sdk_base.rs b/compiler/rustc_target/src/spec/apple_sdk_base.rs
index bf3ebaa2840..49e302676a7 100644
--- a/compiler/rustc_target/src/spec/apple_sdk_base.rs
+++ b/compiler/rustc_target/src/spec/apple_sdk_base.rs
@@ -65,7 +65,6 @@ pub fn opts(os: &'static str, arch: Arch) -> TargetOptions {
     TargetOptions {
         abi: target_abi(arch).into(),
         cpu: target_cpu(arch).into(),
-        dynamic_linking: false,
         link_env_remove: link_env_remove(arch),
         has_thread_local: false,
         ..super::apple_base::opts(os, target_arch_name(arch), target_abi(arch))
diff --git a/compiler/rustc_trait_selection/src/traits/engine.rs b/compiler/rustc_trait_selection/src/traits/engine.rs
index 6c177f63887..136b9432145 100644
--- a/compiler/rustc_trait_selection/src/traits/engine.rs
+++ b/compiler/rustc_trait_selection/src/traits/engine.rs
@@ -3,7 +3,8 @@ use std::cell::RefCell;
 use super::TraitEngine;
 use super::{ChalkFulfillmentContext, FulfillmentContext};
 use crate::infer::InferCtxtExt;
-use rustc_hir::def_id::DefId;
+use rustc_data_structures::fx::FxHashSet;
+use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::{InferCtxt, InferOk};
 use rustc_infer::traits::{
     FulfillmentError, Obligation, ObligationCause, PredicateObligation, TraitEngineExt as _,
@@ -12,6 +13,7 @@ use rustc_middle::ty::error::TypeError;
 use rustc_middle::ty::ToPredicate;
 use rustc_middle::ty::TypeFoldable;
 use rustc_middle::ty::{self, Ty, TyCtxt};
+use rustc_span::Span;
 
 pub trait TraitEngineExt<'tcx> {
     fn new(tcx: TyCtxt<'tcx>) -> Box<Self>;
@@ -109,4 +111,23 @@ impl<'a, 'tcx> ObligationCtxt<'a, 'tcx> {
     pub fn select_all_or_error(&self) -> Vec<FulfillmentError<'tcx>> {
         self.engine.borrow_mut().select_all_or_error(self.infcx)
     }
+
+    pub fn assumed_wf_types(
+        &self,
+        param_env: ty::ParamEnv<'tcx>,
+        span: Span,
+        def_id: LocalDefId,
+    ) -> FxHashSet<Ty<'tcx>> {
+        let tcx = self.infcx.tcx;
+        let assumed_wf_types = tcx.assumed_wf_types(def_id);
+        let mut implied_bounds = FxHashSet::default();
+        let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
+        let cause = ObligationCause::misc(span, hir_id);
+        for ty in assumed_wf_types {
+            implied_bounds.insert(ty);
+            let normalized = self.normalize(cause.clone(), param_env, ty);
+            implied_bounds.insert(normalized);
+        }
+        implied_bounds
+    }
 }
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index 1a39a168038..70fac83325a 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -860,8 +860,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                             }
                         }
 
-                        err.emit();
-                        return;
+                        err
                     }
 
                     ty::PredicateKind::WellFormed(ty) => {
@@ -1564,6 +1563,8 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     obligation.cause.code().peel_derives(),
                     ObligationCauseCode::ItemObligation(_)
                         | ObligationCauseCode::BindingObligation(_, _)
+                        | ObligationCauseCode::ExprItemObligation(..)
+                        | ObligationCauseCode::ExprBindingObligation(..)
                         | ObligationCauseCode::ObjectCastObligation(..)
                         | ObligationCauseCode::OpaqueType
                 );
@@ -2091,13 +2092,11 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
                     }
                 }
 
-                if let ObligationCauseCode::ItemObligation(def_id) = *obligation.cause.code() {
+                if let ObligationCauseCode::ItemObligation(def_id) | ObligationCauseCode::ExprItemObligation(def_id, ..) = *obligation.cause.code() {
                     self.suggest_fully_qualified_path(&mut err, def_id, span, trait_ref.def_id());
-                } else if let (
-                    Ok(ref snippet),
-                    &ObligationCauseCode::BindingObligation(def_id, _),
-                ) =
-                    (self.tcx.sess.source_map().span_to_snippet(span), obligation.cause.code())
+                } else if let Ok(snippet) = &self.tcx.sess.source_map().span_to_snippet(span)
+                    && let ObligationCauseCode::BindingObligation(def_id, _) | ObligationCauseCode::ExprBindingObligation(def_id, ..)
+                        = *obligation.cause.code()
                 {
                     let generics = self.tcx.generics_of(def_id);
                     if generics.params.iter().any(|p| p.name != kw::SelfUpper)
@@ -2520,15 +2519,10 @@ impl<'a, 'tcx> InferCtxtPrivExt<'a, 'tcx> for InferCtxt<'a, 'tcx> {
         err: &mut Diagnostic,
         obligation: &PredicateObligation<'tcx>,
     ) {
-        let (
-            ty::PredicateKind::Trait(pred),
-            &ObligationCauseCode::BindingObligation(item_def_id, span),
-        ) = (
-            obligation.predicate.kind().skip_binder(),
-            obligation.cause.code().peel_derives(),
-        )  else {
-            return;
-        };
+        let ty::PredicateKind::Trait(pred) = obligation.predicate.kind().skip_binder() else { return; };
+        let (ObligationCauseCode::BindingObligation(item_def_id, span)
+        | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..))
+            = *obligation.cause.code().peel_derives() else { return; };
         debug!(?pred, ?item_def_id, ?span);
 
         let (Some(node), true) = (
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
index e6907637c57..6b03555bc69 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/on_unimplemented.rs
@@ -143,7 +143,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         }
 
         if let ObligationCauseCode::ItemObligation(item)
-        | ObligationCauseCode::BindingObligation(item, _) = *obligation.cause.code()
+        | ObligationCauseCode::BindingObligation(item, _)
+        | ObligationCauseCode::ExprItemObligation(item, ..)
+        | ObligationCauseCode::ExprBindingObligation(item, ..) = *obligation.cause.code()
         {
             // FIXME: maybe also have some way of handling methods
             // from other traits? That would require name resolution,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
index 219413121d8..a93f9ec0397 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -671,11 +671,16 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         trait_pred: ty::PolyTraitPredicate<'tcx>,
     ) -> bool {
         // It only make sense when suggesting dereferences for arguments
-        let ObligationCauseCode::FunctionArgumentObligation { .. } = obligation.cause.code() else {
-            return false;
-        };
-        let param_env = obligation.param_env;
-        let body_id = obligation.cause.body_id;
+        let ObligationCauseCode::FunctionArgumentObligation { arg_hir_id, .. } = obligation.cause.code()
+            else { return false; };
+        let Some(typeck_results) = self.in_progress_typeck_results
+            else { return false; };
+        let typeck_results = typeck_results.borrow();
+        let hir::Node::Expr(expr) = self.tcx.hir().get(*arg_hir_id)
+            else { return false; };
+        let Some(arg_ty) = typeck_results.expr_ty_adjusted_opt(expr)
+            else { return false; };
+
         let span = obligation.cause.span;
         let mut real_trait_pred = trait_pred;
         let mut code = obligation.cause.code();
@@ -687,9 +692,19 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
 
             // Skipping binder here, remapping below
             let real_ty = real_trait_pred.self_ty().skip_binder();
+            if self.can_eq(obligation.param_env, real_ty, arg_ty).is_err() {
+                continue;
+            }
 
             if let ty::Ref(region, base_ty, mutbl) = *real_ty.kind() {
-                let mut autoderef = Autoderef::new(self, param_env, body_id, span, base_ty, span);
+                let mut autoderef = Autoderef::new(
+                    self,
+                    obligation.param_env,
+                    obligation.cause.body_id,
+                    span,
+                    base_ty,
+                    span,
+                );
                 if let Some(steps) = autoderef.find_map(|(ty, steps)| {
                     // Re-add the `&`
                     let ty = self.tcx.mk_ref(region, TypeAndMut { ty, mutbl });
@@ -697,24 +712,29 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     // Remapping bound vars here
                     let real_trait_pred_and_ty =
                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, ty));
-                    let obligation = self
-                        .mk_trait_obligation_with_new_self_ty(param_env, real_trait_pred_and_ty);
+                    let obligation = self.mk_trait_obligation_with_new_self_ty(
+                        obligation.param_env,
+                        real_trait_pred_and_ty,
+                    );
                     Some(steps).filter(|_| self.predicate_may_hold(&obligation))
                 }) {
                     if steps > 0 {
-                        if let Ok(src) = self.tcx.sess.source_map().span_to_snippet(span) {
-                            // Don't care about `&mut` because `DerefMut` is used less
-                            // often and user will not expect autoderef happens.
-                            if src.starts_with('&') && !src.starts_with("&mut ") {
-                                let derefs = "*".repeat(steps);
-                                err.span_suggestion(
-                                    span,
-                                    "consider dereferencing here",
-                                    format!("&{}{}", derefs, &src[1..]),
-                                    Applicability::MachineApplicable,
-                                );
-                                return true;
-                            }
+                        // Don't care about `&mut` because `DerefMut` is used less
+                        // often and user will not expect autoderef happens.
+                        if let Some(hir::Node::Expr(hir::Expr {
+                            kind:
+                                hir::ExprKind::AddrOf(hir::BorrowKind::Ref, hir::Mutability::Not, expr),
+                            ..
+                        })) = self.tcx.hir().find(*arg_hir_id)
+                        {
+                            let derefs = "*".repeat(steps);
+                            err.span_suggestion_verbose(
+                                expr.span.shrink_to_lo(),
+                                "consider dereferencing here",
+                                derefs,
+                                Applicability::MachineApplicable,
+                            );
+                            return true;
                         }
                     }
                 } else if real_trait_pred != trait_pred {
@@ -724,7 +744,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     let real_trait_pred_and_base_ty =
                         real_trait_pred.map_bound(|inner_trait_pred| (inner_trait_pred, base_ty));
                     let obligation = self.mk_trait_obligation_with_new_self_ty(
-                        param_env,
+                        obligation.param_env,
                         real_trait_pred_and_base_ty,
                     );
                     if self.predicate_may_hold(&obligation) {
@@ -852,6 +872,7 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             _ => return false,
         };
         if matches!(obligation.cause.code(), ObligationCauseCode::FunctionArgumentObligation { .. })
+            && obligation.cause.span.can_be_used_for_suggestions()
         {
             // When the obligation error has been ensured to have been caused by
             // an argument, the `obligation.cause.span` points at the expression
@@ -882,6 +903,10 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
             obligation.cause.code()
         {
             &parent_code
+        } else if let ObligationCauseCode::ItemObligation(_)
+        | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
+        {
+            obligation.cause.code()
         } else if let ExpnKind::Desugaring(DesugaringKind::ForLoop) =
             span.ctxt().outer_expn_data().kind
         {
@@ -906,102 +931,121 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
         let param_env = obligation.param_env;
 
         // Try to apply the original trait binding obligation by borrowing.
-        let mut try_borrowing =
-            |old_pred: ty::PolyTraitPredicate<'tcx>, blacklist: &[DefId]| -> bool {
-                if blacklist.contains(&old_pred.def_id()) {
-                    return false;
-                }
-                // We map bounds to `&T` and `&mut T`
-                let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
-                    (
-                        trait_pred,
-                        self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
-                    )
-                });
-                let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
+        let mut try_borrowing = |old_pred: ty::PolyTraitPredicate<'tcx>,
+                                 blacklist: &[DefId]|
+         -> bool {
+            if blacklist.contains(&old_pred.def_id()) {
+                return false;
+            }
+            // We map bounds to `&T` and `&mut T`
+            let trait_pred_and_imm_ref = old_pred.map_bound(|trait_pred| {
+                (
+                    trait_pred,
+                    self.tcx.mk_imm_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
+                )
+            });
+            let trait_pred_and_mut_ref = old_pred.map_bound(|trait_pred| {
+                (
+                    trait_pred,
+                    self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
+                )
+            });
+
+            let mk_result = |trait_pred_and_new_ty| {
+                let obligation =
+                    self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
+                self.predicate_must_hold_modulo_regions(&obligation)
+            };
+            let imm_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_imm_ref);
+            let mut_ref_self_ty_satisfies_pred = mk_result(trait_pred_and_mut_ref);
+
+            let (ref_inner_ty_satisfies_pred, ref_inner_ty_mut) =
+                if let ObligationCauseCode::ItemObligation(_) | ObligationCauseCode::ExprItemObligation(..) = obligation.cause.code()
+                    && let ty::Ref(_, ty, mutability) = old_pred.self_ty().skip_binder().kind()
+                {
                     (
-                        trait_pred,
-                        self.tcx.mk_mut_ref(self.tcx.lifetimes.re_static, trait_pred.self_ty()),
+                        mk_result(old_pred.map_bound(|trait_pred| (trait_pred, *ty))),
+                        matches!(mutability, hir::Mutability::Mut),
                     )
-                });
-
-                let mk_result = |trait_pred_and_new_ty| {
-                    let obligation =
-                        self.mk_trait_obligation_with_new_self_ty(param_env, trait_pred_and_new_ty);
-                    self.predicate_must_hold_modulo_regions(&obligation)
+                } else {
+                    (false, false)
                 };
-                let imm_result = mk_result(trait_pred_and_imm_ref);
-                let mut_result = mk_result(trait_pred_and_mut_ref);
-
-                if imm_result || mut_result {
-                    if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
-                        // We have a very specific type of error, where just borrowing this argument
-                        // might solve the problem. In cases like this, the important part is the
-                        // original type obligation, not the last one that failed, which is arbitrary.
-                        // Because of this, we modify the error to refer to the original obligation and
-                        // return early in the caller.
-
-                        let msg = format!("the trait bound `{}` is not satisfied", old_pred);
-                        if has_custom_message {
-                            err.note(&msg);
-                        } else {
-                            err.message =
-                                vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
-                        }
-                        if snippet.starts_with('&') {
-                            // This is already a literal borrow and the obligation is failing
-                            // somewhere else in the obligation chain. Do not suggest non-sense.
-                            return false;
-                        }
-                        err.span_label(
-                            span,
+
+            if imm_ref_self_ty_satisfies_pred
+                || mut_ref_self_ty_satisfies_pred
+                || ref_inner_ty_satisfies_pred
+            {
+                if let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span) {
+                    // We don't want a borrowing suggestion on the fields in structs,
+                    // ```
+                    // struct Foo {
+                    //  the_foos: Vec<Foo>
+                    // }
+                    // ```
+                    if !matches!(
+                        span.ctxt().outer_expn_data().kind,
+                        ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
+                    ) {
+                        return false;
+                    }
+                    if snippet.starts_with('&') {
+                        // This is already a literal borrow and the obligation is failing
+                        // somewhere else in the obligation chain. Do not suggest non-sense.
+                        return false;
+                    }
+                    // We have a very specific type of error, where just borrowing this argument
+                    // might solve the problem. In cases like this, the important part is the
+                    // original type obligation, not the last one that failed, which is arbitrary.
+                    // Because of this, we modify the error to refer to the original obligation and
+                    // return early in the caller.
+
+                    let msg = format!("the trait bound `{}` is not satisfied", old_pred);
+                    if has_custom_message {
+                        err.note(&msg);
+                    } else {
+                        err.message =
+                            vec![(rustc_errors::DiagnosticMessage::Str(msg), Style::NoStyle)];
+                    }
+                    err.span_label(
+                        span,
+                        format!(
+                            "the trait `{}` is not implemented for `{}`",
+                            old_pred.print_modifiers_and_trait_path(),
+                            old_pred.self_ty().skip_binder(),
+                        ),
+                    );
+
+                    if imm_ref_self_ty_satisfies_pred && mut_ref_self_ty_satisfies_pred {
+                        err.span_suggestions(
+                            span.shrink_to_lo(),
+                            "consider borrowing here",
+                            ["&".to_string(), "&mut ".to_string()].into_iter(),
+                            Applicability::MaybeIncorrect,
+                        );
+                    } else {
+                        let is_mut = mut_ref_self_ty_satisfies_pred || ref_inner_ty_mut;
+                        err.span_suggestion_verbose(
+                            span.shrink_to_lo(),
                             &format!(
-                                "expected an implementor of trait `{}`",
-                                old_pred.print_modifiers_and_trait_path(),
+                                "consider{} borrowing here",
+                                if is_mut { " mutably" } else { "" }
                             ),
+                            format!("&{}", if is_mut { "mut " } else { "" }),
+                            Applicability::MaybeIncorrect,
                         );
-
-                        // This if is to prevent a special edge-case
-                        if matches!(
-                            span.ctxt().outer_expn_data().kind,
-                            ExpnKind::Root | ExpnKind::Desugaring(DesugaringKind::ForLoop)
-                        ) {
-                            // We don't want a borrowing suggestion on the fields in structs,
-                            // ```
-                            // struct Foo {
-                            //  the_foos: Vec<Foo>
-                            // }
-                            // ```
-
-                            if imm_result && mut_result {
-                                err.span_suggestions(
-                                    span.shrink_to_lo(),
-                                    "consider borrowing here",
-                                    ["&".to_string(), "&mut ".to_string()].into_iter(),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            } else {
-                                err.span_suggestion_verbose(
-                                    span.shrink_to_lo(),
-                                    &format!(
-                                        "consider{} borrowing here",
-                                        if mut_result { " mutably" } else { "" }
-                                    ),
-                                    format!("&{}", if mut_result { "mut " } else { "" }),
-                                    Applicability::MaybeIncorrect,
-                                );
-                            }
-                        }
-                        return true;
                     }
+                    return true;
                 }
-                return false;
-            };
+            }
+            return false;
+        };
 
         if let ObligationCauseCode::ImplDerivedObligation(cause) = &*code {
             try_borrowing(cause.derived.parent_trait_pred, &[])
         } else if let ObligationCauseCode::BindingObligation(_, _)
-        | ObligationCauseCode::ItemObligation(_) = code
+        | ObligationCauseCode::ItemObligation(_)
+        | ObligationCauseCode::ExprItemObligation(..)
+        | ObligationCauseCode::ExprBindingObligation(..) = code
         {
             try_borrowing(poly_trait_pred, &never_suggest_borrow)
         } else {
@@ -2223,11 +2267,13 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                     region, object_ty,
                 ));
             }
-            ObligationCauseCode::ItemObligation(_item_def_id) => {
+            ObligationCauseCode::ItemObligation(_)
+            | ObligationCauseCode::ExprItemObligation(..) => {
                 // We hold the `DefId` of the item introducing the obligation, but displaying it
                 // doesn't add user usable information. It always point at an associated item.
             }
-            ObligationCauseCode::BindingObligation(item_def_id, span) => {
+            ObligationCauseCode::BindingObligation(item_def_id, span)
+            | ObligationCauseCode::ExprBindingObligation(item_def_id, span, ..) => {
                 let item_name = tcx.def_path_str(item_def_id);
                 let mut multispan = MultiSpan::from(span);
                 if let Some(ident) = tcx.opt_item_ident(item_def_id) {
@@ -2537,9 +2583,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                 parent_trait_pred.remap_constness_diag(param_env);
                 let parent_def_id = parent_trait_pred.def_id();
                 let msg = format!(
-                    "required because of the requirements on the impl of `{}` for `{}`",
-                    parent_trait_pred.print_modifiers_and_trait_path(),
-                    parent_trait_pred.skip_binder().self_ty()
+                    "required for `{}` to implement `{}`",
+                    parent_trait_pred.skip_binder().self_ty(),
+                    parent_trait_pred.print_modifiers_and_trait_path()
                 );
                 let mut is_auto_trait = false;
                 match self.tcx.hir().get_if_local(data.impl_def_id) {
@@ -2608,9 +2654,9 @@ impl<'a, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'a, 'tcx> {
                         pluralize!(count)
                     ));
                     err.note(&format!(
-                        "required because of the requirements on the impl of `{}` for `{}`",
-                        parent_trait_pred.print_modifiers_and_trait_path(),
-                        parent_trait_pred.skip_binder().self_ty()
+                        "required for `{}` to implement `{}`",
+                        parent_trait_pred.skip_binder().self_ty(),
+                        parent_trait_pred.print_modifiers_and_trait_path()
                     ));
                 }
                 // #74711: avoid a stack overflow
diff --git a/compiler/rustc_trait_selection/src/traits/mod.rs b/compiler/rustc_trait_selection/src/traits/mod.rs
index b6d6df1eec6..85ff6e23711 100644
--- a/compiler/rustc_trait_selection/src/traits/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/mod.rs
@@ -117,11 +117,21 @@ pub enum TraitQueryMode {
 
 /// Creates predicate obligations from the generic bounds.
 pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
+    cause: impl Fn(usize, Span) -> ObligationCause<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     generic_bounds: ty::InstantiatedPredicates<'tcx>,
 ) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    util::predicates_for_generics(cause, 0, param_env, generic_bounds)
+    let generic_bounds = generic_bounds;
+    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
+
+    std::iter::zip(generic_bounds.predicates, generic_bounds.spans).enumerate().map(
+        move |(idx, (predicate, span))| Obligation {
+            cause: cause(idx, span),
+            recursion_depth: 0,
+            param_env: param_env,
+            predicate,
+        },
+    )
 }
 
 /// Determines whether the type `ty` is known to meet `bound` and
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 74625cc7bb7..aeaccffd5f5 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -252,10 +252,20 @@ fn project_and_unify_type<'cx, 'tcx>(
         Err(InProgress) => return ProjectAndUnifyResult::Recursive,
     };
     debug!(?normalized, ?obligations, "project_and_unify_type result");
-    match infcx
-        .at(&obligation.cause, obligation.param_env)
-        .eq(normalized, obligation.predicate.term)
-    {
+    let actual = obligation.predicate.term;
+    // For an example where this is neccessary see src/test/ui/impl-trait/nested-return-type2.rs
+    // This allows users to omit re-mentioning all bounds on an associated type and just use an
+    // `impl Trait` for the assoc type to add more bounds.
+    let InferOk { value: actual, obligations: new } =
+        selcx.infcx().replace_opaque_types_with_inference_vars(
+            actual,
+            obligation.cause.body_id,
+            obligation.cause.span,
+            obligation.param_env,
+        );
+    obligations.extend(new);
+
+    match infcx.at(&obligation.cause, obligation.param_env).eq(normalized, actual) {
         Ok(InferOk { obligations: inferred_obligations, value: () }) => {
             obligations.extend(inferred_obligations);
             ProjectAndUnifyResult::Holds(obligations)
@@ -544,6 +554,18 @@ impl<'a, 'b, 'tcx> TypeFolder<'tcx> for AssocTypeNormalizer<'a, 'b, 'tcx> {
                     .flatten()
                     .unwrap_or_else(|| ty::Term::Ty(ty.super_fold_with(self)))
                 };
+                // For cases like #95134 we would like to catch overflows early
+                // otherwise they slip away away and cause ICE.
+                let recursion_limit = self.tcx().recursion_limit();
+                if !recursion_limit.value_within_limit(self.depth) {
+                    let obligation = Obligation::with_depth(
+                        self.cause.clone(),
+                        recursion_limit.0,
+                        self.param_env,
+                        ty,
+                    );
+                    self.selcx.infcx().report_overflow_error(&obligation, true);
+                }
                 debug!(
                     ?self.depth,
                     ?ty,
diff --git a/compiler/rustc_trait_selection/src/traits/util.rs b/compiler/rustc_trait_selection/src/traits/util.rs
index d2500601662..0f5dff01c66 100644
--- a/compiler/rustc_trait_selection/src/traits/util.rs
+++ b/compiler/rustc_trait_selection/src/traits/util.rs
@@ -11,8 +11,6 @@ use rustc_middle::ty::{self, ImplSubject, ToPredicate, Ty, TyCtxt, TypeVisitable
 use super::{Normalized, Obligation, ObligationCause, PredicateObligation, SelectionContext};
 pub use rustc_infer::traits::{self, util::*};
 
-use std::iter;
-
 ///////////////////////////////////////////////////////////////////////////
 // `TraitAliasExpander` iterator
 ///////////////////////////////////////////////////////////////////////////
@@ -210,7 +208,7 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     let Normalized { value: predicates, obligations: normalization_obligations2 } =
         super::normalize(selcx, param_env, ObligationCause::dummy(), predicates);
     let impl_obligations =
-        predicates_for_generics(ObligationCause::dummy(), 0, param_env, predicates);
+        super::predicates_for_generics(|_, _| ObligationCause::dummy(), param_env, predicates);
 
     let impl_obligations = impl_obligations
         .chain(normalization_obligations1.into_iter())
@@ -219,27 +217,6 @@ pub fn impl_subject_and_oblig<'a, 'tcx>(
     (subject, impl_obligations)
 }
 
-pub fn predicates_for_generics<'tcx>(
-    cause: ObligationCause<'tcx>,
-    recursion_depth: usize,
-    param_env: ty::ParamEnv<'tcx>,
-    generic_bounds: ty::InstantiatedPredicates<'tcx>,
-) -> impl Iterator<Item = PredicateObligation<'tcx>> {
-    debug!("predicates_for_generics(generic_bounds={:?})", generic_bounds);
-
-    iter::zip(generic_bounds.predicates, generic_bounds.spans).map(move |(predicate, span)| {
-        let cause = match *cause.code() {
-            traits::ItemObligation(def_id) if !span.is_dummy() => traits::ObligationCause::new(
-                cause.span,
-                cause.body_id,
-                traits::BindingObligation(def_id, span),
-            ),
-            _ => cause.clone(),
-        };
-        Obligation { cause, recursion_depth, param_env, predicate }
-    })
-}
-
 pub fn predicate_for_trait_ref<'tcx>(
     tcx: TyCtxt<'tcx>,
     cause: ObligationCause<'tcx>,
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 7a5e67ff74b..4bd179d2391 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -711,7 +711,7 @@ impl<'tcx> WfPredicates<'tcx> {
         iter::zip(iter::zip(predicates.predicates, predicates.spans), origins.into_iter().rev())
             .map(|((mut pred, span), origin_def_id)| {
                 let code = if span.is_dummy() {
-                    traits::MiscObligation
+                    traits::ItemObligation(origin_def_id)
                 } else {
                     traits::BindingObligation(origin_def_id, span)
                 };
diff --git a/compiler/rustc_traits/src/lib.rs b/compiler/rustc_traits/src/lib.rs
index 2bea164c051..318e76c79f1 100644
--- a/compiler/rustc_traits/src/lib.rs
+++ b/compiler/rustc_traits/src/lib.rs
@@ -1,6 +1,8 @@
 //! New recursive solver modeled on Chalk's recursive solver. Most of
 //! the guts are broken up into modules; see the comments in those modules.
 
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 #![feature(let_else)]
 #![recursion_limit = "256"]
 
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index cfc7c752a6b..32e6cb9c64f 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -7,6 +7,8 @@
     result_into_ok_or_err
 )]
 #![allow(dead_code, unused_variables)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate tracing;
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
new file mode 100644
index 00000000000..a77ea440aaa
--- /dev/null
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -0,0 +1,60 @@
+use crate::rustc_middle::ty::DefIdTree;
+use rustc_hir::{def::DefKind, def_id::DefId};
+use rustc_middle::ty::{self, Ty, TyCtxt};
+
+pub fn provide(providers: &mut ty::query::Providers) {
+    *providers = ty::query::Providers { assumed_wf_types, ..*providers };
+}
+
+fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> &'tcx ty::List<Ty<'tcx>> {
+    match tcx.def_kind(def_id) {
+        DefKind::Fn => {
+            let sig = tcx.fn_sig(def_id);
+            let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
+            liberated_sig.inputs_and_output
+        }
+        DefKind::AssocFn => {
+            let sig = tcx.fn_sig(def_id);
+            let liberated_sig = tcx.liberate_late_bound_regions(def_id, sig);
+            let mut assumed_wf_types: Vec<_> =
+                tcx.assumed_wf_types(tcx.parent(def_id)).as_slice().into();
+            assumed_wf_types.extend(liberated_sig.inputs_and_output);
+            tcx.intern_type_list(&assumed_wf_types)
+        }
+        DefKind::Impl => match tcx.impl_trait_ref(def_id) {
+            Some(trait_ref) => {
+                let types: Vec<_> = trait_ref.substs.types().collect();
+                tcx.intern_type_list(&types)
+            }
+            // Only the impl self type
+            None => tcx.intern_type_list(&[tcx.type_of(def_id)]),
+        },
+        DefKind::AssocConst | DefKind::AssocTy => tcx.assumed_wf_types(tcx.parent(def_id)),
+        DefKind::Mod
+        | DefKind::Struct
+        | DefKind::Union
+        | DefKind::Enum
+        | DefKind::Variant
+        | DefKind::Trait
+        | DefKind::TyAlias
+        | DefKind::ForeignTy
+        | DefKind::TraitAlias
+        | DefKind::TyParam
+        | DefKind::Const
+        | DefKind::ConstParam
+        | DefKind::Static(_)
+        | DefKind::Ctor(_, _)
+        | DefKind::Macro(_)
+        | DefKind::ExternCrate
+        | DefKind::Use
+        | DefKind::ForeignMod
+        | DefKind::AnonConst
+        | DefKind::InlineConst
+        | DefKind::OpaqueTy
+        | DefKind::Field
+        | DefKind::LifetimeParam
+        | DefKind::GlobalAsm
+        | DefKind::Closure
+        | DefKind::Generator => ty::List::empty(),
+    }
+}
diff --git a/compiler/rustc_ty_utils/src/lib.rs b/compiler/rustc_ty_utils/src/lib.rs
index 09f5c2a11aa..55d82693994 100644
--- a/compiler/rustc_ty_utils/src/lib.rs
+++ b/compiler/rustc_ty_utils/src/lib.rs
@@ -21,6 +21,7 @@ use rustc_middle::ty::query::Providers;
 mod assoc;
 mod common_traits;
 mod consts;
+mod implied_bounds;
 pub mod instance;
 mod needs_drop;
 pub mod representability;
@@ -30,6 +31,7 @@ pub fn provide(providers: &mut Providers) {
     assoc::provide(providers);
     common_traits::provide(providers);
     consts::provide(providers);
+    implied_bounds::provide(providers);
     needs_drop::provide(providers);
     ty::provide(providers);
     instance::provide(providers);
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 791e9e0f5a3..5488bca8f47 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -1,6 +1,8 @@
 #![feature(fmt_helpers_for_derive)]
 #![feature(min_specialization)]
 #![feature(rustc_attrs)]
+#![deny(rustc::untranslatable_diagnostic)]
+#![deny(rustc::diagnostic_outside_of_impl)]
 
 #[macro_use]
 extern crate bitflags;
diff --git a/compiler/rustc_typeck/src/astconv/mod.rs b/compiler/rustc_typeck/src/astconv/mod.rs
index 1e6cb53f3ee..5bb02bc246c 100644
--- a/compiler/rustc_typeck/src/astconv/mod.rs
+++ b/compiler/rustc_typeck/src/astconv/mod.rs
@@ -35,7 +35,7 @@ use rustc_session::lint::builtin::{AMBIGUOUS_ASSOCIATED_ITEMS, BARE_TRAIT_OBJECT
 use rustc_span::edition::Edition;
 use rustc_span::lev_distance::find_best_match_for_name;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{Span, DUMMY_SP};
+use rustc_span::Span;
 use rustc_target::spec::abi;
 use rustc_trait_selection::traits;
 use rustc_trait_selection::traits::astconv_object_safety_violations;
@@ -1453,21 +1453,15 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                     .enumerate()
                     .skip(1) // Remove `Self` for `ExistentialPredicate`.
                     .map(|(index, arg)| {
-                        if let ty::GenericArgKind::Type(ty) = arg.unpack() {
-                            debug!(?ty);
-                            if ty == dummy_self {
-                                let param = &generics.params[index];
-                                missing_type_params.push(param.name);
-                                tcx.ty_error().into()
-                            } else if ty.walk().any(|arg| arg == dummy_self.into()) {
-                                references_self = true;
-                                tcx.ty_error().into()
-                            } else {
-                                arg
-                            }
-                        } else {
-                            arg
+                        if arg == dummy_self.into() {
+                            let param = &generics.params[index];
+                            missing_type_params.push(param.name);
+                            return tcx.ty_error().into();
+                        } else if arg.walk().any(|arg| arg == dummy_self.into()) {
+                            references_self = true;
+                            return tcx.ty_error().into();
                         }
+                        arg
                     })
                     .collect();
                 let substs = tcx.intern_substs(&substs[..]);
@@ -1506,13 +1500,34 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
         });
 
         let existential_projections = bounds.projection_bounds.iter().map(|(bound, _)| {
-            bound.map_bound(|b| {
-                if b.projection_ty.self_ty() != dummy_self {
-                    tcx.sess.delay_span_bug(
-                        DUMMY_SP,
-                        &format!("trait_ref_to_existential called on {:?} with non-dummy Self", b),
-                    );
+            bound.map_bound(|mut b| {
+                assert_eq!(b.projection_ty.self_ty(), dummy_self);
+
+                // Like for trait refs, verify that `dummy_self` did not leak inside default type
+                // parameters.
+                let references_self = b.projection_ty.substs.iter().skip(1).any(|arg| {
+                    if arg.walk().any(|arg| arg == dummy_self.into()) {
+                        return true;
+                    }
+                    false
+                });
+                if references_self {
+                    tcx.sess
+                        .delay_span_bug(span, "trait object projection bounds reference `Self`");
+                    let substs: Vec<_> = b
+                        .projection_ty
+                        .substs
+                        .iter()
+                        .map(|arg| {
+                            if arg.walk().any(|arg| arg == dummy_self.into()) {
+                                return tcx.ty_error().into();
+                            }
+                            arg
+                        })
+                        .collect();
+                    b.projection_ty.substs = tcx.intern_substs(&substs[..]);
                 }
+
                 ty::ExistentialProjection::erase_self_ty(tcx, b)
             })
         });
diff --git a/compiler/rustc_typeck/src/check/compare_method.rs b/compiler/rustc_typeck/src/check/compare_method.rs
index ec8d22e81d1..dfef924f699 100644
--- a/compiler/rustc_typeck/src/check/compare_method.rs
+++ b/compiler/rustc_typeck/src/check/compare_method.rs
@@ -1,7 +1,6 @@
 use super::potentially_plural_count;
-use crate::check::regionck::OutlivesEnvironmentExt;
-use crate::check::wfcheck;
 use crate::errors::LifetimesOrBoundsMismatchOnTrait;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticId, ErrorGuaranteed};
 use rustc_hir as hir;
@@ -71,6 +70,72 @@ pub(crate) fn compare_impl_method<'tcx>(
     }
 }
 
+/// This function is best explained by example. Consider a trait:
+///
+///     trait Trait<'t, T> {
+///         // `trait_m`
+///         fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
+///     }
+///
+/// And an impl:
+///
+///     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+///          // `impl_m`
+///          fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
+///     }
+///
+/// We wish to decide if those two method types are compatible.
+/// For this we have to show that, assuming the bounds of the impl hold, the
+/// bounds of `trait_m` imply the bounds of `impl_m`.
+///
+/// We start out with `trait_to_impl_substs`, that maps the trait
+/// type parameters to impl type parameters. This is taken from the
+/// impl trait reference:
+///
+///     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
+///
+/// We create a mapping `dummy_substs` that maps from the impl type
+/// parameters to fresh types and regions. For type parameters,
+/// this is the identity transform, but we could as well use any
+/// placeholder types. For regions, we convert from bound to free
+/// regions (Note: but only early-bound regions, i.e., those
+/// declared on the impl or used in type parameter bounds).
+///
+///     impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
+///
+/// Now we can apply `placeholder_substs` to the type of the impl method
+/// to yield a new function type in terms of our fresh, placeholder
+/// types:
+///
+///     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
+///
+/// We now want to extract and substitute the type of the *trait*
+/// method and compare it. To do so, we must create a compound
+/// substitution by combining `trait_to_impl_substs` and
+/// `impl_to_placeholder_substs`, and also adding a mapping for the method
+/// type parameters. We extend the mapping to also include
+/// the method parameters.
+///
+///     trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
+///
+/// Applying this to the trait method type yields:
+///
+///     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
+///
+/// This type is also the same but the name of the bound region (`'a`
+/// vs `'b`).  However, the normal subtyping rules on fn types handle
+/// this kind of equivalency just fine.
+///
+/// We now use these substitutions to ensure that all declared bounds are
+/// satisfied by the implementation's method.
+///
+/// We do this by creating a parameter environment which contains a
+/// substitution corresponding to `impl_to_placeholder_substs`. We then build
+/// `trait_to_placeholder_substs` and use it to convert the predicates contained
+/// in the `trait_m` generics to the placeholder form.
+///
+/// Finally we register each of these predicates as an obligation and check that
+/// they hold.
 fn compare_predicate_entailment<'tcx>(
     tcx: TyCtxt<'tcx>,
     impl_m: &ty::AssocItem,
@@ -97,69 +162,6 @@ fn compare_predicate_entailment<'tcx>(
         },
     );
 
-    // This code is best explained by example. Consider a trait:
-    //
-    //     trait Trait<'t, T> {
-    //         fn method<'a, M>(t: &'t T, m: &'a M) -> Self;
-    //     }
-    //
-    // And an impl:
-    //
-    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
-    //          fn method<'b, N>(t: &'j &'i U, m: &'b N) -> Foo;
-    //     }
-    //
-    // We wish to decide if those two method types are compatible.
-    //
-    // We start out with trait_to_impl_substs, that maps the trait
-    // type parameters to impl type parameters. This is taken from the
-    // impl trait reference:
-    //
-    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
-    //
-    // We create a mapping `dummy_substs` that maps from the impl type
-    // parameters to fresh types and regions. For type parameters,
-    // this is the identity transform, but we could as well use any
-    // placeholder types. For regions, we convert from bound to free
-    // regions (Note: but only early-bound regions, i.e., those
-    // declared on the impl or used in type parameter bounds).
-    //
-    //     impl_to_placeholder_substs = {'i => 'i0, U => U0, N => N0 }
-    //
-    // Now we can apply placeholder_substs to the type of the impl method
-    // to yield a new function type in terms of our fresh, placeholder
-    // types:
-    //
-    //     <'b> fn(t: &'i0 U0, m: &'b) -> Foo
-    //
-    // We now want to extract and substitute the type of the *trait*
-    // method and compare it. To do so, we must create a compound
-    // substitution by combining trait_to_impl_substs and
-    // impl_to_placeholder_substs, and also adding a mapping for the method
-    // type parameters. We extend the mapping to also include
-    // the method parameters.
-    //
-    //     trait_to_placeholder_substs = { T => &'i0 U0, Self => Foo, M => N0 }
-    //
-    // Applying this to the trait method type yields:
-    //
-    //     <'a> fn(t: &'i0 U0, m: &'a) -> Foo
-    //
-    // This type is also the same but the name of the bound region ('a
-    // vs 'b).  However, the normal subtyping rules on fn types handle
-    // this kind of equivalency just fine.
-    //
-    // We now use these substitutions to ensure that all declared bounds are
-    // satisfied by the implementation's method.
-    //
-    // We do this by creating a parameter environment which contains a
-    // substitution corresponding to impl_to_placeholder_substs. We then build
-    // trait_to_placeholder_substs and use it to convert the predicates contained
-    // in the trait_m.generics to the placeholder form.
-    //
-    // Finally we register each of these predicates as an obligation in
-    // a fresh FulfillmentCtxt, and invoke select_all_or_error.
-
     // Create mapping from impl to placeholder.
     let impl_to_placeholder_substs = InternalSubsts::identity_for_item(tcx, impl_m.def_id);
 
@@ -399,8 +401,11 @@ fn compare_predicate_entailment<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(infcx, wf_tys, impl_m_hir_id);
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(infcx),
+            infcx.implied_bounds_tys(param_env, impl_m_hir_id, wf_tys),
+        );
         infcx.check_region_obligations_and_report_errors(
             impl_m.def_id.expect_local(),
             &outlives_environment,
@@ -1445,14 +1450,17 @@ pub fn check_type_bounds<'tcx>(
     };
     debug!(?normalize_param_env);
 
+    let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
     let impl_ty_substs = InternalSubsts::identity_for_item(tcx, impl_ty.def_id);
     let rebased_substs = impl_ty_substs.rebase_onto(tcx, container_id, impl_trait_ref.substs);
 
     tcx.infer_ctxt().enter(move |infcx| {
         let ocx = ObligationCtxt::new(&infcx);
 
+        let assumed_wf_types =
+            ocx.assumed_wf_types(param_env, impl_ty_span, impl_ty.def_id.expect_local());
+
         let mut selcx = traits::SelectionContext::new(&infcx);
-        let impl_ty_hir_id = tcx.hir().local_def_id_to_hir_id(impl_ty.def_id.expect_local());
         let normalize_cause = ObligationCause::new(
             impl_ty_span,
             impl_ty_hir_id,
@@ -1463,7 +1471,7 @@ pub fn check_type_bounds<'tcx>(
         );
         let mk_cause = |span: Span| {
             let code = if span.is_dummy() {
-                traits::MiscObligation
+                traits::ItemObligation(trait_ty.def_id)
             } else {
                 traits::BindingObligation(trait_ty.def_id, span)
             };
@@ -1508,17 +1516,10 @@ pub fn check_type_bounds<'tcx>(
 
         // Finally, resolve all regions. This catches wily misuses of
         // lifetime parameters.
-        let implied_bounds = match impl_ty.container {
-            ty::TraitContainer => FxHashSet::default(),
-            ty::ImplContainer => wfcheck::impl_implied_bounds(
-                tcx,
-                param_env,
-                container_id.expect_local(),
-                impl_ty_span,
-            ),
-        };
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(&infcx, implied_bounds, impl_ty_hir_id);
+        let implied_bounds = infcx.implied_bounds_tys(param_env, impl_ty_hir_id, assumed_wf_types);
+        let outlives_environment =
+            OutlivesEnvironment::with_bounds(param_env, Some(&infcx), implied_bounds);
+
         infcx.check_region_obligations_and_report_errors(
             impl_ty.def_id.expect_local(),
             &outlives_environment,
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
index 1d9d04ceec0..20d25d508d2 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/_impl.rs
@@ -607,9 +607,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     #[instrument(skip(self), level = "debug")]
     pub(in super::super) fn select_all_obligations_or_error(&self) {
-        let errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self);
+        let mut errors = self.fulfillment_cx.borrow_mut().select_all_or_error(&self);
 
         if !errors.is_empty() {
+            self.adjust_fulfillment_errors_for_expr_obligation(&mut errors);
             self.report_fulfillment_errors(&errors, self.inh.body_id, false);
         }
     }
@@ -623,6 +624,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut result = self.fulfillment_cx.borrow_mut().select_where_possible(self);
         if !result.is_empty() {
             mutate_fulfillment_errors(&mut result);
+            self.adjust_fulfillment_errors_for_expr_obligation(&mut result);
             self.report_fulfillment_errors(&result, self.inh.body_id, fallback_has_occurred);
         }
     }
@@ -820,23 +822,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let ty = item_ty.subst(self.tcx, substs);
 
         self.write_resolution(hir_id, Ok((def_kind, def_id)));
-        self.add_required_obligations_with_code(
-            span,
-            def_id,
-            &substs,
-            match lang_item {
-                hir::LangItem::IntoFutureIntoFuture => {
-                    ObligationCauseCode::AwaitableExpr(expr_hir_id)
-                }
-                hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
-                    ObligationCauseCode::ForLoopIterator
-                }
-                hir::LangItem::TryTraitFromOutput
-                | hir::LangItem::TryTraitFromResidual
-                | hir::LangItem::TryTraitBranch => ObligationCauseCode::QuestionMark,
-                _ => traits::ItemObligation(def_id),
-            },
-        );
+
+        let code = match lang_item {
+            hir::LangItem::IntoFutureIntoFuture => {
+                Some(ObligationCauseCode::AwaitableExpr(expr_hir_id))
+            }
+            hir::LangItem::IteratorNext | hir::LangItem::IntoIterIntoIter => {
+                Some(ObligationCauseCode::ForLoopIterator)
+            }
+            hir::LangItem::TryTraitFromOutput
+            | hir::LangItem::TryTraitFromResidual
+            | hir::LangItem::TryTraitBranch => Some(ObligationCauseCode::QuestionMark),
+            _ => None,
+        };
+        if let Some(code) = code {
+            self.add_required_obligations_with_code(span, def_id, substs, move |_, _| code.clone());
+        } else {
+            self.add_required_obligations_for_hir(span, def_id, substs, hir_id);
+        }
+
         (Res::Def(def_kind, def_id), ty)
     }
 
@@ -1348,7 +1352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // First, store the "user substs" for later.
         self.write_user_type_annotation_from_substs(hir_id, def_id, substs, user_self_ty);
 
-        self.add_required_obligations(span, def_id, &substs);
+        self.add_required_obligations_for_hir(span, def_id, &substs, hir_id);
 
         // Substitute the values for the type parameters into the type of
         // the referenced item.
@@ -1385,32 +1389,36 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     /// Add all the obligations that are required, substituting and normalized appropriately.
-    pub(crate) fn add_required_obligations(
+    pub(crate) fn add_required_obligations_for_hir(
         &self,
         span: Span,
         def_id: DefId,
-        substs: &SubstsRef<'tcx>,
+        substs: SubstsRef<'tcx>,
+        hir_id: hir::HirId,
     ) {
-        self.add_required_obligations_with_code(
-            span,
-            def_id,
-            substs,
-            traits::ItemObligation(def_id),
-        )
+        self.add_required_obligations_with_code(span, def_id, substs, |idx, span| {
+            if span.is_dummy() {
+                ObligationCauseCode::ExprItemObligation(def_id, hir_id, idx)
+            } else {
+                ObligationCauseCode::ExprBindingObligation(def_id, span, hir_id, idx)
+            }
+        })
     }
 
-    #[tracing::instrument(level = "debug", skip(self, span, def_id, substs))]
+    #[tracing::instrument(level = "debug", skip(self, code, span, def_id, substs))]
     fn add_required_obligations_with_code(
         &self,
         span: Span,
         def_id: DefId,
-        substs: &SubstsRef<'tcx>,
-        code: ObligationCauseCode<'tcx>,
+        substs: SubstsRef<'tcx>,
+        code: impl Fn(usize, Span) -> ObligationCauseCode<'tcx>,
     ) {
         let (bounds, _) = self.instantiate_bounds(span, def_id, &substs);
 
         for obligation in traits::predicates_for_generics(
-            traits::ObligationCause::new(span, self.body_id, code),
+            |idx, predicate_span| {
+                traits::ObligationCause::new(span, self.body_id, code(idx, predicate_span))
+            },
             self.param_env,
             bounds,
         ) {
diff --git a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
index aab60de80ef..3642b2ab03b 100644
--- a/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
+++ b/compiler/rustc_typeck/src/check/fn_ctxt/checks.rs
@@ -15,6 +15,7 @@ use crate::check::{
 use crate::structured_errors::StructuredDiagnostic;
 
 use rustc_ast as ast;
+use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::{pluralize, Applicability, Diagnostic, DiagnosticId, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Res};
@@ -27,13 +28,14 @@ use rustc_infer::infer::InferOk;
 use rustc_infer::infer::TypeTrace;
 use rustc_middle::ty::adjustment::AllowTwoPhase;
 use rustc_middle::ty::visit::TypeVisitable;
-use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty};
+use rustc_middle::ty::{self, DefIdTree, IsSuggestable, Ty, TypeSuperVisitable, TypeVisitor};
 use rustc_session::Session;
 use rustc_span::symbol::Ident;
 use rustc_span::{self, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
+use std::ops::ControlFlow;
 use std::slice;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -247,17 +249,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Cause selection errors caused by resolving a single argument to point at the
             // argument and not the call. This lets us customize the span pointed to in the
             // fulfillment error to be more accurate.
-            let coerced_ty =
-                self.resolve_vars_with_obligations_and_mutate_fulfillment(coerced_ty, |errors| {
-                    self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
-                    self.point_at_arg_instead_of_call_if_possible(
-                        errors,
-                        call_expr,
-                        call_span,
-                        provided_args,
-                        &expected_input_tys,
-                    );
-                });
+            let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
 
             let coerce_error = self
                 .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
@@ -312,16 +304,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // an "opportunistic" trait resolution of any trait bounds on
             // the call. This helps coercions.
             if check_closures {
-                self.select_obligations_where_possible(false, |errors| {
-                    self.point_at_type_arg_instead_of_call_if_possible(errors, call_expr);
-                    self.point_at_arg_instead_of_call_if_possible(
-                        errors,
-                        call_expr,
-                        call_span,
-                        &provided_args,
-                        &expected_input_tys,
-                    );
-                })
+                self.select_obligations_where_possible(false, |_| {})
             }
 
             // Check each argument, to satisfy the input it was provided for
@@ -674,7 +657,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             Applicability::MachineApplicable,
                         );
                     };
-                    self.label_fn_like(&mut err, fn_def_id, callee_ty, Some(mismatch_idx), is_method);
+                    self.label_fn_like(
+                        &mut err,
+                        fn_def_id,
+                        callee_ty,
+                        Some(mismatch_idx),
+                        is_method,
+                    );
                     err.emit();
                     return;
                 }
@@ -1081,8 +1070,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
                 let suggestion_text = if let Some(provided_idx) = provided_idx
                     && let (_, provided_span) = provided_arg_tys[*provided_idx]
-                    && let Ok(arg_text) =
-                        source_map.span_to_snippet(provided_span)
+                    && let Ok(arg_text) = source_map.span_to_snippet(provided_span)
                 {
                     arg_text
                 } else {
@@ -1183,7 +1171,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             self.write_user_type_annotation_from_substs(hir_id, did, substs, None);
 
             // Check bounds on type arguments used in the path.
-            self.add_required_obligations(path_span, did, substs);
+            self.add_required_obligations_for_hir(path_span, did, substs, hir_id);
 
             Some((variant, ty))
         } else {
@@ -1620,183 +1608,406 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    /// Given a vec of evaluated `FulfillmentError`s and an `fn` call argument expressions, we walk
-    /// the checked and coerced types for each argument to see if any of the `FulfillmentError`s
-    /// reference a type argument. The reason to walk also the checked type is that the coerced type
-    /// can be not easily comparable with predicate type (because of coercion). If the types match
-    /// for either checked or coerced type, and there's only *one* argument that does, we point at
-    /// the corresponding argument's expression span instead of the `fn` call path span.
-    fn point_at_arg_instead_of_call_if_possible(
+    /// Given a vector of fulfillment errors, try to adjust the spans of the
+    /// errors to more accurately point at the cause of the failure.
+    ///
+    /// This applies to calls, methods, and struct expressions. This will also
+    /// try to deduplicate errors that are due to the same cause but might
+    /// have been created with different [`ObligationCause`][traits::ObligationCause]s.
+    pub(super) fn adjust_fulfillment_errors_for_expr_obligation(
         &self,
         errors: &mut Vec<traits::FulfillmentError<'tcx>>,
-        expr: &'tcx hir::Expr<'tcx>,
-        call_sp: Span,
-        args: &'tcx [hir::Expr<'tcx>],
-        expected_tys: &[Ty<'tcx>],
     ) {
-        // We *do not* do this for desugared call spans to keep good diagnostics when involving
-        // the `?` operator.
-        if call_sp.desugaring_kind().is_some() {
-            return;
+        // Store a mapping from `(Span, Predicate) -> ObligationCause`, so that
+        // other errors that have the same span and predicate can also get fixed,
+        // even if their `ObligationCauseCode` isn't an `Expr*Obligation` kind.
+        // This is important since if we adjust one span but not the other, then
+        // we will have "duplicated" the error on the UI side.
+        let mut remap_cause = FxHashSet::default();
+        let mut not_adjusted = vec![];
+
+        for error in errors {
+            let before_span = error.obligation.cause.span;
+            if self.adjust_fulfillment_error_for_expr_obligation(error)
+                || before_span != error.obligation.cause.span
+            {
+                // Store both the predicate and the predicate *without constness*
+                // since sometimes we instantiate and check both of these in a
+                // method call, for example.
+                remap_cause.insert((
+                    before_span,
+                    error.obligation.predicate,
+                    error.obligation.cause.clone(),
+                ));
+                remap_cause.insert((
+                    before_span,
+                    error.obligation.predicate.without_const(self.tcx),
+                    error.obligation.cause.clone(),
+                ));
+            } else {
+                // If it failed to be adjusted once around, it may be adjusted
+                // via the "remap cause" mapping the second time...
+                not_adjusted.push(error);
+            }
         }
 
-        'outer: for error in errors {
-            // Only if the cause is somewhere inside the expression we want try to point at arg.
-            // Otherwise, it means that the cause is somewhere else and we should not change
-            // anything because we can break the correct span.
-            if !call_sp.contains(error.obligation.cause.span) {
-                continue;
+        for error in not_adjusted {
+            for (span, predicate, cause) in &remap_cause {
+                if *predicate == error.obligation.predicate
+                    && span.contains(error.obligation.cause.span)
+                {
+                    error.obligation.cause = cause.clone();
+                    continue;
+                }
             }
+        }
+    }
 
-            // Peel derived obligation, because it's the type that originally
-            // started this inference chain that matters, not the one we wound
-            // up with at the end.
-            fn unpeel_to_top<'a, 'tcx>(
-                mut code: &'a ObligationCauseCode<'tcx>,
-            ) -> &'a ObligationCauseCode<'tcx> {
-                let mut result_code = code;
-                loop {
-                    let parent = match code {
-                        ObligationCauseCode::ImplDerivedObligation(c) => &c.derived.parent_code,
-                        ObligationCauseCode::BuiltinDerivedObligation(c)
-                        | ObligationCauseCode::DerivedObligation(c) => &c.parent_code,
-                        _ => break result_code,
-                    };
-                    (result_code, code) = (code, parent);
+    fn adjust_fulfillment_error_for_expr_obligation(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+    ) -> bool {
+        let (traits::ExprItemObligation(def_id, hir_id, idx) | traits::ExprBindingObligation(def_id, _, hir_id, idx))
+            = *error.obligation.cause.code().peel_derives() else { return false; };
+        let hir = self.tcx.hir();
+        let hir::Node::Expr(expr) = hir.get(hir_id) else { return false; };
+
+        // Skip over mentioning async lang item
+        if Some(def_id) == self.tcx.lang_items().from_generator_fn()
+            && error.obligation.cause.span.desugaring_kind()
+                == Some(rustc_span::DesugaringKind::Async)
+        {
+            return false;
+        }
+
+        let Some(unsubstituted_pred) =
+            self.tcx.predicates_of(def_id).instantiate_identity(self.tcx).predicates.into_iter().nth(idx)
+            else { return false; };
+
+        let generics = self.tcx.generics_of(def_id);
+        let predicate_substs = match unsubstituted_pred.kind().skip_binder() {
+            ty::PredicateKind::Trait(pred) => pred.trait_ref.substs,
+            ty::PredicateKind::Projection(pred) => pred.projection_ty.substs,
+            _ => ty::List::empty(),
+        };
+
+        let find_param_matching = |matches: &dyn Fn(&ty::ParamTy) -> bool| {
+            predicate_substs.types().find_map(|ty| {
+                ty.walk().find_map(|arg| {
+                    if let ty::GenericArgKind::Type(ty) = arg.unpack()
+                        && let ty::Param(param_ty) = ty.kind()
+                        && matches(param_ty)
+                    {
+                        Some(arg)
+                    } else {
+                        None
+                    }
+                })
+            })
+        };
+
+        // Prefer generics that are local to the fn item, since these are likely
+        // to be the cause of the unsatisfied predicate.
+        let mut param_to_point_at = find_param_matching(&|param_ty| {
+            self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) == def_id
+        });
+        // Fall back to generic that isn't local to the fn item. This will come
+        // from a trait or impl, for example.
+        let mut fallback_param_to_point_at = find_param_matching(&|param_ty| {
+            self.tcx.parent(generics.type_param(param_ty, self.tcx).def_id) != def_id
+                && param_ty.name != rustc_span::symbol::kw::SelfUpper
+        });
+        // Finally, the `Self` parameter is possibly the reason that the predicate
+        // is unsatisfied. This is less likely to be true for methods, because
+        // method probe means that we already kinda check that the predicates due
+        // to the `Self` type are true.
+        let mut self_param_to_point_at =
+            find_param_matching(&|param_ty| param_ty.name == rustc_span::symbol::kw::SelfUpper);
+
+        // Finally, for ambiguity-related errors, we actually want to look
+        // for a parameter that is the source of the inference type left
+        // over in this predicate.
+        if let traits::FulfillmentErrorCode::CodeAmbiguity = error.code {
+            fallback_param_to_point_at = None;
+            self_param_to_point_at = None;
+            param_to_point_at =
+                self.find_ambiguous_parameter_in(def_id, error.root_obligation.predicate);
+        }
+
+        if self.closure_span_overlaps_error(error, expr.span) {
+            return false;
+        }
+
+        match &expr.kind {
+            hir::ExprKind::Path(qpath) => {
+                if let hir::Node::Expr(hir::Expr {
+                    kind: hir::ExprKind::Call(callee, args),
+                    hir_id: call_hir_id,
+                    span: call_span,
+                    ..
+                }) = hir.get(hir.get_parent_node(expr.hir_id))
+                    && callee.hir_id == expr.hir_id
+                {
+                    if self.closure_span_overlaps_error(error, *call_span) {
+                        return false;
+                    }
+
+                    for param in
+                        [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                        .into_iter()
+                        .flatten()
+                    {
+                        if self.point_at_arg_if_possible(
+                                error,
+                                def_id,
+                                param,
+                                *call_hir_id,
+                                callee.span,
+                                args,
+                            )
+                        {
+                            return true;
+                        }
+                    }
+                    // Notably, we only point to params that are local to the
+                    // item we're checking, since those are the ones we are able
+                    // to look in the final `hir::PathSegment` for. Everything else
+                    // would require a deeper search into the `qpath` than I think
+                    // is worthwhile.
+                    if let Some(param_to_point_at) = param_to_point_at
+                        && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+                    {
+                        return true;
+                    }
                 }
             }
-            let self_: ty::subst::GenericArg<'_> =
-                match unpeel_to_top(error.obligation.cause.code()) {
-                    ObligationCauseCode::BuiltinDerivedObligation(code)
-                    | ObligationCauseCode::DerivedObligation(code) => {
-                        code.parent_trait_pred.self_ty().skip_binder().into()
-                    }
-                    ObligationCauseCode::ImplDerivedObligation(code) => {
-                        code.derived.parent_trait_pred.self_ty().skip_binder().into()
+            hir::ExprKind::MethodCall(segment, args, ..) => {
+                for param in [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                    .into_iter()
+                    .flatten()
+                {
+                    if self.point_at_arg_if_possible(
+                        error,
+                        def_id,
+                        param,
+                        hir_id,
+                        segment.ident.span,
+                        args,
+                    ) {
+                        return true;
                     }
-                    _ => match error.obligation.predicate.kind().skip_binder() {
-                        ty::PredicateKind::Trait(predicate) => predicate.self_ty().into(),
-                        ty::PredicateKind::Projection(predicate) => {
-                            predicate.projection_ty.self_ty().into()
+                }
+                if let Some(param_to_point_at) = param_to_point_at
+                    && self.point_at_generic_if_possible(error, def_id, param_to_point_at, segment)
+                {
+                    return true;
+                }
+            }
+            hir::ExprKind::Struct(qpath, fields, ..) => {
+                if let Res::Def(DefKind::Struct | DefKind::Variant, variant_def_id) =
+                    self.typeck_results.borrow().qpath_res(qpath, hir_id)
+                {
+                    for param in
+                        [param_to_point_at, fallback_param_to_point_at, self_param_to_point_at]
+                    {
+                        if let Some(param) = param
+                            && self.point_at_field_if_possible(
+                                error,
+                                def_id,
+                                param,
+                                variant_def_id,
+                                fields,
+                            )
+                        {
+                            return true;
                         }
-                        _ => continue,
-                    },
-                };
-            let self_ = self.resolve_vars_if_possible(self_);
-            let ty_matches_self = |ty: Ty<'tcx>| ty.walk().any(|arg| arg == self_);
-
-            let typeck_results = self.typeck_results.borrow();
-
-            for (idx, arg) in args.iter().enumerate() {
-                // Don't adjust the span if we already have a more precise span
-                // within one of the args.
-                if arg.span.contains(error.obligation.cause.span) {
-                    let references_arg =
-                        typeck_results.expr_ty_opt(arg).map_or(false, &ty_matches_self)
-                            || expected_tys.get(idx).copied().map_or(false, &ty_matches_self);
-                    if references_arg && !arg.span.from_expansion() {
-                        error.obligation.cause.map_code(|parent_code| {
-                            ObligationCauseCode::FunctionArgumentObligation {
-                                arg_hir_id: args[idx].hir_id,
-                                call_hir_id: expr.hir_id,
-                                parent_code,
-                            }
-                        })
                     }
-                    continue 'outer;
+                }
+                if let Some(param_to_point_at) = param_to_point_at
+                    && self.point_at_path_if_possible(error, def_id, param_to_point_at, qpath)
+                {
+                    return true;
                 }
             }
+            _ => {}
+        }
 
-            // Collect the argument position for all arguments that could have caused this
-            // `FulfillmentError`.
-            let mut referenced_in: Vec<_> = std::iter::zip(expected_tys, args)
-                .enumerate()
-                .flat_map(|(idx, (expected_ty, arg))| {
-                    if let Some(arg_ty) = typeck_results.expr_ty_opt(arg) {
-                        vec![(idx, arg_ty), (idx, *expected_ty)]
-                    } else {
-                        vec![]
-                    }
-                })
-                .filter_map(|(i, ty)| {
-                    let ty = self.resolve_vars_if_possible(ty);
-                    // We walk the argument type because the argument's type could have
-                    // been `Option<T>`, but the `FulfillmentError` references `T`.
-                    if ty_matches_self(ty) { Some(i) } else { None }
-                })
-                .collect();
+        false
+    }
 
-            // Both checked and coerced types could have matched, thus we need to remove
-            // duplicates.
+    fn closure_span_overlaps_error(
+        &self,
+        error: &traits::FulfillmentError<'tcx>,
+        span: Span,
+    ) -> bool {
+        if let traits::FulfillmentErrorCode::CodeSelectionError(
+            traits::SelectionError::OutputTypeParameterMismatch(_, expected, _),
+        ) = error.code
+            && let ty::Closure(def_id, _) | ty::Generator(def_id, ..) = expected.skip_binder().self_ty().kind()
+            && span.overlaps(self.tcx.def_span(*def_id))
+        {
+            true
+        } else {
+            false
+        }
+    }
 
-            // We sort primitive type usize here and can use unstable sort
-            referenced_in.sort_unstable();
-            referenced_in.dedup();
+    fn point_at_arg_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        call_hir_id: hir::HirId,
+        callee_span: Span,
+        args: &[hir::Expr<'tcx>],
+    ) -> bool {
+        let sig = self.tcx.fn_sig(def_id).skip_binder();
+        let args_referencing_param: Vec<_> = sig
+            .inputs()
+            .iter()
+            .enumerate()
+            .filter(|(_, ty)| find_param_in_ty(**ty, param_to_point_at))
+            .collect();
 
-            if let &[idx] = &referenced_in[..] {
-                // Do not point at the inside of a macro.
-                // That would often result in poor error messages.
-                if args[idx].span.from_expansion() {
-                    continue;
+        // If there's one field that references the given generic, great!
+        if let [(idx, _)] = args_referencing_param.as_slice() && let Some(arg) = args.get(*idx) {
+            error.obligation.cause.span = arg.span.find_ancestor_in_same_ctxt(error.obligation.cause.span).unwrap_or(arg.span);
+            error.obligation.cause.map_code(|parent_code| {
+                ObligationCauseCode::FunctionArgumentObligation {
+                    arg_hir_id: arg.hir_id,
+                    call_hir_id,
+                    parent_code,
                 }
-                // We make sure that only *one* argument matches the obligation failure
-                // and we assign the obligation's span to its expression's.
-                error.obligation.cause.span = args[idx].span;
-                error.obligation.cause.map_code(|parent_code| {
-                    ObligationCauseCode::FunctionArgumentObligation {
-                        arg_hir_id: args[idx].hir_id,
-                        call_hir_id: expr.hir_id,
-                        parent_code,
-                    }
-                });
-            } else if error.obligation.cause.span == call_sp {
-                // Make function calls point at the callee, not the whole thing.
-                if let hir::ExprKind::Call(callee, _) = expr.kind {
-                    error.obligation.cause.span = callee.span;
+            });
+            return true;
+        } else if args_referencing_param.len() > 0 {
+            // If more than one argument applies, then point to the callee span at least...
+            // We have chance to fix this up further in `point_at_generics_if_possible`
+            error.obligation.cause.span = callee_span;
+        }
+
+        false
+    }
+
+    fn point_at_field_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        variant_def_id: DefId,
+        expr_fields: &[hir::ExprField<'tcx>],
+    ) -> bool {
+        let def = self.tcx.adt_def(def_id);
+
+        let identity_substs = ty::InternalSubsts::identity_for_item(self.tcx, def_id);
+        let fields_referencing_param: Vec<_> = def
+            .variant_with_id(variant_def_id)
+            .fields
+            .iter()
+            .filter(|field| {
+                let field_ty = field.ty(self.tcx, identity_substs);
+                find_param_in_ty(field_ty, param_to_point_at)
+            })
+            .collect();
+
+        if let [field] = fields_referencing_param.as_slice() {
+            for expr_field in expr_fields {
+                // Look for the ExprField that matches the field, using the
+                // same rules that check_expr_struct uses for macro hygiene.
+                if self.tcx.adjust_ident(expr_field.ident, variant_def_id) == field.ident(self.tcx)
+                {
+                    error.obligation.cause.span = expr_field
+                        .expr
+                        .span
+                        .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+                        .unwrap_or(expr_field.span);
+                    return true;
                 }
             }
         }
+
+        false
     }
 
-    /// Given a vec of evaluated `FulfillmentError`s and an `fn` call expression, we walk the
-    /// `PathSegment`s and resolve their type parameters to see if any of the `FulfillmentError`s
-    /// were caused by them. If they were, we point at the corresponding type argument's span
-    /// instead of the `fn` call path span.
-    fn point_at_type_arg_instead_of_call_if_possible(
+    fn point_at_path_if_possible(
         &self,
-        errors: &mut Vec<traits::FulfillmentError<'tcx>>,
-        call_expr: &'tcx hir::Expr<'tcx>,
-    ) {
-        if let hir::ExprKind::Call(path, _) = &call_expr.kind {
-            if let hir::ExprKind::Path(hir::QPath::Resolved(_, path)) = &path.kind {
-                for error in errors {
-                    let self_ty = match error.obligation.predicate.kind().skip_binder() {
-                        ty::PredicateKind::Trait(predicate) => predicate.self_ty(),
-                        ty::PredicateKind::Projection(predicate) => {
-                            predicate.projection_ty.self_ty()
-                        }
-                        _ => continue,
-                    };
-                    // If any of the type arguments in this path segment caused the
-                    // `FulfillmentError`, point at its span (#61860).
-                    for arg in path
-                        .segments
-                        .iter()
-                        .filter_map(|seg| seg.args.as_ref())
-                        .flat_map(|a| a.args.iter())
-                    {
-                        if let hir::GenericArg::Type(hir_ty) = &arg
-                            && let Some(ty) =
-                                self.typeck_results.borrow().node_type_opt(hir_ty.hir_id)
-                            && self.resolve_vars_if_possible(ty) == self_ty
-                        {
-                            error.obligation.cause.span = hir_ty.span;
-                            break;
-                        }
-                    }
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param: ty::GenericArg<'tcx>,
+        qpath: &QPath<'tcx>,
+    ) -> bool {
+        match qpath {
+            hir::QPath::Resolved(_, path) => {
+                if let Some(segment) = path.segments.last()
+                    && self.point_at_generic_if_possible(error, def_id, param, segment)
+                {
+                    return true;
+                }
+            }
+            hir::QPath::TypeRelative(_, segment) => {
+                if self.point_at_generic_if_possible(error, def_id, param, segment) {
+                    return true;
+                }
+            }
+            _ => {}
+        }
+
+        false
+    }
+
+    fn point_at_generic_if_possible(
+        &self,
+        error: &mut traits::FulfillmentError<'tcx>,
+        def_id: DefId,
+        param_to_point_at: ty::GenericArg<'tcx>,
+        segment: &hir::PathSegment<'tcx>,
+    ) -> bool {
+        let own_substs = self
+            .tcx
+            .generics_of(def_id)
+            .own_substs(ty::InternalSubsts::identity_for_item(self.tcx, def_id));
+        let Some((index, _)) = own_substs
+            .iter()
+            .filter(|arg| matches!(arg.unpack(), ty::GenericArgKind::Type(_)))
+            .enumerate()
+            .find(|(_, arg)| **arg == param_to_point_at) else { return false };
+        let Some(arg) = segment
+            .args()
+            .args
+            .iter()
+            .filter(|arg| matches!(arg, hir::GenericArg::Type(_)))
+            .nth(index) else { return false; };
+        error.obligation.cause.span = arg
+            .span()
+            .find_ancestor_in_same_ctxt(error.obligation.cause.span)
+            .unwrap_or(arg.span());
+        true
+    }
+
+    fn find_ambiguous_parameter_in<T: TypeVisitable<'tcx>>(
+        &self,
+        item_def_id: DefId,
+        t: T,
+    ) -> Option<ty::GenericArg<'tcx>> {
+        struct FindAmbiguousParameter<'a, 'tcx>(&'a FnCtxt<'a, 'tcx>, DefId);
+        impl<'tcx> TypeVisitor<'tcx> for FindAmbiguousParameter<'_, 'tcx> {
+            type BreakTy = ty::GenericArg<'tcx>;
+            fn visit_ty(&mut self, ty: Ty<'tcx>) -> std::ops::ControlFlow<Self::BreakTy> {
+                if let Some(origin) = self.0.type_var_origin(ty)
+                    && let TypeVariableOriginKind::TypeParameterDefinition(_, Some(def_id)) =
+                        origin.kind
+                    && let generics = self.0.tcx.generics_of(self.1)
+                    && let Some(index) = generics.param_def_id_to_index(self.0.tcx, def_id)
+                    && let Some(subst) = ty::InternalSubsts::identity_for_item(self.0.tcx, self.1)
+                        .get(index as usize)
+                {
+                    ControlFlow::Break(*subst)
+                } else {
+                    ty.super_visit_with(self)
                 }
             }
         }
+        t.visit_with(&mut FindAmbiguousParameter(self, item_def_id)).break_value()
     }
 
     fn label_fn_like(
@@ -1864,14 +2075,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let new_def_id = self.probe(|_| {
                         let trait_ref = ty::TraitRef::new(
                             call_kind.to_def_id(self.tcx),
-                            self.tcx.mk_substs([
-                                ty::GenericArg::from(callee_ty),
-                                self.next_ty_var(TypeVariableOrigin {
-                                    kind: TypeVariableOriginKind::MiscVariable,
-                                    span: rustc_span::DUMMY_SP,
-                                })
-                                .into(),
-                            ].into_iter()),
+                            self.tcx.mk_substs(
+                                [
+                                    ty::GenericArg::from(callee_ty),
+                                    self.next_ty_var(TypeVariableOrigin {
+                                        kind: TypeVariableOriginKind::MiscVariable,
+                                        span: rustc_span::DUMMY_SP,
+                                    })
+                                    .into(),
+                                ]
+                                .into_iter(),
+                            ),
                         );
                         let obligation = traits::Obligation::new(
                             traits::ObligationCause::dummy(),
@@ -1886,7 +2100,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             Ok(Some(traits::ImplSource::UserDefined(impl_source))) => {
                                 Some(impl_source.impl_def_id)
                             }
-                            _ => None
+                            _ => None,
                         }
                     });
                     if let Some(new_def_id) = new_def_id {
@@ -1940,3 +2154,23 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 }
+
+fn find_param_in_ty<'tcx>(ty: Ty<'tcx>, param_to_point_at: ty::GenericArg<'tcx>) -> bool {
+    let mut walk = ty.walk();
+    while let Some(arg) = walk.next() {
+        if arg == param_to_point_at {
+            return true;
+        } else if let ty::GenericArgKind::Type(ty) = arg.unpack()
+            && let ty::Projection(..) = ty.kind()
+        {
+            // This logic may seem a bit strange, but typically when
+            // we have a projection type in a function signature, the
+            // argument that's being passed into that signature is
+            // not actually constraining that projection's substs in
+            // a meaningful way. So we skip it, and see improvements
+            // in some UI tests.
+            walk.skip_current_subtree();
+        }
+    }
+    false
+}
diff --git a/compiler/rustc_typeck/src/check/generator_interior.rs b/compiler/rustc_typeck/src/check/generator_interior.rs
index d4f8001493c..85a0d4e4499 100644
--- a/compiler/rustc_typeck/src/check/generator_interior.rs
+++ b/compiler/rustc_typeck/src/check/generator_interior.rs
@@ -457,7 +457,7 @@ impl<'a, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'tcx> {
 }
 
 #[derive(Default)]
-pub struct SuspendCheckData<'a, 'tcx> {
+struct SuspendCheckData<'a, 'tcx> {
     expr: Option<&'tcx Expr<'tcx>>,
     source_span: Span,
     yield_span: Span,
@@ -472,7 +472,7 @@ pub struct SuspendCheckData<'a, 'tcx> {
 //
 // Note that this technique was chosen over things like a `Suspend` marker trait
 // as it is simpler and has precedent in the compiler
-pub fn check_must_not_suspend_ty<'tcx>(
+fn check_must_not_suspend_ty<'tcx>(
     fcx: &FnCtxt<'_, 'tcx>,
     ty: Ty<'tcx>,
     hir_id: HirId,
@@ -489,6 +489,8 @@ pub fn check_must_not_suspend_ty<'tcx>(
 
     let plural_suffix = pluralize!(data.plural_len);
 
+    debug!("Checking must_not_suspend for {}", ty);
+
     match *ty.kind() {
         ty::Adt(..) if ty.is_box() => {
             let boxed_ty = ty.boxed_ty();
@@ -580,6 +582,12 @@ pub fn check_must_not_suspend_ty<'tcx>(
                 },
             )
         }
+        // If drop tracking is enabled, we want to look through references, since the referrent
+        // may not be considered live across the await point.
+        ty::Ref(_region, ty, _mutability) if fcx.sess().opts.unstable_opts.drop_tracking => {
+            let descr_pre = &format!("{}reference{} to ", data.descr_pre, plural_suffix);
+            check_must_not_suspend_ty(fcx, ty, hir_id, SuspendCheckData { descr_pre, ..data })
+        }
         _ => false,
     }
 }
diff --git a/compiler/rustc_typeck/src/check/method/confirm.rs b/compiler/rustc_typeck/src/check/method/confirm.rs
index 2c89b63ae84..59fd5c315ae 100644
--- a/compiler/rustc_typeck/src/check/method/confirm.rs
+++ b/compiler/rustc_typeck/src/check/method/confirm.rs
@@ -491,7 +491,19 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
         // so we just call `predicates_for_generics` directly to avoid redoing work.
         // `self.add_required_obligations(self.span, def_id, &all_substs);`
         for obligation in traits::predicates_for_generics(
-            traits::ObligationCause::new(self.span, self.body_id, traits::ItemObligation(def_id)),
+            |idx, span| {
+                let code = if span.is_dummy() {
+                    ObligationCauseCode::ExprItemObligation(def_id, self.call_expr.hir_id, idx)
+                } else {
+                    ObligationCauseCode::ExprBindingObligation(
+                        def_id,
+                        span,
+                        self.call_expr.hir_id,
+                        idx,
+                    )
+                };
+                traits::ObligationCause::new(self.span, self.body_id, code)
+            },
             self.param_env,
             method_predicates,
         ) {
diff --git a/compiler/rustc_typeck/src/check/method/mod.rs b/compiler/rustc_typeck/src/check/method/mod.rs
index 0e678c41f8b..de26a9e56e2 100644
--- a/compiler/rustc_typeck/src/check/method/mod.rs
+++ b/compiler/rustc_typeck/src/check/method/mod.rs
@@ -534,7 +534,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             traits::ObligationCause::misc(span, self.body_id)
         };
-        obligations.extend(traits::predicates_for_generics(cause.clone(), self.param_env, bounds));
+        let predicates_cause = cause.clone();
+        obligations.extend(traits::predicates_for_generics(
+            move |_, _| predicates_cause.clone(),
+            self.param_env,
+            bounds,
+        ));
 
         // Also add an obligation for the method type being well-formed.
         let method_ty = tcx.mk_fn_ptr(ty::Binder::dummy(fn_sig));
diff --git a/compiler/rustc_typeck/src/check/method/probe.rs b/compiler/rustc_typeck/src/check/method/probe.rs
index efe15fec7cb..d9870060a40 100644
--- a/compiler/rustc_typeck/src/check/method/probe.rs
+++ b/compiler/rustc_typeck/src/check/method/probe.rs
@@ -1514,8 +1514,11 @@ impl<'a, 'tcx> ProbeContext<'a, 'tcx> {
                         traits::normalize(selcx, self.param_env, cause.clone(), impl_bounds);
 
                     // Convert the bounds into obligations.
-                    let impl_obligations =
-                        traits::predicates_for_generics(cause, self.param_env, impl_bounds);
+                    let impl_obligations = traits::predicates_for_generics(
+                        move |_, _| cause.clone(),
+                        self.param_env,
+                        impl_bounds,
+                    );
 
                     let candidate_obligations = impl_obligations
                         .chain(norm_obligations.into_iter())
diff --git a/compiler/rustc_typeck/src/check/mod.rs b/compiler/rustc_typeck/src/check/mod.rs
index dfbef544b1d..fb675212e3f 100644
--- a/compiler/rustc_typeck/src/check/mod.rs
+++ b/compiler/rustc_typeck/src/check/mod.rs
@@ -87,7 +87,6 @@ mod op;
 mod pat;
 mod place_op;
 mod region;
-pub mod regionck;
 pub mod rvalue_scopes;
 mod upvar;
 pub mod wfcheck;
diff --git a/compiler/rustc_typeck/src/check/regionck.rs b/compiler/rustc_typeck/src/check/regionck.rs
deleted file mode 100644
index d49a6138f7a..00000000000
--- a/compiler/rustc_typeck/src/check/regionck.rs
+++ /dev/null
@@ -1,47 +0,0 @@
-use crate::outlives::outlives_bounds::InferCtxtExt as _;
-use rustc_data_structures::fx::FxHashSet;
-use rustc_hir as hir;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::InferCtxt;
-use rustc_middle::ty::Ty;
-
-pub(crate) trait OutlivesEnvironmentExt<'tcx> {
-    fn add_implied_bounds(
-        &mut self,
-        infcx: &InferCtxt<'_, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    );
-}
-
-impl<'tcx> OutlivesEnvironmentExt<'tcx> for OutlivesEnvironment<'tcx> {
-    /// This method adds "implied bounds" into the outlives environment.
-    /// Implied bounds are outlives relationships that we can deduce
-    /// on the basis that certain types must be well-formed -- these are
-    /// either the types that appear in the function signature or else
-    /// the input types to an impl. For example, if you have a function
-    /// like
-    ///
-    /// ```
-    /// fn foo<'a, 'b, T>(x: &'a &'b [T]) { }
-    /// ```
-    ///
-    /// we can assume in the caller's body that `'b: 'a` and that `T:
-    /// 'b` (and hence, transitively, that `T: 'a`). This method would
-    /// add those assumptions into the outlives-environment.
-    ///
-    /// Tests: `src/test/ui/regions/regions-free-region-ordering-*.rs`
-    #[instrument(level = "debug", skip(self, infcx))]
-    fn add_implied_bounds<'a>(
-        &mut self,
-        infcx: &InferCtxt<'a, 'tcx>,
-        fn_sig_tys: FxHashSet<Ty<'tcx>>,
-        body_id: hir::HirId,
-    ) {
-        for ty in fn_sig_tys {
-            let ty = infcx.resolve_vars_if_possible(ty);
-            let implied_bounds = infcx.implied_outlives_bounds(self.param_env, body_id, ty);
-            self.add_outlives_bounds(Some(infcx), implied_bounds)
-        }
-    }
-}
diff --git a/compiler/rustc_typeck/src/check/wfcheck.rs b/compiler/rustc_typeck/src/check/wfcheck.rs
index d0334cd0df7..ed653f0f9c8 100644
--- a/compiler/rustc_typeck/src/check/wfcheck.rs
+++ b/compiler/rustc_typeck/src/check/wfcheck.rs
@@ -1,5 +1,5 @@
-use crate::check::regionck::OutlivesEnvironmentExt;
 use crate::constrained_generic_params::{identify_constrained_generic_params, Parameter};
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 use rustc_ast as ast;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::{pluralize, struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed};
@@ -10,7 +10,6 @@ use rustc_hir::ItemKind;
 use rustc_infer::infer::outlives::env::{OutlivesEnvironment, RegionBoundPairs};
 use rustc_infer::infer::outlives::obligations::TypeOutlives;
 use rustc_infer::infer::{self, InferCtxt, TyCtxtInferExt};
-use rustc_infer::traits::Normalized;
 use rustc_middle::ty::query::Providers;
 use rustc_middle::ty::subst::{GenericArgKind, InternalSubsts, Subst};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
@@ -24,8 +23,6 @@ use rustc_span::{Span, DUMMY_SP};
 use rustc_trait_selection::autoderef::Autoderef;
 use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt as _;
-use rustc_trait_selection::traits::query::normalize::AtExt;
-use rustc_trait_selection::traits::query::NoSolution;
 use rustc_trait_selection::traits::{
     self, ObligationCause, ObligationCauseCode, ObligationCtxt, WellFormedLoc,
 };
@@ -72,9 +69,11 @@ impl<'tcx> WfCheckingCtxt<'_, 'tcx> {
     ) {
         let cause =
             traits::ObligationCause::new(span, self.body_id, ObligationCauseCode::WellFormed(loc));
+        // for a type to be WF, we do not need to check if const trait predicates satisfy.
+        let param_env = self.param_env.without_const();
         self.ocx.register_obligation(traits::Obligation::new(
             cause,
-            self.param_env,
+            param_env,
             ty::Binder::dummy(ty::PredicateKind::WellFormed(arg)).to_predicate(self.tcx()),
         ));
     }
@@ -86,26 +85,31 @@ pub(super) fn enter_wf_checking_ctxt<'tcx, F>(
     body_def_id: LocalDefId,
     f: F,
 ) where
-    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>) -> FxHashSet<Ty<'tcx>>,
+    F: for<'a> FnOnce(&WfCheckingCtxt<'a, 'tcx>),
 {
     let param_env = tcx.param_env(body_def_id);
     let body_id = tcx.hir().local_def_id_to_hir_id(body_def_id);
     tcx.infer_ctxt().enter(|ref infcx| {
         let ocx = ObligationCtxt::new(infcx);
+
+        let assumed_wf_types = ocx.assumed_wf_types(param_env, span, body_def_id);
+
         let mut wfcx = WfCheckingCtxt { ocx, span, body_id, param_env };
 
         if !tcx.features().trivial_bounds {
             wfcx.check_false_global_bounds()
         }
-        let wf_tys = f(&mut wfcx);
+        f(&mut wfcx);
         let errors = wfcx.select_all_or_error();
         if !errors.is_empty() {
             infcx.report_fulfillment_errors(&errors, None, false);
             return;
         }
 
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(infcx, wf_tys, body_id);
+        let implied_bounds = infcx.implied_bounds_tys(param_env, body_id, assumed_wf_types);
+        let outlives_environment =
+            OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+
         infcx.check_region_obligations_and_report_errors(body_def_id, &outlives_environment);
     })
 }
@@ -694,8 +698,11 @@ fn resolve_regions_with_wf_tys<'tcx>(
     // region constraints get added and solved there and we need to test each
     // call individually.
     tcx.infer_ctxt().enter(|infcx| {
-        let mut outlives_environment = OutlivesEnvironment::new(param_env);
-        outlives_environment.add_implied_bounds(&infcx, wf_tys.clone(), id);
+        let outlives_environment = OutlivesEnvironment::with_bounds(
+            param_env,
+            Some(&infcx),
+            infcx.implied_bounds_tys(param_env, id, wf_tys.clone()),
+        );
         let region_bound_pairs = outlives_environment.region_bound_pairs();
 
         add_constraints(&infcx, region_bound_pairs);
@@ -976,15 +983,9 @@ fn check_associated_item(
     enter_wf_checking_ctxt(tcx, span, item_id, |wfcx| {
         let item = tcx.associated_item(item_id);
 
-        let (mut implied_bounds, self_ty) = match item.container {
-            ty::TraitContainer => (FxHashSet::default(), tcx.types.self_param),
-            ty::ImplContainer => {
-                let def_id = item.container_id(tcx);
-                (
-                    impl_implied_bounds(tcx, wfcx.param_env, def_id.expect_local(), span),
-                    tcx.type_of(def_id),
-                )
-            }
+        let self_ty = match item.container {
+            ty::TraitContainer => tcx.types.self_param,
+            ty::ImplContainer => tcx.type_of(item.container_id(tcx)),
         };
 
         match item.kind {
@@ -1002,7 +1003,6 @@ fn check_associated_item(
                     sig,
                     hir_sig.decl,
                     item.def_id.expect_local(),
-                    &mut implied_bounds,
                 );
                 check_method_receiver(wfcx, hir_sig, item, self_ty);
             }
@@ -1017,8 +1017,6 @@ fn check_associated_item(
                 }
             }
         }
-
-        implied_bounds
     })
 }
 
@@ -1118,9 +1116,6 @@ fn check_type_defn<'tcx, F>(
         }
 
         check_where_clauses(wfcx, item.span, item.def_id);
-
-        // No implied bounds in a struct definition.
-        FxHashSet::default()
     });
 }
 
@@ -1144,9 +1139,7 @@ fn check_trait(tcx: TyCtxt<'_>, item: &hir::Item<'_>) {
     }
 
     enter_wf_checking_ctxt(tcx, item.span, item.def_id, |wfcx| {
-        check_where_clauses(wfcx, item.span, item.def_id);
-
-        FxHashSet::default()
+        check_where_clauses(wfcx, item.span, item.def_id)
     });
 
     // Only check traits, don't check trait aliases
@@ -1186,9 +1179,7 @@ fn check_item_fn(
 ) {
     enter_wf_checking_ctxt(tcx, span, def_id, |wfcx| {
         let sig = tcx.fn_sig(def_id);
-        let mut implied_bounds = FxHashSet::default();
-        check_fn_or_method(wfcx, ident.span, sig, decl, def_id, &mut implied_bounds);
-        implied_bounds
+        check_fn_or_method(wfcx, ident.span, sig, decl, def_id);
     })
 }
 
@@ -1231,9 +1222,6 @@ fn check_item_type(tcx: TyCtxt<'_>, item_id: LocalDefId, ty_span: Span, allow_fo
                 tcx.require_lang_item(LangItem::Sync, Some(ty_span)),
             );
         }
-
-        // No implied bounds in a const, etc.
-        FxHashSet::default()
     });
 }
 
@@ -1284,8 +1272,6 @@ fn check_impl<'tcx>(
         }
 
         check_where_clauses(wfcx, item.span, item.def_id);
-
-        impl_implied_bounds(tcx, wfcx.param_env, item.def_id, item.span)
     });
 }
 
@@ -1465,7 +1451,13 @@ fn check_where_clauses<'tcx>(wfcx: &WfCheckingCtxt<'_, 'tcx>, span: Span, def_id
     assert_eq!(predicates.predicates.len(), predicates.spans.len());
     let wf_obligations =
         iter::zip(&predicates.predicates, &predicates.spans).flat_map(|(&p, &sp)| {
-            traits::wf::predicate_obligations(infcx, wfcx.param_env, wfcx.body_id, p, sp)
+            traits::wf::predicate_obligations(
+                infcx,
+                wfcx.param_env.without_const(),
+                wfcx.body_id,
+                p,
+                sp,
+            )
         });
 
     let obligations: Vec<_> = wf_obligations.chain(default_obligations).collect();
@@ -1479,7 +1471,6 @@ fn check_fn_or_method<'tcx>(
     sig: ty::PolyFnSig<'tcx>,
     hir_decl: &hir::FnDecl<'_>,
     def_id: LocalDefId,
-    implied_bounds: &mut FxHashSet<Ty<'tcx>>,
 ) {
     let tcx = wfcx.tcx();
     let sig = tcx.liberate_late_bound_regions(def_id.to_def_id(), sig);
@@ -1521,15 +1512,8 @@ fn check_fn_or_method<'tcx>(
         );
     }
 
-    implied_bounds.extend(sig.inputs());
-
     wfcx.register_wf_obligation(hir_decl.output.span(), None, sig.output().into());
 
-    // FIXME(#27579) return types should not be implied bounds
-    implied_bounds.insert(sig.output());
-
-    debug!(?implied_bounds);
-
     check_where_clauses(wfcx, span, def_id);
 }
 
@@ -1924,40 +1908,6 @@ impl<'a, 'tcx> WfCheckingCtxt<'a, 'tcx> {
     }
 }
 
-pub fn impl_implied_bounds<'tcx>(
-    tcx: TyCtxt<'tcx>,
-    param_env: ty::ParamEnv<'tcx>,
-    impl_def_id: LocalDefId,
-    span: Span,
-) -> FxHashSet<Ty<'tcx>> {
-    // We completely ignore any obligations caused by normalizing the types
-    // we assume to be well formed. Considering that the user of the implied
-    // bounds will also normalize them, we leave it to them to emit errors
-    // which should result in better causes and spans.
-    tcx.infer_ctxt().enter(|infcx| {
-        let cause = ObligationCause::misc(span, tcx.hir().local_def_id_to_hir_id(impl_def_id));
-        match tcx.impl_trait_ref(impl_def_id) {
-            Some(trait_ref) => {
-                // Trait impl: take implied bounds from all types that
-                // appear in the trait reference.
-                match infcx.at(&cause, param_env).normalize(trait_ref) {
-                    Ok(Normalized { value, obligations: _ }) => value.substs.types().collect(),
-                    Err(NoSolution) => FxHashSet::default(),
-                }
-            }
-
-            None => {
-                // Inherent impl: take implied bounds from the `self` type.
-                let self_ty = tcx.type_of(impl_def_id);
-                match infcx.at(&cause, param_env).normalize(self_ty) {
-                    Ok(Normalized { value, obligations: _ }) => FxHashSet::from_iter([value]),
-                    Err(NoSolution) => FxHashSet::default(),
-                }
-            }
-        }
-    })
-}
-
 fn error_392(
     tcx: TyCtxt<'_>,
     span: Span,
diff --git a/compiler/rustc_typeck/src/check/writeback.rs b/compiler/rustc_typeck/src/check/writeback.rs
index ebf1f506183..ba687bc4da4 100644
--- a/compiler/rustc_typeck/src/check/writeback.rs
+++ b/compiler/rustc_typeck/src/check/writeback.rs
@@ -3,7 +3,6 @@
 // substitutions.
 
 use crate::check::FnCtxt;
-
 use hir::def_id::LocalDefId;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::ErrorGuaranteed;
@@ -16,6 +15,7 @@ use rustc_middle::mir::FakeReadCause;
 use rustc_middle::ty::adjustment::{Adjust, Adjustment, PointerCast};
 use rustc_middle::ty::fold::{TypeFoldable, TypeFolder, TypeSuperFoldable};
 use rustc_middle::ty::visit::{TypeSuperVisitable, TypeVisitable};
+use rustc_middle::ty::TypeckResults;
 use rustc_middle::ty::{self, ClosureSizeProfileData, Ty, TyCtxt};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
@@ -192,6 +192,27 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         }
     }
 
+    // (ouz-a 1005988): Normally `[T] : std::ops::Index<usize>` should be normalized
+    // into [T] but currently `Where` clause stops the normalization process for it,
+    // here we compare types of expr and base in a code without `Where` clause they would be equal
+    // if they are not we don't modify the expr, hence we bypass the ICE
+    fn is_builtin_index(
+        &mut self,
+        typeck_results: &TypeckResults<'tcx>,
+        e: &hir::Expr<'_>,
+        base_ty: Ty<'tcx>,
+        index_ty: Ty<'tcx>,
+    ) -> bool {
+        if let Some(elem_ty) = base_ty.builtin_index() {
+            let Some(exp_ty) = typeck_results.expr_ty_opt(e) else {return false;};
+            let resolved_exp_ty = self.resolve(exp_ty, &e.span);
+
+            elem_ty == resolved_exp_ty && index_ty == self.fcx.tcx.types.usize
+        } else {
+            false
+        }
+    }
+
     // Similar to operators, indexing is always assumed to be overloaded
     // Here, correct cases where an indexing expression can be simplified
     // to use builtin indexing because the index type is known to be
@@ -222,8 +243,9 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
                     )
                 });
                 let index_ty = self.fcx.resolve_vars_if_possible(index_ty);
+                let resolved_base_ty = self.resolve(*base_ty, &base.span);
 
-                if base_ty.builtin_index().is_some() && index_ty == self.fcx.tcx.types.usize {
+                if self.is_builtin_index(&typeck_results, e, resolved_base_ty, index_ty) {
                     // Remove the method call record
                     typeck_results.type_dependent_defs_mut().remove(e.hir_id);
                     typeck_results.node_substs_mut().remove(e.hir_id);
diff --git a/compiler/rustc_typeck/src/check_unused.rs b/compiler/rustc_typeck/src/check_unused.rs
index 4a3cfa1ca37..1d23ed92921 100644
--- a/compiler/rustc_typeck/src/check_unused.rs
+++ b/compiler/rustc_typeck/src/check_unused.rs
@@ -1,5 +1,5 @@
+use crate::errors::{ExternCrateNotIdiomatic, UnusedExternCrate};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
-use rustc_errors::Applicability;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LocalDefId};
@@ -108,25 +108,16 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         // We do this in any edition.
         if extern_crate.warn_if_unused {
             if let Some(&span) = unused_extern_crates.get(&def_id) {
+                // Removal suggestion span needs to include attributes (Issue #54400)
                 let id = tcx.hir().local_def_id_to_hir_id(def_id);
-                tcx.struct_span_lint_hir(lint, id, span, |lint| {
-                    // Removal suggestion span needs to include attributes (Issue #54400)
-                    let span_with_attrs = tcx
-                        .hir()
-                        .attrs(id)
-                        .iter()
-                        .map(|attr| attr.span)
-                        .fold(span, |acc, attr_span| acc.to(attr_span));
-
-                    lint.build("unused extern crate")
-                        .span_suggestion_short(
-                            span_with_attrs,
-                            "remove it",
-                            "",
-                            Applicability::MachineApplicable,
-                        )
-                        .emit();
-                });
+                let span_with_attrs = tcx
+                    .hir()
+                    .attrs(id)
+                    .iter()
+                    .map(|attr| attr.span)
+                    .fold(span, |acc, attr_span| acc.to(attr_span));
+
+                tcx.emit_spanned_lint(lint, id, span, UnusedExternCrate { span: span_with_attrs });
                 continue;
             }
         }
@@ -158,23 +149,23 @@ fn unused_crates_lint(tcx: TyCtxt<'_>) {
         if !tcx.hir().attrs(id).is_empty() {
             continue;
         }
-        tcx.struct_span_lint_hir(lint, id, extern_crate.span, |lint| {
-            // Otherwise, we can convert it into a `use` of some kind.
-            let base_replacement = match extern_crate.orig_name {
-                Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
-                None => format!("use {};", item.ident.name),
-            };
-            let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
-            let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
-            lint.build("`extern crate` is not idiomatic in the new edition")
-                .span_suggestion_short(
-                    extern_crate.span,
-                    &format!("convert it to a `{}`", add_vis("use".to_string())),
-                    add_vis(base_replacement),
-                    Applicability::MachineApplicable,
-                )
-                .emit();
-        })
+
+        let base_replacement = match extern_crate.orig_name {
+            Some(orig_name) => format!("use {} as {};", orig_name, item.ident.name),
+            None => format!("use {};", item.ident.name),
+        };
+        let vis = tcx.sess.source_map().span_to_snippet(item.vis_span).unwrap_or_default();
+        let add_vis = |to| if vis.is_empty() { to } else { format!("{} {}", vis, to) };
+        tcx.emit_spanned_lint(
+            lint,
+            id,
+            extern_crate.span,
+            ExternCrateNotIdiomatic {
+                span: extern_crate.span,
+                msg_code: add_vis("use".to_string()),
+                suggestion_code: add_vis(base_replacement),
+            },
+        );
     }
 }
 
diff --git a/compiler/rustc_typeck/src/coherence/builtin.rs b/compiler/rustc_typeck/src/coherence/builtin.rs
index 043e21fc1e3..2467a81638f 100644
--- a/compiler/rustc_typeck/src/coherence/builtin.rs
+++ b/compiler/rustc_typeck/src/coherence/builtin.rs
@@ -47,9 +47,11 @@ impl<'tcx> Checker<'tcx> {
 }
 
 fn visit_implementation_of_drop(tcx: TyCtxt<'_>, impl_did: LocalDefId) {
-    // Destructors only work on nominal types.
-    if let ty::Adt(..) | ty::Error(_) = tcx.type_of(impl_did).kind() {
-        return;
+    // Destructors only work on local ADT types.
+    match tcx.type_of(impl_did).kind() {
+        ty::Adt(def, _) if def.did().is_local() => return,
+        ty::Error(_) => return,
+        _ => {}
     }
 
     let sp = match tcx.hir().expect_item(impl_did).kind {
diff --git a/compiler/rustc_typeck/src/collect.rs b/compiler/rustc_typeck/src/collect.rs
index e7c5ecc60ec..970b39dc845 100644
--- a/compiler/rustc_typeck/src/collect.rs
+++ b/compiler/rustc_typeck/src/collect.rs
@@ -2836,12 +2836,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: DefId) -> CodegenFnAttrs {
                     codegen_fn_attrs.flags |= CodegenFnAttrFlags::USED;
                 }
                 Some(_) => {
-                    tcx.sess
-                        .struct_span_err(
-                            attr.span,
-                            "expected `used`, `used(compiler)` or `used(linker)`",
-                        )
-                        .emit();
+                    tcx.sess.emit_err(errors::ExpectedUsedSymbol { span: attr.span });
                 }
                 None => {
                     // Unfortunately, unconditionally using `llvm.used` causes
diff --git a/compiler/rustc_typeck/src/errors.rs b/compiler/rustc_typeck/src/errors.rs
index 0438ac02ea9..2214fc2ced8 100644
--- a/compiler/rustc_typeck/src/errors.rs
+++ b/compiler/rustc_typeck/src/errors.rs
@@ -1,12 +1,12 @@
 //! Errors emitted by typeck.
 use rustc_errors::{error_code, Applicability, DiagnosticBuilder, ErrorGuaranteed};
-use rustc_macros::{SessionDiagnostic, SessionSubdiagnostic};
+use rustc_macros::{LintDiagnostic, SessionDiagnostic, SessionSubdiagnostic};
 use rustc_middle::ty::Ty;
 use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::{symbol::Ident, Span, Symbol};
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::field_multiply_specified_in_initializer, code = "E0062")]
+#[diag(typeck::field_multiply_specified_in_initializer, code = "E0062")]
 pub struct FieldMultiplySpecifiedInInitializer {
     #[primary_span]
     #[label]
@@ -17,7 +17,7 @@ pub struct FieldMultiplySpecifiedInInitializer {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unrecognized_atomic_operation, code = "E0092")]
+#[diag(typeck::unrecognized_atomic_operation, code = "E0092")]
 pub struct UnrecognizedAtomicOperation<'a> {
     #[primary_span]
     #[label]
@@ -26,7 +26,7 @@ pub struct UnrecognizedAtomicOperation<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
+#[diag(typeck::wrong_number_of_generic_arguments_to_intrinsic, code = "E0094")]
 pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
     #[primary_span]
     #[label]
@@ -37,7 +37,7 @@ pub struct WrongNumberOfGenericArgumentsToIntrinsic<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unrecognized_intrinsic_function, code = "E0093")]
+#[diag(typeck::unrecognized_intrinsic_function, code = "E0093")]
 pub struct UnrecognizedIntrinsicFunction {
     #[primary_span]
     #[label]
@@ -46,7 +46,7 @@ pub struct UnrecognizedIntrinsicFunction {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
+#[diag(typeck::lifetimes_or_bounds_mismatch_on_trait, code = "E0195")]
 pub struct LifetimesOrBoundsMismatchOnTrait {
     #[primary_span]
     #[label]
@@ -58,7 +58,7 @@ pub struct LifetimesOrBoundsMismatchOnTrait {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::drop_impl_on_wrong_item, code = "E0120")]
+#[diag(typeck::drop_impl_on_wrong_item, code = "E0120")]
 pub struct DropImplOnWrongItem {
     #[primary_span]
     #[label]
@@ -66,7 +66,7 @@ pub struct DropImplOnWrongItem {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::field_already_declared, code = "E0124")]
+#[diag(typeck::field_already_declared, code = "E0124")]
 pub struct FieldAlreadyDeclared {
     pub field_name: Ident,
     #[primary_span]
@@ -77,7 +77,7 @@ pub struct FieldAlreadyDeclared {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
+#[diag(typeck::copy_impl_on_type_with_dtor, code = "E0184")]
 pub struct CopyImplOnTypeWithDtor {
     #[primary_span]
     #[label]
@@ -85,14 +85,14 @@ pub struct CopyImplOnTypeWithDtor {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::multiple_relaxed_default_bounds, code = "E0203")]
+#[diag(typeck::multiple_relaxed_default_bounds, code = "E0203")]
 pub struct MultipleRelaxedDefaultBounds {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::copy_impl_on_non_adt, code = "E0206")]
+#[diag(typeck::copy_impl_on_non_adt, code = "E0206")]
 pub struct CopyImplOnNonAdt {
     #[primary_span]
     #[label]
@@ -100,7 +100,7 @@ pub struct CopyImplOnNonAdt {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::trait_object_declared_with_no_traits, code = "E0224")]
+#[diag(typeck::trait_object_declared_with_no_traits, code = "E0224")]
 pub struct TraitObjectDeclaredWithNoTraits {
     #[primary_span]
     pub span: Span,
@@ -109,14 +109,14 @@ pub struct TraitObjectDeclaredWithNoTraits {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0227")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0227")]
 pub struct AmbiguousLifetimeBound {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::assoc_type_binding_not_allowed, code = "E0229")]
+#[diag(typeck::assoc_type_binding_not_allowed, code = "E0229")]
 pub struct AssocTypeBindingNotAllowed {
     #[primary_span]
     #[label]
@@ -124,14 +124,14 @@ pub struct AssocTypeBindingNotAllowed {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::functional_record_update_on_non_struct, code = "E0436")]
+#[diag(typeck::functional_record_update_on_non_struct, code = "E0436")]
 pub struct FunctionalRecordUpdateOnNonStruct {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::typeof_reserved_keyword_used, code = "E0516")]
+#[diag(typeck::typeof_reserved_keyword_used, code = "E0516")]
 pub struct TypeofReservedKeywordUsed<'tcx> {
     pub ty: Ty<'tcx>,
     #[primary_span]
@@ -142,7 +142,7 @@ pub struct TypeofReservedKeywordUsed<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
+#[diag(typeck::return_stmt_outside_of_fn_body, code = "E0572")]
 pub struct ReturnStmtOutsideOfFnBody {
     #[primary_span]
     pub span: Span,
@@ -153,14 +153,14 @@ pub struct ReturnStmtOutsideOfFnBody {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::yield_expr_outside_of_generator, code = "E0627")]
+#[diag(typeck::yield_expr_outside_of_generator, code = "E0627")]
 pub struct YieldExprOutsideOfGenerator {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::struct_expr_non_exhaustive, code = "E0639")]
+#[diag(typeck::struct_expr_non_exhaustive, code = "E0639")]
 pub struct StructExprNonExhaustive {
     #[primary_span]
     pub span: Span,
@@ -168,14 +168,14 @@ pub struct StructExprNonExhaustive {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::method_call_on_unknown_type, code = "E0699")]
+#[diag(typeck::method_call_on_unknown_type, code = "E0699")]
 pub struct MethodCallOnUnknownType {
     #[primary_span]
     pub span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::value_of_associated_struct_already_specified, code = "E0719")]
+#[diag(typeck::value_of_associated_struct_already_specified, code = "E0719")]
 pub struct ValueOfAssociatedStructAlreadySpecified {
     #[primary_span]
     #[label]
@@ -187,7 +187,7 @@ pub struct ValueOfAssociatedStructAlreadySpecified {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::address_of_temporary_taken, code = "E0745")]
+#[diag(typeck::address_of_temporary_taken, code = "E0745")]
 pub struct AddressOfTemporaryTaken {
     #[primary_span]
     #[label]
@@ -233,7 +233,7 @@ pub enum ExpectedReturnTypeLabel<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::unconstrained_opaque_type)]
+#[diag(typeck::unconstrained_opaque_type)]
 #[note]
 pub struct UnconstrainedOpaqueType {
     #[primary_span]
@@ -309,7 +309,7 @@ impl<'a> SessionDiagnostic<'a> for MissingTypeParams {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::manual_implementation, code = "E0183")]
+#[diag(typeck::manual_implementation, code = "E0183")]
 #[help]
 pub struct ManualImplementation {
     #[primary_span]
@@ -319,8 +319,31 @@ pub struct ManualImplementation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::substs_on_overridden_impl)]
+#[diag(typeck::substs_on_overridden_impl)]
 pub struct SubstsOnOverriddenImpl {
     #[primary_span]
     pub span: Span,
 }
+
+#[derive(LintDiagnostic)]
+#[diag(typeck::unused_extern_crate)]
+pub struct UnusedExternCrate {
+    #[suggestion(applicability = "machine-applicable", code = "")]
+    pub span: Span,
+}
+
+#[derive(LintDiagnostic)]
+#[diag(typeck::extern_crate_not_idiomatic)]
+pub struct ExternCrateNotIdiomatic {
+    #[suggestion_short(applicability = "machine-applicable", code = "{suggestion_code}")]
+    pub span: Span,
+    pub msg_code: String,
+    pub suggestion_code: String,
+}
+
+#[derive(SessionDiagnostic)]
+#[diag(typeck::expected_used_symbol)]
+pub struct ExpectedUsedSymbol {
+    #[primary_span]
+    pub span: Span,
+}
diff --git a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
index 74abb71a18e..6240024d49c 100644
--- a/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
+++ b/compiler/rustc_typeck/src/impl_wf_check/min_specialization.rs
@@ -65,27 +65,25 @@
 //! cause use after frees with purely safe code in the same way as specializing
 //! on traits with methods can.
 
-use crate::check::regionck::OutlivesEnvironmentExt;
-use crate::check::wfcheck::impl_implied_bounds;
 use crate::constrained_generic_params as cgp;
 use crate::errors::SubstsOnOverriddenImpl;
+use crate::outlives::outlives_bounds::InferCtxtExt as _;
 
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def_id::{DefId, LocalDefId};
 use rustc_infer::infer::outlives::env::OutlivesEnvironment;
-use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
+use rustc_infer::infer::TyCtxtInferExt;
 use rustc_infer::traits::specialization_graph::Node;
 use rustc_middle::ty::subst::{GenericArg, InternalSubsts, SubstsRef};
 use rustc_middle::ty::trait_def::TraitSpecializationKind;
 use rustc_middle::ty::{self, TyCtxt, TypeVisitable};
 use rustc_span::Span;
-use rustc_trait_selection::traits::{self, translate_substs, wf};
+use rustc_trait_selection::traits::error_reporting::InferCtxtExt;
+use rustc_trait_selection::traits::{self, translate_substs, wf, ObligationCtxt};
 
 pub(super) fn check_min_specialization(tcx: TyCtxt<'_>, impl_def_id: LocalDefId) {
     if let Some(node) = parent_specialization_node(tcx, impl_def_id) {
-        tcx.infer_ctxt().enter(|infcx| {
-            check_always_applicable(&infcx, impl_def_id, node);
-        });
+        check_always_applicable(tcx, impl_def_id, node);
     }
 }
 
@@ -105,16 +103,14 @@ fn parent_specialization_node(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId) -> Opti
 }
 
 /// Check that `impl1` is a sound specialization
-fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId, impl2_node: Node) {
-    if let Some((impl1_substs, impl2_substs)) = get_impl_substs(infcx, impl1_def_id, impl2_node) {
+fn check_always_applicable(tcx: TyCtxt<'_>, impl1_def_id: LocalDefId, impl2_node: Node) {
+    if let Some((impl1_substs, impl2_substs)) = get_impl_substs(tcx, impl1_def_id, impl2_node) {
         let impl2_def_id = impl2_node.def_id();
         debug!(
             "check_always_applicable(\nimpl1_def_id={:?},\nimpl2_def_id={:?},\nimpl2_substs={:?}\n)",
             impl1_def_id, impl2_def_id, impl2_substs
         );
 
-        let tcx = infcx.tcx;
-
         let parent_substs = if impl2_node.is_from_trait() {
             impl2_substs.to_vec()
         } else {
@@ -124,7 +120,7 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
         let span = tcx.def_span(impl1_def_id);
         check_static_lifetimes(tcx, &parent_substs, span);
         check_duplicate_params(tcx, impl1_substs, &parent_substs, span);
-        check_predicates(infcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
+        check_predicates(tcx, impl1_def_id, impl1_substs, impl2_node, impl2_substs, span);
     }
 }
 
@@ -139,32 +135,38 @@ fn check_always_applicable(infcx: &InferCtxt<'_, '_>, impl1_def_id: LocalDefId,
 ///
 /// Would return `S1 = [C]` and `S2 = [Vec<C>, C]`.
 fn get_impl_substs<'tcx>(
-    infcx: &InferCtxt<'_, 'tcx>,
+    tcx: TyCtxt<'tcx>,
     impl1_def_id: LocalDefId,
     impl2_node: Node,
 ) -> Option<(SubstsRef<'tcx>, SubstsRef<'tcx>)> {
-    let tcx = infcx.tcx;
-    let param_env = tcx.param_env(impl1_def_id);
+    tcx.infer_ctxt().enter(|ref infcx| {
+        let ocx = ObligationCtxt::new(infcx);
+        let param_env = tcx.param_env(impl1_def_id);
+        let impl1_hir_id = tcx.hir().local_def_id_to_hir_id(impl1_def_id);
 
-    let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
-    let impl2_substs =
-        translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+        let assumed_wf_types =
+            ocx.assumed_wf_types(param_env, tcx.def_span(impl1_def_id), impl1_def_id);
 
-    let mut outlives_env = OutlivesEnvironment::new(param_env);
-    let implied_bounds =
-        impl_implied_bounds(infcx.tcx, param_env, impl1_def_id, tcx.def_span(impl1_def_id));
-    outlives_env.add_implied_bounds(
-        infcx,
-        implied_bounds,
-        tcx.hir().local_def_id_to_hir_id(impl1_def_id),
-    );
-    infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
-    let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
-        let span = tcx.def_span(impl1_def_id);
-        tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
-        return None;
-    };
-    Some((impl1_substs, impl2_substs))
+        let impl1_substs = InternalSubsts::identity_for_item(tcx, impl1_def_id.to_def_id());
+        let impl2_substs =
+            translate_substs(infcx, param_env, impl1_def_id.to_def_id(), impl1_substs, impl2_node);
+
+        let errors = ocx.select_all_or_error();
+        if !errors.is_empty() {
+            ocx.infcx.report_fulfillment_errors(&errors, None, false);
+            return None;
+        }
+
+        let implied_bounds = infcx.implied_bounds_tys(param_env, impl1_hir_id, assumed_wf_types);
+        let outlives_env = OutlivesEnvironment::with_bounds(param_env, Some(infcx), implied_bounds);
+        infcx.check_region_obligations_and_report_errors(impl1_def_id, &outlives_env);
+        let Ok(impl2_substs) = infcx.fully_resolve(impl2_substs) else {
+            let span = tcx.def_span(impl1_def_id);
+            tcx.sess.emit_err(SubstsOnOverriddenImpl { span });
+            return None;
+        };
+        Some((impl1_substs, impl2_substs))
+    })
 }
 
 /// Returns a list of all of the unconstrained subst of the given impl.
@@ -279,14 +281,13 @@ fn check_static_lifetimes<'tcx>(
 /// * a well-formed predicate of a type argument of the trait being implemented,
 ///   including the `Self`-type.
 fn check_predicates<'tcx>(
-    infcx: &InferCtxt<'_, 'tcx>,
+    tcx: TyCtxt<'tcx>,
     impl1_def_id: LocalDefId,
     impl1_substs: SubstsRef<'tcx>,
     impl2_node: Node,
     impl2_substs: SubstsRef<'tcx>,
     span: Span,
 ) {
-    let tcx = infcx.tcx;
     let instantiated = tcx.predicates_of(impl1_def_id).instantiate(tcx, impl1_substs);
     let impl1_predicates: Vec<_> = traits::elaborate_predicates_with_span(
         tcx,
@@ -343,19 +344,23 @@ fn check_predicates<'tcx>(
 
     // Include the well-formed predicates of the type parameters of the impl.
     for arg in tcx.impl_trait_ref(impl1_def_id).unwrap().substs {
-        if let Some(obligations) = wf::obligations(
-            infcx,
-            tcx.param_env(impl1_def_id),
-            tcx.hir().local_def_id_to_hir_id(impl1_def_id),
-            0,
-            arg,
-            span,
-        ) {
+        tcx.infer_ctxt().enter(|ref infcx| {
+            let obligations = wf::obligations(
+                infcx,
+                tcx.param_env(impl1_def_id),
+                tcx.hir().local_def_id_to_hir_id(impl1_def_id),
+                0,
+                arg,
+                span,
+            )
+            .unwrap();
+
+            assert!(!obligations.needs_infer());
             impl2_predicates.extend(
                 traits::elaborate_obligations(tcx, obligations)
                     .map(|obligation| obligation.predicate),
             )
-        }
+        })
     }
     impl2_predicates.extend(
         traits::elaborate_predicates_with_span(tcx, always_applicable_traits)
diff --git a/compiler/rustc_typeck/src/lib.rs b/compiler/rustc_typeck/src/lib.rs
index 8c6fb6a7718..1ff9c627131 100644
--- a/compiler/rustc_typeck/src/lib.rs
+++ b/compiler/rustc_typeck/src/lib.rs
@@ -72,6 +72,7 @@ This API is completely unstable and subject to change.
 #![feature(slice_partition_dedup)]
 #![feature(try_blocks)]
 #![feature(is_some_with)]
+#![feature(type_alias_impl_trait)]
 #![recursion_limit = "256"]
 
 #[macro_use]
diff --git a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
index 229a6465084..024e20d9223 100644
--- a/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
+++ b/compiler/rustc_typeck/src/outlives/outlives_bounds.rs
@@ -1,5 +1,7 @@
+use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
-use rustc_middle::ty::{self, Ty};
+use rustc_hir::HirId;
+use rustc_middle::ty::{self, ParamEnv, Ty};
 use rustc_trait_selection::infer::InferCtxt;
 use rustc_trait_selection::traits::query::type_op::{self, TypeOp, TypeOpOutput};
 use rustc_trait_selection::traits::query::NoSolution;
@@ -7,16 +9,24 @@ use rustc_trait_selection::traits::{ObligationCause, TraitEngine, TraitEngineExt
 
 pub use rustc_middle::traits::query::OutlivesBound;
 
-pub trait InferCtxtExt<'tcx> {
+type Bounds<'a, 'tcx: 'a> = impl Iterator<Item = OutlivesBound<'tcx>> + 'a;
+pub trait InferCtxtExt<'a, 'tcx> {
     fn implied_outlives_bounds(
         &self,
         param_env: ty::ParamEnv<'tcx>,
         body_id: hir::HirId,
         ty: Ty<'tcx>,
     ) -> Vec<OutlivesBound<'tcx>>;
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ty::ParamEnv<'tcx>,
+        body_id: hir::HirId,
+        tys: FxHashSet<Ty<'tcx>>,
+    ) -> Bounds<'a, 'tcx>;
 }
 
-impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
+impl<'a, 'cx, 'tcx: 'a> InferCtxtExt<'a, 'tcx> for InferCtxt<'cx, 'tcx> {
     /// Implied bounds are region relationships that we deduce
     /// automatically. The idea is that (e.g.) a caller must check that a
     /// function's argument types are well-formed immediately before
@@ -87,4 +97,18 @@ impl<'cx, 'tcx> InferCtxtExt<'tcx> for InferCtxt<'cx, 'tcx> {
 
         output
     }
+
+    fn implied_bounds_tys(
+        &'a self,
+        param_env: ParamEnv<'tcx>,
+        body_id: HirId,
+        tys: FxHashSet<Ty<'tcx>>,
+    ) -> Bounds<'a, 'tcx> {
+        tys.into_iter()
+            .map(move |ty| {
+                let ty = self.resolve_vars_if_possible(ty);
+                self.implied_outlives_bounds(param_env, body_id, ty)
+            })
+            .flatten()
+    }
 }
diff --git a/library/alloc/src/alloc/tests.rs b/library/alloc/src/alloc/tests.rs
index 7d560964d85..b2f0194599b 100644
--- a/library/alloc/src/alloc/tests.rs
+++ b/library/alloc/src/alloc/tests.rs
@@ -15,7 +15,7 @@ fn allocate_zeroed() {
         let end = i.add(layout.size());
         while i < end {
             assert_eq!(*i, 0);
-            i = i.offset(1);
+            i = i.add(1);
         }
         Global.deallocate(ptr.as_non_null_ptr(), layout);
     }
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index c1ceeb0deb8..6955d863c99 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -1,4 +1,4 @@
-//! A pointer type for heap allocation.
+//! The `Box<T>` type for heap allocation.
 //!
 //! [`Box<T>`], casually referred to as a 'box', provides the simplest form of
 //! heap allocation in Rust. Boxes provide ownership for this allocation, and
diff --git a/library/alloc/src/collections/binary_heap.rs b/library/alloc/src/collections/binary_heap.rs
index 197e7aaaccf..4583bc9a158 100644
--- a/library/alloc/src/collections/binary_heap.rs
+++ b/library/alloc/src/collections/binary_heap.rs
@@ -1010,7 +1010,8 @@ impl<T> BinaryHeap<T> {
     /// current length. The allocator may reserve more space to speculatively
     /// avoid frequent allocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
diff --git a/library/alloc/src/collections/vec_deque/mod.rs b/library/alloc/src/collections/vec_deque/mod.rs
index 4d895d83745..347a938fd0c 100644
--- a/library/alloc/src/collections/vec_deque/mod.rs
+++ b/library/alloc/src/collections/vec_deque/mod.rs
@@ -794,7 +794,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
     /// in the given deque. The collection may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
@@ -2447,8 +2448,8 @@ impl<T, A: Allocator> VecDeque<T, A> {
                     let mut right_offset = 0;
                     for i in left_edge..right_edge {
                         right_offset = (i - left_edge) % (cap - right_edge);
-                        let src: isize = (right_edge + right_offset) as isize;
-                        ptr::swap(buf.add(i), buf.offset(src));
+                        let src = right_edge + right_offset;
+                        ptr::swap(buf.add(i), buf.add(src));
                     }
                     let n_ops = right_edge - left_edge;
                     left_edge += n_ops;
diff --git a/library/alloc/src/ffi/c_str.rs b/library/alloc/src/ffi/c_str.rs
index ae61b1f1e8e..be21d8c722d 100644
--- a/library/alloc/src/ffi/c_str.rs
+++ b/library/alloc/src/ffi/c_str.rs
@@ -436,9 +436,9 @@ impl CString {
     ///
     /// unsafe {
     ///     assert_eq!(b'f', *ptr as u8);
-    ///     assert_eq!(b'o', *ptr.offset(1) as u8);
-    ///     assert_eq!(b'o', *ptr.offset(2) as u8);
-    ///     assert_eq!(b'\0', *ptr.offset(3) as u8);
+    ///     assert_eq!(b'o', *ptr.add(1) as u8);
+    ///     assert_eq!(b'o', *ptr.add(2) as u8);
+    ///     assert_eq!(b'\0', *ptr.add(3) as u8);
     ///
     ///     // retake pointer to free memory
     ///     let _ = CString::from_raw(ptr);
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 8b6f4054851..62fd5955726 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -56,10 +56,6 @@
 //! [`Rc`]: rc
 //! [`RefCell`]: core::cell
 
-// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
-// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
-// rustc itself never sets the feature, so this line has no affect there.
-#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 #![allow(unused_attributes)]
 #![stable(feature = "alloc", since = "1.36.0")]
 #![doc(
@@ -77,6 +73,10 @@
 ))]
 #![no_std]
 #![needs_allocator]
+// To run liballoc tests without x.py without ending up with two copies of liballoc, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
 //
 // Lints:
 #![deny(unsafe_op_in_unsafe_fn)]
@@ -145,6 +145,7 @@
 #![feature(unchecked_math)]
 #![feature(unicode_internals)]
 #![feature(unsize)]
+#![feature(utf8_chunks)]
 #![feature(std_internals)]
 //
 // Language features:
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 63d4d945290..bcd3f49e208 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -1,82 +1,12 @@
-//! A dynamically-sized view into a contiguous sequence, `[T]`.
+//! Utilities for the slice primitive type.
 //!
 //! *[See also the slice primitive type](slice).*
 //!
-//! Slices are a view into a block of memory represented as a pointer and a
-//! length.
+//! Most of the structs in this module are iterator types which can only be created
+//! using a certain function. For example, `slice.iter()` yields an [`Iter`].
 //!
-//! ```
-//! // slicing a Vec
-//! let vec = vec![1, 2, 3];
-//! let int_slice = &vec[..];
-//! // coercing an array to a slice
-//! let str_slice: &[&str] = &["one", "two", "three"];
-//! ```
-//!
-//! Slices are either mutable or shared. The shared slice type is `&[T]`,
-//! while the mutable slice type is `&mut [T]`, where `T` represents the element
-//! type. For example, you can mutate the block of memory that a mutable slice
-//! points to:
-//!
-//! ```
-//! let x = &mut [1, 2, 3];
-//! x[1] = 7;
-//! assert_eq!(x, &[1, 7, 3]);
-//! ```
-//!
-//! Here are some of the things this module contains:
-//!
-//! ## Structs
-//!
-//! There are several structs that are useful for slices, such as [`Iter`], which
-//! represents iteration over a slice.
-//!
-//! ## Trait Implementations
-//!
-//! There are several implementations of common traits for slices. Some examples
-//! include:
-//!
-//! * [`Clone`]
-//! * [`Eq`], [`Ord`] - for slices whose element type are [`Eq`] or [`Ord`].
-//! * [`Hash`] - for slices whose element type is [`Hash`].
-//!
-//! ## Iteration
-//!
-//! The slices implement `IntoIterator`. The iterator yields references to the
-//! slice elements.
-//!
-//! ```
-//! let numbers = &[0, 1, 2];
-//! for n in numbers {
-//!     println!("{n} is a number!");
-//! }
-//! ```
-//!
-//! The mutable slice yields mutable references to the elements:
-//!
-//! ```
-//! let mut scores = [7, 8, 9];
-//! for score in &mut scores[..] {
-//!     *score += 1;
-//! }
-//! ```
-//!
-//! This iterator yields mutable references to the slice's elements, so while
-//! the element type of the slice is `i32`, the element type of the iterator is
-//! `&mut i32`.
-//!
-//! * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
-//!   iterators.
-//! * Further methods that return iterators are [`.split`], [`.splitn`],
-//!   [`.chunks`], [`.windows`] and more.
-//!
-//! [`Hash`]: core::hash::Hash
-//! [`.iter`]: slice::iter
-//! [`.iter_mut`]: slice::iter_mut
-//! [`.split`]: slice::split
-//! [`.splitn`]: slice::splitn
-//! [`.chunks`]: slice::chunks
-//! [`.windows`]: slice::windows
+//! A few functions are provided to create a slice from a value reference
+//! or from a raw pointer.
 #![stable(feature = "rust1", since = "1.0.0")]
 // Many of the usings in this module are only used in the test configuration.
 // It's cleaner to just turn off the unused_imports warning than to fix them.
@@ -1024,7 +954,7 @@ where
             // Consume the greater side.
             // If equal, prefer the right run to maintain stability.
             unsafe {
-                let to_copy = if is_less(&*right.offset(-1), &*left.offset(-1)) {
+                let to_copy = if is_less(&*right.sub(1), &*left.sub(1)) {
                     decrement_and_get(left)
                 } else {
                     decrement_and_get(right)
@@ -1038,12 +968,12 @@ where
 
     unsafe fn get_and_increment<T>(ptr: &mut *mut T) -> *mut T {
         let old = *ptr;
-        *ptr = unsafe { ptr.offset(1) };
+        *ptr = unsafe { ptr.add(1) };
         old
     }
 
     unsafe fn decrement_and_get<T>(ptr: &mut *mut T) -> *mut T {
-        *ptr = unsafe { ptr.offset(-1) };
+        *ptr = unsafe { ptr.sub(1) };
         *ptr
     }
 
diff --git a/library/alloc/src/str.rs b/library/alloc/src/str.rs
index d5ed2c4adf4..b28d20cda17 100644
--- a/library/alloc/src/str.rs
+++ b/library/alloc/src/str.rs
@@ -1,26 +1,6 @@
-//! Unicode string slices.
+//! Utilities for the `str` primitive type.
 //!
 //! *[See also the `str` primitive type](str).*
-//!
-//! The `&str` type is one of the two main string types, the other being `String`.
-//! Unlike its `String` counterpart, its contents are borrowed.
-//!
-//! # Basic Usage
-//!
-//! A basic string declaration of `&str` type:
-//!
-//! ```
-//! let hello_world = "Hello, World!";
-//! ```
-//!
-//! Here we have declared a string literal, also known as a string slice.
-//! String literals have a static lifetime, which means the string `hello_world`
-//! is guaranteed to be valid for the duration of the entire program.
-//! We can explicitly specify `hello_world`'s lifetime as well:
-//!
-//! ```
-//! let hello_world: &'static str = "Hello, world!";
-//! ```
 
 #![stable(feature = "rust1", since = "1.0.0")]
 // Many of the usings in this module are only used in the test configuration.
@@ -71,6 +51,8 @@ pub use core::str::{RSplit, Split};
 pub use core::str::{RSplitN, SplitN};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::str::{RSplitTerminator, SplitTerminator};
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+pub use core::str::{Utf8Chunk, Utf8Chunks};
 
 /// Note: `str` in `Concat<str>` is not meaningful here.
 /// This type parameter of the trait only exists to enable another impl.
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index a5118e5333b..e28ace4795f 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -58,9 +58,9 @@ use core::ops::Bound::{Excluded, Included, Unbounded};
 use core::ops::{self, Index, IndexMut, Range, RangeBounds};
 use core::ptr;
 use core::slice;
-#[cfg(not(no_global_oom_handling))]
-use core::str::lossy;
 use core::str::pattern::Pattern;
+#[cfg(not(no_global_oom_handling))]
+use core::str::Utf8Chunks;
 
 #[cfg(not(no_global_oom_handling))]
 use crate::borrow::{Cow, ToOwned};
@@ -628,11 +628,11 @@ impl String {
     #[cfg(not(no_global_oom_handling))]
     #[stable(feature = "rust1", since = "1.0.0")]
     pub fn from_utf8_lossy(v: &[u8]) -> Cow<'_, str> {
-        let mut iter = lossy::Utf8Lossy::from_bytes(v).chunks();
+        let mut iter = Utf8Chunks::new(v);
 
         let first_valid = if let Some(chunk) = iter.next() {
-            let lossy::Utf8LossyChunk { valid, broken } = chunk;
-            if broken.is_empty() {
+            let valid = chunk.valid();
+            if chunk.invalid().is_empty() {
                 debug_assert_eq!(valid.len(), v.len());
                 return Cow::Borrowed(valid);
             }
@@ -647,9 +647,9 @@ impl String {
         res.push_str(first_valid);
         res.push_str(REPLACEMENT);
 
-        for lossy::Utf8LossyChunk { valid, broken } in iter {
-            res.push_str(valid);
-            if !broken.is_empty() {
+        for chunk in iter {
+            res.push_str(chunk.valid());
+            if !chunk.invalid().is_empty() {
                 res.push_str(REPLACEMENT);
             }
         }
@@ -1080,7 +1080,8 @@ impl String {
     /// current length. The allocator may reserve more space to speculatively
     /// avoid frequent allocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 202d0e7f020..0fae8953aa2 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -618,3 +618,22 @@ fn test_arc_cyclic_two_refs() {
     assert_eq!(Arc::strong_count(&two_refs), 3);
     assert_eq!(Arc::weak_count(&two_refs), 2);
 }
+
+/// Test for Arc::drop bug (https://github.com/rust-lang/rust/issues/55005)
+#[test]
+#[cfg(miri)] // relies on Stacked Borrows in Miri
+fn arc_drop_dereferenceable_race() {
+    // The bug seems to take up to 700 iterations to reproduce with most seeds (tested 0-9).
+    for _ in 0..750 {
+        let arc_1 = Arc::new(());
+        let arc_2 = arc_1.clone();
+        let thread = thread::spawn(|| drop(arc_2));
+        // Spin a bit; makes the race more likely to appear
+        let mut i = 0;
+        while i < 256 {
+            i += 1;
+        }
+        drop(arc_1);
+        thread.join().unwrap();
+    }
+}
diff --git a/library/alloc/src/vec/in_place_collect.rs b/library/alloc/src/vec/in_place_collect.rs
index 55dcb84ad16..b211421b202 100644
--- a/library/alloc/src/vec/in_place_collect.rs
+++ b/library/alloc/src/vec/in_place_collect.rs
@@ -267,7 +267,7 @@ where
             // one slot in the underlying storage will have been freed up and we can immediately
             // write back the result.
             unsafe {
-                let dst = dst_buf.offset(i as isize);
+                let dst = dst_buf.add(i);
                 debug_assert!(dst as *const _ <= end, "InPlaceIterable contract violation");
                 ptr::write(dst, self.__iterator_get_unchecked(i));
                 // Since this executes user code which can panic we have to bump the pointer
diff --git a/library/alloc/src/vec/into_iter.rs b/library/alloc/src/vec/into_iter.rs
index 1b483e3fc77..4351548811d 100644
--- a/library/alloc/src/vec/into_iter.rs
+++ b/library/alloc/src/vec/into_iter.rs
@@ -148,7 +148,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
 
     #[inline]
     fn next(&mut self) -> Option<T> {
-        if self.ptr as *const _ == self.end {
+        if self.ptr == self.end {
             None
         } else if mem::size_of::<T>() == 0 {
             // purposefully don't use 'ptr.offset' because for
@@ -160,7 +160,7 @@ impl<T, A: Allocator> Iterator for IntoIter<T, A> {
             Some(unsafe { mem::zeroed() })
         } else {
             let old = self.ptr;
-            self.ptr = unsafe { self.ptr.offset(1) };
+            self.ptr = unsafe { self.ptr.add(1) };
 
             Some(unsafe { ptr::read(old) })
         }
@@ -272,7 +272,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
             // Make up a value of this ZST.
             Some(unsafe { mem::zeroed() })
         } else {
-            self.end = unsafe { self.end.offset(-1) };
+            self.end = unsafe { self.end.sub(1) };
 
             Some(unsafe { ptr::read(self.end) })
         }
@@ -288,7 +288,7 @@ impl<T, A: Allocator> DoubleEndedIterator for IntoIter<T, A> {
             }
         } else {
             // SAFETY: same as for advance_by()
-            self.end = unsafe { self.end.offset(step_size.wrapping_neg() as isize) };
+            self.end = unsafe { self.end.sub(step_size) };
         }
         let to_drop = ptr::slice_from_raw_parts_mut(self.end as *mut T, step_size);
         // SAFETY: same as for advance_by()
diff --git a/library/alloc/src/vec/mod.rs b/library/alloc/src/vec/mod.rs
index fa9f2131c0c..2c786fd511e 100644
--- a/library/alloc/src/vec/mod.rs
+++ b/library/alloc/src/vec/mod.rs
@@ -542,8 +542,8 @@ impl<T> Vec<T> {
     ///
     /// unsafe {
     ///     // Overwrite memory with 4, 5, 6
-    ///     for i in 0..len as isize {
-    ///         ptr::write(p.offset(i), 4 + i);
+    ///     for i in 0..len {
+    ///         ptr::write(p.add(i), 4 + i);
     ///     }
     ///
     ///     // Put everything back together into a Vec
@@ -702,8 +702,8 @@ impl<T, A: Allocator> Vec<T, A> {
     ///
     /// unsafe {
     ///     // Overwrite memory with 4, 5, 6
-    ///     for i in 0..len as isize {
-    ///         ptr::write(p.offset(i), 4 + i);
+    ///     for i in 0..len {
+    ///         ptr::write(p.add(i), 4 + i);
     ///     }
     ///
     ///     // Put everything back together into a Vec
@@ -875,7 +875,8 @@ impl<T, A: Allocator> Vec<T, A> {
     /// in the given `Vec<T>`. The collection may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns
-    /// `Ok(())`. Does nothing if capacity is already sufficient.
+    /// `Ok(())`. Does nothing if capacity is already sufficient. This method
+    /// preserves the contents even if an error occurs.
     ///
     /// # Errors
     ///
@@ -1393,7 +1394,7 @@ impl<T, A: Allocator> Vec<T, A> {
                 if index < len {
                     // Shift everything over to make space. (Duplicating the
                     // `index`th element into two consecutive places.)
-                    ptr::copy(p, p.offset(1), len - index);
+                    ptr::copy(p, p.add(1), len - index);
                 } else if index == len {
                     // No elements need shifting.
                 } else {
@@ -1455,7 +1456,7 @@ impl<T, A: Allocator> Vec<T, A> {
                 ret = ptr::read(ptr);
 
                 // Shift everything down to fill in that spot.
-                ptr::copy(ptr.offset(1), ptr, len - index - 1);
+                ptr::copy(ptr.add(1), ptr, len - index - 1);
             }
             self.set_len(len - 1);
             ret
@@ -2408,7 +2409,7 @@ impl<T, A: Allocator> Vec<T, A> {
             // Write all elements except the last one
             for _ in 1..n {
                 ptr::write(ptr, value.next());
-                ptr = ptr.offset(1);
+                ptr = ptr.add(1);
                 // Increment the length in every step in case next() panics
                 local_len.increment_len(1);
             }
@@ -2927,6 +2928,8 @@ unsafe impl<#[may_dangle] T, A: Allocator> Drop for Vec<T, A> {
 #[rustc_const_unstable(feature = "const_default_impls", issue = "87864")]
 impl<T> const Default for Vec<T> {
     /// Creates an empty `Vec<T>`.
+    ///
+    /// The vector will not allocate until elements are pushed onto it.
     fn default() -> Vec<T> {
         Vec::new()
     }
diff --git a/library/alloc/src/vec/spec_extend.rs b/library/alloc/src/vec/spec_extend.rs
index 506ee0ecfa2..1ea9c827afd 100644
--- a/library/alloc/src/vec/spec_extend.rs
+++ b/library/alloc/src/vec/spec_extend.rs
@@ -39,7 +39,7 @@ where
                 let mut local_len = SetLenOnDrop::new(&mut self.len);
                 iterator.for_each(move |element| {
                     ptr::write(ptr, element);
-                    ptr = ptr.offset(1);
+                    ptr = ptr.add(1);
                     // Since the loop executes user code which can panic we have to bump the pointer
                     // after each step.
                     // NB can't overflow since we would have had to alloc the address space
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index d83cd29ddba..99bfb2a45ed 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -38,6 +38,7 @@
 #![feature(const_str_from_utf8)]
 #![feature(nonnull_slice_from_raw_parts)]
 #![feature(panic_update_hook)]
+#![feature(pointer_is_aligned)]
 #![feature(slice_flatten)]
 #![feature(thin_box)]
 #![feature(bench_black_box)]
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 7379569dd68..e30329aa1cb 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -1010,11 +1010,11 @@ fn test_as_bytes_fail() {
 fn test_as_ptr() {
     let buf = "hello".as_ptr();
     unsafe {
-        assert_eq!(*buf.offset(0), b'h');
-        assert_eq!(*buf.offset(1), b'e');
-        assert_eq!(*buf.offset(2), b'l');
-        assert_eq!(*buf.offset(3), b'l');
-        assert_eq!(*buf.offset(4), b'o');
+        assert_eq!(*buf.add(0), b'h');
+        assert_eq!(*buf.add(1), b'e');
+        assert_eq!(*buf.add(2), b'l');
+        assert_eq!(*buf.add(3), b'l');
+        assert_eq!(*buf.add(4), b'o');
     }
 }
 
diff --git a/library/alloc/tests/thin_box.rs b/library/alloc/tests/thin_box.rs
index 368aa564f94..e008b0cc357 100644
--- a/library/alloc/tests/thin_box.rs
+++ b/library/alloc/tests/thin_box.rs
@@ -48,11 +48,11 @@ fn verify_aligned<T>(ptr: *const T) {
     // practice these checks are mostly just smoke-detectors for an extremely
     // broken `ThinBox` impl, since it's an extremely subtle piece of code.
     let ptr = core::hint::black_box(ptr);
-    let align = core::mem::align_of::<T>();
     assert!(
-        (ptr.addr() & (align - 1)) == 0 && !ptr.is_null(),
-        "misaligned ThinBox data; valid pointers to `{}` should be aligned to {align}: {ptr:p}",
-        core::any::type_name::<T>(),
+        ptr.is_aligned() && !ptr.is_null(),
+        "misaligned ThinBox data; valid pointers to `{ty}` should be aligned to {align}: {ptr:p}",
+        ty = core::any::type_name::<T>(),
+        align = core::mem::align_of::<T>(),
     );
 }
 
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index d94da8f5f5a..5be4d5f1279 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -294,6 +294,22 @@ fn test_retain() {
 }
 
 #[test]
+fn test_retain_predicate_order() {
+    for to_keep in [true, false] {
+        let mut number_of_executions = 0;
+        let mut vec = vec![1, 2, 3, 4];
+        let mut next_expected = 1;
+        vec.retain(|&x| {
+            assert_eq!(next_expected, x);
+            next_expected += 1;
+            number_of_executions += 1;
+            to_keep
+        });
+        assert_eq!(number_of_executions, 4);
+    }
+}
+
+#[test]
 fn test_retain_pred_panic_with_hole() {
     let v = (0..5).map(Rc::new).collect::<Vec<_>>();
     catch_unwind(AssertUnwindSafe(|| {
@@ -355,6 +371,35 @@ fn test_retain_drop_panic() {
 }
 
 #[test]
+fn test_retain_maybeuninits() {
+    // This test aimed to be run under miri.
+    use core::mem::MaybeUninit;
+    let mut vec: Vec<_> = [1i32, 2, 3, 4].map(|v| MaybeUninit::new(vec![v])).into();
+    vec.retain(|x| {
+        // SAFETY: Retain must visit every element of Vec in original order and exactly once.
+        // Our values is initialized at creation of Vec.
+        let v = unsafe { x.assume_init_ref()[0] };
+        if v & 1 == 0 {
+            return true;
+        }
+        // SAFETY: Value is initialized.
+        // Value wouldn't be dropped by `Vec::retain`
+        // because `MaybeUninit` doesn't drop content.
+        drop(unsafe { x.assume_init_read() });
+        false
+    });
+    let vec: Vec<i32> = vec
+        .into_iter()
+        .map(|x| unsafe {
+            // SAFETY: All values dropped in retain predicate must be removed by `Vec::retain`.
+            // Remaining values are initialized.
+            x.assume_init()[0]
+        })
+        .collect();
+    assert_eq!(vec, [2, 4]);
+}
+
+#[test]
 fn test_dedup() {
     fn case(a: Vec<i32>, b: Vec<i32>) {
         let mut v = a;
diff --git a/library/core/src/any.rs b/library/core/src/any.rs
index f20c497a183..e54f6c912d5 100644
--- a/library/core/src/any.rs
+++ b/library/core/src/any.rs
@@ -1,7 +1,4 @@
-//! This module contains the `Any` trait, which enables dynamic typing
-//! of any `'static` type through runtime reflection. It also contains the
-//! `Provider` trait and accompanying API, which enable trait objects to provide
-//! data based on typed requests, an alternate form of runtime reflection.
+//! Utilities for dynamic typing or type reflection.
 //!
 //! # `Any` and `TypeId`
 //!
diff --git a/library/core/src/array/mod.rs b/library/core/src/array/mod.rs
index c9823a136bc..db5bfcab9d2 100644
--- a/library/core/src/array/mod.rs
+++ b/library/core/src/array/mod.rs
@@ -1,4 +1,4 @@
-//! Helper functions and types for fixed-length arrays.
+//! Utilities for the array primitive type.
 //!
 //! *[See also the array primitive type](array).*
 
diff --git a/library/core/src/borrow.rs b/library/core/src/borrow.rs
index 58eabecf3f0..8378611eb18 100644
--- a/library/core/src/borrow.rs
+++ b/library/core/src/borrow.rs
@@ -1,4 +1,4 @@
-//! A module for working with borrowed data.
+//! Utilities for working with borrowed data.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 0df23e7bbe6..a4bdd38f655 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -1,4 +1,6 @@
-//! A character type.
+//! Utilities for the `char` primitive type.
+//!
+//! *[See also the `char` primitive type](primitive@char).*
 //!
 //! The `char` type represents a single character. More specifically, since
 //! 'character' isn't a well-defined concept in Unicode, `char` is a '[Unicode
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index 171f4902236..8a30bb67450 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -1,6 +1,6 @@
-//! Functionality for ordering and comparison.
+//! Utilities for comparing and ordering values.
 //!
-//! This module contains various tools for ordering and comparing values. In
+//! This module contains various tools for comparing and ordering values. In
 //! summary:
 //!
 //! * [`Eq`] and [`PartialEq`] are traits that allow you to define total and
@@ -38,8 +38,10 @@ use self::Ordering::*;
 ///
 /// Implementations must ensure that `eq` and `ne` are consistent with each other:
 ///
-/// - `a != b` if and only if `!(a == b)`
-///   (ensured by the default implementation).
+/// - `a != b` if and only if `!(a == b)`.
+///
+/// The default implementation of `ne` provides this consistency and is almost
+/// always sufficient. It should not be overridden without very good reason.
 ///
 /// If [`PartialOrd`] or [`Ord`] are also implemented for `Self` and `Rhs`, their methods must also
 /// be consistent with `PartialEq` (see the documentation of those traits for the exact
@@ -225,7 +227,8 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
     #[stable(feature = "rust1", since = "1.0.0")]
     fn eq(&self, other: &Rhs) -> bool;
 
-    /// This method tests for `!=`.
+    /// This method tests for `!=`. The default implementation is almost always
+    /// sufficient, and should not be overridden without very good reason.
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/core/src/default.rs b/library/core/src/default.rs
index 1ce00828bf3..b53cd6074b5 100644
--- a/library/core/src/default.rs
+++ b/library/core/src/default.rs
@@ -1,4 +1,4 @@
-//! The `Default` trait for types which may have meaningful default values.
+//! The `Default` trait for types with a default value.
 
 #![stable(feature = "rust1", since = "1.0.0")]
 
diff --git a/library/core/src/intrinsics.rs b/library/core/src/intrinsics.rs
index 15467e0191d..441d2382686 100644
--- a/library/core/src/intrinsics.rs
+++ b/library/core/src/intrinsics.rs
@@ -2139,7 +2139,7 @@ pub(crate) use assert_unsafe_precondition;
 /// Checks whether `ptr` is properly aligned with respect to
 /// `align_of::<T>()`.
 pub(crate) fn is_aligned_and_not_null<T>(ptr: *const T) -> bool {
-    !ptr.is_null() && ptr.addr() % mem::align_of::<T>() == 0
+    !ptr.is_null() && ptr.is_aligned()
 }
 
 /// Checks whether the regions of memory starting at `src` and `dst` of size
@@ -2209,9 +2209,9 @@ pub(crate) fn is_nonoverlapping<T>(src: *const T, dst: *const T, count: usize) -
 ///     dst.reserve(src_len);
 ///
 ///     unsafe {
-///         // The call to offset is always safe because `Vec` will never
+///         // The call to add is always safe because `Vec` will never
 ///         // allocate more than `isize::MAX` bytes.
-///         let dst_ptr = dst.as_mut_ptr().offset(dst_len as isize);
+///         let dst_ptr = dst.as_mut_ptr().add(dst_len);
 ///         let src_ptr = src.as_ptr();
 ///
 ///         // Truncate `src` without dropping its contents. We do this first,
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 15a120e35a2..307016c2690 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -1,6 +1,6 @@
 use crate::fmt;
 use crate::iter::{DoubleEndedIterator, Fuse, FusedIterator, Iterator, Map, TrustedLen};
-use crate::ops::Try;
+use crate::ops::{ControlFlow, Try};
 
 /// An iterator that maps each element to an iterator, and yields the elements
 /// of the produced iterators.
@@ -73,6 +73,21 @@ where
     {
         self.inner.fold(init, fold)
     }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+        self.inner.advance_by(n)
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.inner.count()
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        self.inner.last()
+    }
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
@@ -103,6 +118,11 @@ where
     {
         self.inner.rfold(init, fold)
     }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+        self.inner.advance_back_by(n)
+    }
 }
 
 #[stable(feature = "fused", since = "1.26.0")]
@@ -214,6 +234,21 @@ where
     {
         self.inner.fold(init, fold)
     }
+
+    #[inline]
+    fn advance_by(&mut self, n: usize) -> Result<(), usize> {
+        self.inner.advance_by(n)
+    }
+
+    #[inline]
+    fn count(self) -> usize {
+        self.inner.count()
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        self.inner.last()
+    }
 }
 
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
@@ -244,6 +279,11 @@ where
     {
         self.inner.rfold(init, fold)
     }
+
+    #[inline]
+    fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
+        self.inner.advance_back_by(n)
+    }
 }
 
 #[stable(feature = "iterator_flatten", since = "1.29.0")]
@@ -280,6 +320,144 @@ where
     }
 }
 
+impl<I, U> FlattenCompat<I, U>
+where
+    I: Iterator<Item: IntoIterator<IntoIter = U>>,
+{
+    /// Folds the inner iterators into an accumulator by applying an operation.
+    ///
+    /// Folds over the inner iterators, not over their elements. Is used by the `fold`, `count`,
+    /// and `last` methods.
+    #[inline]
+    fn iter_fold<Acc, Fold>(self, mut acc: Acc, mut fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, U) -> Acc,
+    {
+        #[inline]
+        fn flatten<T: IntoIterator, Acc>(
+            fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc + '_ {
+            move |acc, iter| fold(acc, iter.into_iter())
+        }
+
+        if let Some(iter) = self.frontiter {
+            acc = fold(acc, iter);
+        }
+
+        acc = self.iter.fold(acc, flatten(&mut fold));
+
+        if let Some(iter) = self.backiter {
+            acc = fold(acc, iter);
+        }
+
+        acc
+    }
+
+    /// Folds over the inner iterators as long as the given function returns successfully,
+    /// always storing the most recent inner iterator in `self.frontiter`.
+    ///
+    /// Folds over the inner iterators, not over their elements. Is used by the `try_fold` and
+    /// `advance_by` methods.
+    #[inline]
+    fn iter_try_fold<Acc, Fold, R>(&mut self, mut acc: Acc, mut fold: Fold) -> R
+    where
+        Fold: FnMut(Acc, &mut U) -> R,
+        R: Try<Output = Acc>,
+    {
+        #[inline]
+        fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
+            frontiter: &'a mut Option<T::IntoIter>,
+            fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R,
+        ) -> impl FnMut(Acc, T) -> R + 'a {
+            move |acc, iter| fold(acc, frontiter.insert(iter.into_iter()))
+        }
+
+        if let Some(iter) = &mut self.frontiter {
+            acc = fold(acc, iter)?;
+        }
+        self.frontiter = None;
+
+        acc = self.iter.try_fold(acc, flatten(&mut self.frontiter, &mut fold))?;
+        self.frontiter = None;
+
+        if let Some(iter) = &mut self.backiter {
+            acc = fold(acc, iter)?;
+        }
+        self.backiter = None;
+
+        try { acc }
+    }
+}
+
+impl<I, U> FlattenCompat<I, U>
+where
+    I: DoubleEndedIterator<Item: IntoIterator<IntoIter = U>>,
+{
+    /// Folds the inner iterators into an accumulator by applying an operation, starting form the
+    /// back.
+    ///
+    /// Folds over the inner iterators, not over their elements. Is used by the `rfold` method.
+    #[inline]
+    fn iter_rfold<Acc, Fold>(self, mut acc: Acc, mut fold: Fold) -> Acc
+    where
+        Fold: FnMut(Acc, U) -> Acc,
+    {
+        #[inline]
+        fn flatten<T: IntoIterator, Acc>(
+            fold: &mut impl FnMut(Acc, T::IntoIter) -> Acc,
+        ) -> impl FnMut(Acc, T) -> Acc + '_ {
+            move |acc, iter| fold(acc, iter.into_iter())
+        }
+
+        if let Some(iter) = self.backiter {
+            acc = fold(acc, iter);
+        }
+
+        acc = self.iter.rfold(acc, flatten(&mut fold));
+
+        if let Some(iter) = self.frontiter {
+            acc = fold(acc, iter);
+        }
+
+        acc
+    }
+
+    /// Folds over the inner iterators in reverse order as long as the given function returns
+    /// successfully, always storing the most recent inner iterator in `self.backiter`.
+    ///
+    /// Folds over the inner iterators, not over their elements. Is used by the `try_rfold` and
+    /// `advance_back_by` methods.
+    #[inline]
+    fn iter_try_rfold<Acc, Fold, R>(&mut self, mut acc: Acc, mut fold: Fold) -> R
+    where
+        Fold: FnMut(Acc, &mut U) -> R,
+        R: Try<Output = Acc>,
+    {
+        #[inline]
+        fn flatten<'a, T: IntoIterator, Acc, R: Try>(
+            backiter: &'a mut Option<T::IntoIter>,
+            fold: &'a mut impl FnMut(Acc, &mut T::IntoIter) -> R,
+        ) -> impl FnMut(Acc, T) -> R + 'a {
+            move |acc, iter| fold(acc, backiter.insert(iter.into_iter()))
+        }
+
+        if let Some(iter) = &mut self.backiter {
+            acc = fold(acc, iter)?;
+        }
+        self.backiter = None;
+
+        acc = self.iter.try_rfold(acc, flatten(&mut self.backiter, &mut fold))?;
+        self.backiter = None;
+
+        if let Some(iter) = &mut self.frontiter {
+            acc = fold(acc, iter)?;
+        }
+        self.frontiter = None;
+
+        try { acc }
+    }
+}
+
 impl<I, U> Iterator for FlattenCompat<I, U>
 where
     I: Iterator<Item: IntoIterator<IntoIter = U, Item = U::Item>>,
@@ -323,99 +501,74 @@ where
     }
 
     #[inline]
-    fn try_fold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
+    fn try_fold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>,
     {
         #[inline]
-        fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
-            frontiter: &'a mut Option<T::IntoIter>,
-            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
-        ) -> impl FnMut(Acc, T) -> R + 'a {
-            move |acc, x| {
-                let mut mid = x.into_iter();
-                let r = mid.try_fold(acc, &mut *fold);
-                *frontiter = Some(mid);
-                r
-            }
-        }
-
-        if let Some(ref mut front) = self.frontiter {
-            init = front.try_fold(init, &mut fold)?;
+        fn flatten<U: Iterator, Acc, R: Try<Output = Acc>>(
+            mut fold: impl FnMut(Acc, U::Item) -> R,
+        ) -> impl FnMut(Acc, &mut U) -> R {
+            move |acc, iter| iter.try_fold(acc, &mut fold)
         }
-        self.frontiter = None;
 
-        init = self.iter.try_fold(init, flatten(&mut self.frontiter, &mut fold))?;
-        self.frontiter = None;
-
-        if let Some(ref mut back) = self.backiter {
-            init = back.try_fold(init, &mut fold)?;
-        }
-        self.backiter = None;
-
-        try { init }
+        self.iter_try_fold(init, flatten(fold))
     }
 
     #[inline]
-    fn fold<Acc, Fold>(self, mut init: Acc, mut fold: Fold) -> Acc
+    fn fold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
         #[inline]
-        fn flatten<T: IntoIterator, Acc>(
-            fold: &mut impl FnMut(Acc, T::Item) -> Acc,
-        ) -> impl FnMut(Acc, T) -> Acc + '_ {
-            move |acc, x| x.into_iter().fold(acc, &mut *fold)
-        }
-
-        if let Some(front) = self.frontiter {
-            init = front.fold(init, &mut fold);
-        }
-
-        init = self.iter.fold(init, flatten(&mut fold));
-
-        if let Some(back) = self.backiter {
-            init = back.fold(init, &mut fold);
+        fn flatten<U: Iterator, Acc>(
+            mut fold: impl FnMut(Acc, U::Item) -> Acc,
+        ) -> impl FnMut(Acc, U) -> Acc {
+            move |acc, iter| iter.fold(acc, &mut fold)
         }
 
-        init
+        self.iter_fold(init, flatten(fold))
     }
 
     #[inline]
     #[rustc_inherit_overflow_checks]
     fn advance_by(&mut self, n: usize) -> Result<(), usize> {
-        let mut rem = n;
-        loop {
-            if let Some(ref mut front) = self.frontiter {
-                match front.advance_by(rem) {
-                    ret @ Ok(_) => return ret,
-                    Err(advanced) => rem -= advanced,
-                }
-            }
-            self.frontiter = match self.iter.next() {
-                Some(iterable) => Some(iterable.into_iter()),
-                _ => break,
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        fn advance<U: Iterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
+            match iter.advance_by(n) {
+                Ok(()) => ControlFlow::BREAK,
+                Err(advanced) => ControlFlow::Continue(n - advanced),
             }
         }
 
-        self.frontiter = None;
-
-        if let Some(ref mut back) = self.backiter {
-            match back.advance_by(rem) {
-                ret @ Ok(_) => return ret,
-                Err(advanced) => rem -= advanced,
-            }
+        match self.iter_try_fold(n, advance) {
+            ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
+            _ => Ok(()),
         }
+    }
 
-        if rem > 0 {
-            return Err(n - rem);
+    #[inline]
+    fn count(self) -> usize {
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        fn count<U: Iterator>(acc: usize, iter: U) -> usize {
+            acc + iter.count()
         }
 
-        self.backiter = None;
+        self.iter_fold(0, count)
+    }
+
+    #[inline]
+    fn last(self) -> Option<Self::Item> {
+        #[inline]
+        fn last<U: Iterator>(last: Option<U::Item>, iter: U) -> Option<U::Item> {
+            iter.last().or(last)
+        }
 
-        Ok(())
+        self.iter_fold(None, last)
     }
 }
 
@@ -438,105 +591,53 @@ where
     }
 
     #[inline]
-    fn try_rfold<Acc, Fold, R>(&mut self, mut init: Acc, mut fold: Fold) -> R
+    fn try_rfold<Acc, Fold, R>(&mut self, init: Acc, fold: Fold) -> R
     where
         Self: Sized,
         Fold: FnMut(Acc, Self::Item) -> R,
         R: Try<Output = Acc>,
     {
         #[inline]
-        fn flatten<'a, T: IntoIterator, Acc, R: Try<Output = Acc>>(
-            backiter: &'a mut Option<T::IntoIter>,
-            fold: &'a mut impl FnMut(Acc, T::Item) -> R,
-        ) -> impl FnMut(Acc, T) -> R + 'a
-        where
-            T::IntoIter: DoubleEndedIterator,
-        {
-            move |acc, x| {
-                let mut mid = x.into_iter();
-                let r = mid.try_rfold(acc, &mut *fold);
-                *backiter = Some(mid);
-                r
-            }
+        fn flatten<U: DoubleEndedIterator, Acc, R: Try<Output = Acc>>(
+            mut fold: impl FnMut(Acc, U::Item) -> R,
+        ) -> impl FnMut(Acc, &mut U) -> R {
+            move |acc, iter| iter.try_rfold(acc, &mut fold)
         }
 
-        if let Some(ref mut back) = self.backiter {
-            init = back.try_rfold(init, &mut fold)?;
-        }
-        self.backiter = None;
-
-        init = self.iter.try_rfold(init, flatten(&mut self.backiter, &mut fold))?;
-        self.backiter = None;
-
-        if let Some(ref mut front) = self.frontiter {
-            init = front.try_rfold(init, &mut fold)?;
-        }
-        self.frontiter = None;
-
-        try { init }
+        self.iter_try_rfold(init, flatten(fold))
     }
 
     #[inline]
-    fn rfold<Acc, Fold>(self, mut init: Acc, mut fold: Fold) -> Acc
+    fn rfold<Acc, Fold>(self, init: Acc, fold: Fold) -> Acc
     where
         Fold: FnMut(Acc, Self::Item) -> Acc,
     {
         #[inline]
-        fn flatten<T: IntoIterator, Acc>(
-            fold: &mut impl FnMut(Acc, T::Item) -> Acc,
-        ) -> impl FnMut(Acc, T) -> Acc + '_
-        where
-            T::IntoIter: DoubleEndedIterator,
-        {
-            move |acc, x| x.into_iter().rfold(acc, &mut *fold)
-        }
-
-        if let Some(back) = self.backiter {
-            init = back.rfold(init, &mut fold);
+        fn flatten<U: DoubleEndedIterator, Acc>(
+            mut fold: impl FnMut(Acc, U::Item) -> Acc,
+        ) -> impl FnMut(Acc, U) -> Acc {
+            move |acc, iter| iter.rfold(acc, &mut fold)
         }
 
-        init = self.iter.rfold(init, flatten(&mut fold));
-
-        if let Some(front) = self.frontiter {
-            init = front.rfold(init, &mut fold);
-        }
-
-        init
+        self.iter_rfold(init, flatten(fold))
     }
 
     #[inline]
     #[rustc_inherit_overflow_checks]
     fn advance_back_by(&mut self, n: usize) -> Result<(), usize> {
-        let mut rem = n;
-        loop {
-            if let Some(ref mut back) = self.backiter {
-                match back.advance_back_by(rem) {
-                    ret @ Ok(_) => return ret,
-                    Err(advanced) => rem -= advanced,
-                }
-            }
-            match self.iter.next_back() {
-                Some(iterable) => self.backiter = Some(iterable.into_iter()),
-                _ => break,
-            }
-        }
-
-        self.backiter = None;
-
-        if let Some(ref mut front) = self.frontiter {
-            match front.advance_back_by(rem) {
-                ret @ Ok(_) => return ret,
-                Err(advanced) => rem -= advanced,
+        #[inline]
+        #[rustc_inherit_overflow_checks]
+        fn advance<U: DoubleEndedIterator>(n: usize, iter: &mut U) -> ControlFlow<(), usize> {
+            match iter.advance_back_by(n) {
+                Ok(()) => ControlFlow::BREAK,
+                Err(advanced) => ControlFlow::Continue(n - advanced),
             }
         }
 
-        if rem > 0 {
-            return Err(n - rem);
+        match self.iter_try_rfold(n, advance) {
+            ControlFlow::Continue(remaining) if remaining > 0 => Err(n - remaining),
+            _ => Ok(()),
         }
-
-        self.frontiter = None;
-
-        Ok(())
     }
 }
 
diff --git a/library/core/src/num/f32.rs b/library/core/src/num/f32.rs
index 23c46f1a74a..509a6c3cac5 100644
--- a/library/core/src/num/f32.rs
+++ b/library/core/src/num/f32.rs
@@ -1,4 +1,4 @@
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type][f32].*
 //!
@@ -1282,15 +1282,14 @@ impl f32 {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
-    pub fn clamp(self, min: f32, max: f32) -> f32 {
+    pub fn clamp(mut self, min: f32, max: f32) -> f32 {
         assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
+        if self < min {
+            self = min;
         }
-        if x > max {
-            x = max;
+        if self > max {
+            self = max;
         }
-        x
+        self
     }
 }
diff --git a/library/core/src/num/f64.rs b/library/core/src/num/f64.rs
index b5c8241d294..5aeaa4b9ada 100644
--- a/library/core/src/num/f64.rs
+++ b/library/core/src/num/f64.rs
@@ -1,4 +1,4 @@
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type][f64].*
 //!
@@ -1280,15 +1280,14 @@ impl f64 {
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "clamp", since = "1.50.0")]
     #[inline]
-    pub fn clamp(self, min: f64, max: f64) -> f64 {
+    pub fn clamp(mut self, min: f64, max: f64) -> f64 {
         assert!(min <= max);
-        let mut x = self;
-        if x < min {
-            x = min;
+        if self < min {
+            self = min;
         }
-        if x > max {
-            x = max;
+        if self > max {
+            self = max;
         }
-        x
+        self
     }
 }
diff --git a/library/core/src/num/mod.rs b/library/core/src/num/mod.rs
index f481399fdcf..72b6dc28185 100644
--- a/library/core/src/num/mod.rs
+++ b/library/core/src/num/mod.rs
@@ -623,7 +623,7 @@ impl u8 {
     ///
     /// - U+0021 ..= U+002F `! " # $ % & ' ( ) * + , - . /`, or
     /// - U+003A ..= U+0040 `: ; < = > ? @`, or
-    /// - U+005B ..= U+0060 ``[ \ ] ^ _ ` ``, or
+    /// - U+005B ..= U+0060 `` [ \ ] ^ _ ` ``, or
     /// - U+007B ..= U+007E `{ | } ~`
     ///
     /// # Examples
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index 1c14b9341ca..2b2ef64fdb1 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -801,11 +801,53 @@ mod prim_array {}
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
 /// ```
+///
+/// ## Trait Implementations
+///
+/// Some traits are implemented for slices if the element type implements
+/// that trait. This includes [`Eq`], [`Hash`] and [`Ord`].
+///
+/// ## Iteration
+///
+/// The slices implement `IntoIterator`. The iterator yields references to the
+/// slice elements.
+///
+/// ```
+/// let numbers: &[i32] = &[0, 1, 2];
+/// for n in numbers {
+///     println!("{n} is a number!");
+/// }
+/// ```
+///
+/// The mutable slice yields mutable references to the elements:
+///
+/// ```
+/// let mut scores: &mut [i32] = &mut [7, 8, 9];
+/// for score in scores {
+///     *score += 1;
+/// }
+/// ```
+///
+/// This iterator yields mutable references to the slice's elements, so while
+/// the element type of the slice is `i32`, the element type of the iterator is
+/// `&mut i32`.
+///
+/// * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
+///   iterators.
+/// * Further methods that return iterators are [`.split`], [`.splitn`],
+///   [`.chunks`], [`.windows`] and more.
+///
+/// [`Hash`]: core::hash::Hash
+/// [`.iter`]: slice::iter
+/// [`.iter_mut`]: slice::iter_mut
+/// [`.split`]: slice::split
+/// [`.splitn`]: slice::splitn
+/// [`.chunks`]: slice::chunks
+/// [`.windows`]: slice::windows
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
 #[doc(primitive = "str")]
-//
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -816,19 +858,22 @@ mod prim_slice {}
 ///
 /// String slices are always valid UTF-8.
 ///
-/// # Examples
+/// # Basic Usage
 ///
 /// String literals are string slices:
 ///
 /// ```
-/// let hello = "Hello, world!";
-///
-/// // with an explicit type annotation
-/// let hello: &'static str = "Hello, world!";
+/// let hello_world = "Hello, World!";
 /// ```
 ///
-/// They are `'static` because they're stored directly in the final binary, and
-/// so will be valid for the `'static` duration.
+/// Here we have declared a string slice initialized with a string literal.
+/// String literals have a static lifetime, which means the string `hello_world`
+/// is guaranteed to be valid for the duration of the entire program.
+/// We can explicitly specify `hello_world`'s lifetime as well:
+///
+/// ```
+/// let hello_world: &'static str = "Hello, world!";
+/// ```
 ///
 /// # Representation
 ///
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index e79d47c9f98..ea6a70c2f4e 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -674,8 +674,9 @@ impl<T> [T] {
     /// assert!(v == [3, 2, 1]);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[rustc_const_unstable(feature = "const_reverse", issue = "100784")]
     #[inline]
-    pub fn reverse(&mut self) {
+    pub const fn reverse(&mut self) {
         let half_len = self.len() / 2;
         let Range { start, end } = self.as_mut_ptr_range();
 
@@ -698,9 +699,9 @@ impl<T> [T] {
         revswap(front_half, back_half, half_len);
 
         #[inline]
-        fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
-            debug_assert_eq!(a.len(), n);
-            debug_assert_eq!(b.len(), n);
+        const fn revswap<T>(a: &mut [T], b: &mut [T], n: usize) {
+            debug_assert!(a.len() == n);
+            debug_assert!(b.len() == n);
 
             // Because this function is first compiled in isolation,
             // this check tells LLVM that the indexing below is
@@ -708,8 +709,10 @@ impl<T> [T] {
             // lengths of the slices are known -- it's removed.
             let (a, b) = (&mut a[..n], &mut b[..n]);
 
-            for i in 0..n {
+            let mut i = 0;
+            while i < n {
                 mem::swap(&mut a[i], &mut b[n - 1 - i]);
+                i += 1;
             }
         }
     }
@@ -2921,7 +2924,7 @@ impl<T> [T] {
                 let prev_ptr_write = ptr.add(next_write - 1);
                 if !same_bucket(&mut *ptr_read, &mut *prev_ptr_write) {
                     if next_read != next_write {
-                        let ptr_write = prev_ptr_write.offset(1);
+                        let ptr_write = prev_ptr_write.add(1);
                         mem::swap(&mut *ptr_read, &mut *ptr_write);
                     }
                     next_write += 1;
diff --git a/library/core/src/slice/sort.rs b/library/core/src/slice/sort.rs
index 6a201834b8e..8b025da2a46 100644
--- a/library/core/src/slice/sort.rs
+++ b/library/core/src/slice/sort.rs
@@ -326,8 +326,8 @@ where
                 unsafe {
                     // Branchless comparison.
                     *end_l = i as u8;
-                    end_l = end_l.offset(!is_less(&*elem, pivot) as isize);
-                    elem = elem.offset(1);
+                    end_l = end_l.add(!is_less(&*elem, pivot) as usize);
+                    elem = elem.add(1);
                 }
             }
         }
@@ -352,9 +352,9 @@ where
                 //        Plus, `block_r` was asserted to be less than `BLOCK` and `elem` will therefore at most be pointing to the beginning of the slice.
                 unsafe {
                     // Branchless comparison.
-                    elem = elem.offset(-1);
+                    elem = elem.sub(1);
                     *end_r = i as u8;
-                    end_r = end_r.offset(is_less(&*elem, pivot) as isize);
+                    end_r = end_r.add(is_less(&*elem, pivot) as usize);
                 }
             }
         }
@@ -365,12 +365,12 @@ where
         if count > 0 {
             macro_rules! left {
                 () => {
-                    l.offset(*start_l as isize)
+                    l.add(*start_l as usize)
                 };
             }
             macro_rules! right {
                 () => {
-                    r.offset(-(*start_r as isize) - 1)
+                    r.sub((*start_r as usize) + 1)
                 };
             }
 
@@ -398,16 +398,16 @@ where
                 ptr::copy_nonoverlapping(right!(), left!(), 1);
 
                 for _ in 1..count {
-                    start_l = start_l.offset(1);
+                    start_l = start_l.add(1);
                     ptr::copy_nonoverlapping(left!(), right!(), 1);
-                    start_r = start_r.offset(1);
+                    start_r = start_r.add(1);
                     ptr::copy_nonoverlapping(right!(), left!(), 1);
                 }
 
                 ptr::copy_nonoverlapping(&tmp, right!(), 1);
                 mem::forget(tmp);
-                start_l = start_l.offset(1);
-                start_r = start_r.offset(1);
+                start_l = start_l.add(1);
+                start_r = start_r.add(1);
             }
         }
 
@@ -420,7 +420,7 @@ where
             // safe. Otherwise, the debug assertions in the `is_done` case guarantee that
             // `width(l, r) == block_l + block_r`, namely, that the block sizes have been adjusted to account
             // for the smaller number of remaining elements.
-            l = unsafe { l.offset(block_l as isize) };
+            l = unsafe { l.add(block_l) };
         }
 
         if start_r == end_r {
@@ -428,7 +428,7 @@ where
 
             // SAFETY: Same argument as [block-width-guarantee]. Either this is a full block `2*BLOCK`-wide,
             // or `block_r` has been adjusted for the last handful of elements.
-            r = unsafe { r.offset(-(block_r as isize)) };
+            r = unsafe { r.sub(block_r) };
         }
 
         if is_done {
@@ -457,9 +457,9 @@ where
             //  - `offsets_l` contains valid offsets into `v` collected during the partitioning of
             //    the last block, so the `l.offset` calls are valid.
             unsafe {
-                end_l = end_l.offset(-1);
-                ptr::swap(l.offset(*end_l as isize), r.offset(-1));
-                r = r.offset(-1);
+                end_l = end_l.sub(1);
+                ptr::swap(l.add(*end_l as usize), r.sub(1));
+                r = r.sub(1);
             }
         }
         width(v.as_mut_ptr(), r)
@@ -470,9 +470,9 @@ where
         while start_r < end_r {
             // SAFETY: See the reasoning in [remaining-elements-safety].
             unsafe {
-                end_r = end_r.offset(-1);
-                ptr::swap(l, r.offset(-(*end_r as isize) - 1));
-                l = l.offset(1);
+                end_r = end_r.sub(1);
+                ptr::swap(l, r.sub((*end_r as usize) + 1));
+                l = l.add(1);
             }
         }
         width(v.as_mut_ptr(), l)
diff --git a/library/core/src/str/lossy.rs b/library/core/src/str/lossy.rs
index 6ec1c93908f..59f873d1268 100644
--- a/library/core/src/str/lossy.rs
+++ b/library/core/src/str/lossy.rs
@@ -1,51 +1,170 @@
-use crate::char;
-use crate::fmt::{self, Write};
-use crate::mem;
+use crate::fmt;
+use crate::fmt::Formatter;
+use crate::fmt::Write;
+use crate::iter::FusedIterator;
 
 use super::from_utf8_unchecked;
 use super::validations::utf8_char_width;
 
-/// Lossy UTF-8 string.
-#[unstable(feature = "str_internals", issue = "none")]
-pub struct Utf8Lossy {
-    bytes: [u8],
+/// An item returned by the [`Utf8Chunks`] iterator.
+///
+/// A `Utf8Chunk` stores a sequence of [`u8`] up to the first broken character
+/// when decoding a UTF-8 string.
+///
+/// # Examples
+///
+/// ```
+/// #![feature(utf8_chunks)]
+///
+/// use std::str::Utf8Chunks;
+///
+/// // An invalid UTF-8 string
+/// let bytes = b"foo\xF1\x80bar";
+///
+/// // Decode the first `Utf8Chunk`
+/// let chunk = Utf8Chunks::new(bytes).next().unwrap();
+///
+/// // The first three characters are valid UTF-8
+/// assert_eq!("foo", chunk.valid());
+///
+/// // The fourth character is broken
+/// assert_eq!(b"\xF1\x80", chunk.invalid());
+/// ```
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+#[derive(Clone, Debug, PartialEq, Eq)]
+pub struct Utf8Chunk<'a> {
+    valid: &'a str,
+    invalid: &'a [u8],
 }
 
-impl Utf8Lossy {
+impl<'a> Utf8Chunk<'a> {
+    /// Returns the next validated UTF-8 substring.
+    ///
+    /// This substring can be empty at the start of the string or between
+    /// broken UTF-8 characters.
     #[must_use]
-    pub fn from_bytes(bytes: &[u8]) -> &Utf8Lossy {
-        // SAFETY: Both use the same memory layout, and UTF-8 correctness isn't required.
-        unsafe { mem::transmute(bytes) }
+    #[unstable(feature = "utf8_chunks", issue = "99543")]
+    pub fn valid(&self) -> &'a str {
+        self.valid
     }
 
-    pub fn chunks(&self) -> Utf8LossyChunksIter<'_> {
-        Utf8LossyChunksIter { source: &self.bytes }
+    /// Returns the invalid sequence that caused a failure.
+    ///
+    /// The returned slice will have a maximum length of 3 and starts after the
+    /// substring given by [`valid`]. Decoding will resume after this sequence.
+    ///
+    /// If empty, this is the last chunk in the string. If non-empty, an
+    /// unexpected byte was encountered or the end of the input was reached
+    /// unexpectedly.
+    ///
+    /// Lossy decoding would replace this sequence with [`U+FFFD REPLACEMENT
+    /// CHARACTER`].
+    ///
+    /// [`valid`]: Self::valid
+    /// [`U+FFFD REPLACEMENT CHARACTER`]: crate::char::REPLACEMENT_CHARACTER
+    #[must_use]
+    #[unstable(feature = "utf8_chunks", issue = "99543")]
+    pub fn invalid(&self) -> &'a [u8] {
+        self.invalid
     }
 }
 
-/// Iterator over lossy UTF-8 string
-#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[must_use]
+#[unstable(feature = "str_internals", issue = "none")]
+pub struct Debug<'a>(&'a [u8]);
+
 #[unstable(feature = "str_internals", issue = "none")]
-#[allow(missing_debug_implementations)]
-pub struct Utf8LossyChunksIter<'a> {
+impl fmt::Debug for Debug<'_> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        f.write_char('"')?;
+
+        for chunk in Utf8Chunks::new(self.0) {
+            // Valid part.
+            // Here we partially parse UTF-8 again which is suboptimal.
+            {
+                let valid = chunk.valid();
+                let mut from = 0;
+                for (i, c) in valid.char_indices() {
+                    let esc = c.escape_debug();
+                    // If char needs escaping, flush backlog so far and write, else skip
+                    if esc.len() != 1 {
+                        f.write_str(&valid[from..i])?;
+                        for c in esc {
+                            f.write_char(c)?;
+                        }
+                        from = i + c.len_utf8();
+                    }
+                }
+                f.write_str(&valid[from..])?;
+            }
+
+            // Broken parts of string as hex escape.
+            for &b in chunk.invalid() {
+                write!(f, "\\x{:02X}", b)?;
+            }
+        }
+
+        f.write_char('"')
+    }
+}
+
+/// An iterator used to decode a slice of mostly UTF-8 bytes to string slices
+/// ([`&str`]) and byte slices ([`&[u8]`][byteslice]).
+///
+/// If you want a simple conversion from UTF-8 byte slices to string slices,
+/// [`from_utf8`] is easier to use.
+///
+/// [byteslice]: slice
+/// [`from_utf8`]: super::from_utf8
+///
+/// # Examples
+///
+/// This can be used to create functionality similar to
+/// [`String::from_utf8_lossy`] without allocating heap memory:
+///
+/// ```
+/// #![feature(utf8_chunks)]
+///
+/// use std::str::Utf8Chunks;
+///
+/// fn from_utf8_lossy<F>(input: &[u8], mut push: F) where F: FnMut(&str) {
+///     for chunk in Utf8Chunks::new(input) {
+///         push(chunk.valid());
+///
+///         if !chunk.invalid().is_empty() {
+///             push("\u{FFFD}");
+///         }
+///     }
+/// }
+/// ```
+///
+/// [`String::from_utf8_lossy`]: ../../std/string/struct.String.html#method.from_utf8_lossy
+#[must_use = "iterators are lazy and do nothing unless consumed"]
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+#[derive(Clone)]
+pub struct Utf8Chunks<'a> {
     source: &'a [u8],
 }
 
-#[unstable(feature = "str_internals", issue = "none")]
-#[derive(PartialEq, Eq, Debug)]
-pub struct Utf8LossyChunk<'a> {
-    /// Sequence of valid chars.
-    /// Can be empty between broken UTF-8 chars.
-    pub valid: &'a str,
-    /// Single broken char, empty if none.
-    /// Empty iff iterator item is last.
-    pub broken: &'a [u8],
+impl<'a> Utf8Chunks<'a> {
+    /// Creates a new iterator to decode the bytes.
+    #[unstable(feature = "utf8_chunks", issue = "99543")]
+    pub fn new(bytes: &'a [u8]) -> Self {
+        Self { source: bytes }
+    }
+
+    #[doc(hidden)]
+    #[unstable(feature = "str_internals", issue = "none")]
+    pub fn debug(&self) -> Debug<'_> {
+        Debug(self.source)
+    }
 }
 
-impl<'a> Iterator for Utf8LossyChunksIter<'a> {
-    type Item = Utf8LossyChunk<'a>;
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+impl<'a> Iterator for Utf8Chunks<'a> {
+    type Item = Utf8Chunk<'a>;
 
-    fn next(&mut self) -> Option<Utf8LossyChunk<'a>> {
+    fn next(&mut self) -> Option<Utf8Chunk<'a>> {
         if self.source.is_empty() {
             return None;
         }
@@ -130,71 +249,22 @@ impl<'a> Iterator for Utf8LossyChunksIter<'a> {
 
         // SAFETY: `valid_up_to <= i` because it is only ever assigned via
         // `valid_up_to = i` and `i` only increases.
-        let (valid, broken) = unsafe { inspected.split_at_unchecked(valid_up_to) };
+        let (valid, invalid) = unsafe { inspected.split_at_unchecked(valid_up_to) };
 
-        Some(Utf8LossyChunk {
+        Some(Utf8Chunk {
             // SAFETY: All bytes up to `valid_up_to` are valid UTF-8.
             valid: unsafe { from_utf8_unchecked(valid) },
-            broken,
+            invalid,
         })
     }
 }
 
-impl fmt::Display for Utf8Lossy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // If we're the empty string then our iterator won't actually yield
-        // anything, so perform the formatting manually
-        if self.bytes.is_empty() {
-            return "".fmt(f);
-        }
-
-        for Utf8LossyChunk { valid, broken } in self.chunks() {
-            // If we successfully decoded the whole chunk as a valid string then
-            // we can return a direct formatting of the string which will also
-            // respect various formatting flags if possible.
-            if valid.len() == self.bytes.len() {
-                assert!(broken.is_empty());
-                return valid.fmt(f);
-            }
-
-            f.write_str(valid)?;
-            if !broken.is_empty() {
-                f.write_char(char::REPLACEMENT_CHARACTER)?;
-            }
-        }
-        Ok(())
-    }
-}
-
-impl fmt::Debug for Utf8Lossy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        f.write_char('"')?;
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+impl FusedIterator for Utf8Chunks<'_> {}
 
-        for Utf8LossyChunk { valid, broken } in self.chunks() {
-            // Valid part.
-            // Here we partially parse UTF-8 again which is suboptimal.
-            {
-                let mut from = 0;
-                for (i, c) in valid.char_indices() {
-                    let esc = c.escape_debug();
-                    // If char needs escaping, flush backlog so far and write, else skip
-                    if esc.len() != 1 {
-                        f.write_str(&valid[from..i])?;
-                        for c in esc {
-                            f.write_char(c)?;
-                        }
-                        from = i + c.len_utf8();
-                    }
-                }
-                f.write_str(&valid[from..])?;
-            }
-
-            // Broken parts of string as hex escape.
-            for &b in broken {
-                write!(f, "\\x{:02x}", b)?;
-            }
-        }
-
-        f.write_char('"')
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+impl fmt::Debug for Utf8Chunks<'_> {
+    fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
+        f.debug_struct("Utf8Chunks").field("source", &self.debug()).finish()
     }
 }
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index ee66895a7ed..e44e025aaf1 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -22,9 +22,9 @@ use crate::slice::{self, SliceIndex};
 
 pub mod pattern;
 
-#[unstable(feature = "str_internals", issue = "none")]
-#[allow(missing_docs)]
-pub mod lossy;
+mod lossy;
+#[unstable(feature = "utf8_chunks", issue = "99543")]
+pub use lossy::{Utf8Chunk, Utf8Chunks};
 
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use converts::{from_utf8, from_utf8_unchecked};
diff --git a/library/core/src/str/validations.rs b/library/core/src/str/validations.rs
index 04bc665233e..2acef432f20 100644
--- a/library/core/src/str/validations.rs
+++ b/library/core/src/str/validations.rs
@@ -216,12 +216,12 @@ pub(super) const fn run_utf8_validation(v: &[u8]) -> Result<(), Utf8Error> {
                     // SAFETY: since `align - index` and `ascii_block_size` are
                     // multiples of `usize_bytes`, `block = ptr.add(index)` is
                     // always aligned with a `usize` so it's safe to dereference
-                    // both `block` and `block.offset(1)`.
+                    // both `block` and `block.add(1)`.
                     unsafe {
                         let block = ptr.add(index) as *const usize;
                         // break if there is a nonascii byte
                         let zu = contains_nonascii(*block);
-                        let zv = contains_nonascii(*block.offset(1));
+                        let zv = contains_nonascii(*block.add(1));
                         if zu || zv {
                             break;
                         }
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 40ca9abd6bd..3c96290fc53 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -1554,8 +1554,8 @@ impl<T> AtomicPtr<T> {
     /// Offsets the pointer's address by adding `val` *bytes*, returning the
     /// previous pointer.
     ///
-    /// This is equivalent to using [`wrapping_add`] and [`cast`] to atomically
-    /// perform `ptr = ptr.cast::<u8>().wrapping_add(val).cast::<T>()`.
+    /// This is equivalent to using [`wrapping_byte_add`] to atomically
+    /// perform `ptr = ptr.wrapping_byte_add(val)`.
     ///
     /// `fetch_byte_add` takes an [`Ordering`] argument which describes the
     /// memory ordering of this operation. All ordering modes are possible. Note
@@ -1565,8 +1565,7 @@ impl<T> AtomicPtr<T> {
     /// **Note**: This method is only available on platforms that support atomic
     /// operations on [`AtomicPtr`].
     ///
-    /// [`wrapping_add`]: pointer::wrapping_add
-    /// [`cast`]: pointer::cast
+    /// [`wrapping_byte_add`]: pointer::wrapping_byte_add
     ///
     /// # Examples
     ///
@@ -1591,8 +1590,8 @@ impl<T> AtomicPtr<T> {
     /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
     /// previous pointer.
     ///
-    /// This is equivalent to using [`wrapping_sub`] and [`cast`] to atomically
-    /// perform `ptr = ptr.cast::<u8>().wrapping_sub(val).cast::<T>()`.
+    /// This is equivalent to using [`wrapping_byte_sub`] to atomically
+    /// perform `ptr = ptr.wrapping_byte_sub(val)`.
     ///
     /// `fetch_byte_sub` takes an [`Ordering`] argument which describes the
     /// memory ordering of this operation. All ordering modes are possible. Note
@@ -1602,8 +1601,7 @@ impl<T> AtomicPtr<T> {
     /// **Note**: This method is only available on platforms that support atomic
     /// operations on [`AtomicPtr`].
     ///
-    /// [`wrapping_sub`]: pointer::wrapping_sub
-    /// [`cast`]: pointer::cast
+    /// [`wrapping_byte_sub`]: pointer::wrapping_byte_sub
     ///
     /// # Examples
     ///
diff --git a/library/core/tests/iter/adapters/flatten.rs b/library/core/tests/iter/adapters/flatten.rs
index f8ab8c9d444..690fd0c2197 100644
--- a/library/core/tests/iter/adapters/flatten.rs
+++ b/library/core/tests/iter/adapters/flatten.rs
@@ -168,3 +168,45 @@ fn test_trusted_len_flatten() {
     assert_trusted_len(&iter);
     assert_eq!(iter.size_hint(), (20, Some(20)));
 }
+
+#[test]
+fn test_flatten_count() {
+    let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
+
+    assert_eq!(it.clone().count(), 40);
+    it.advance_by(5).unwrap();
+    assert_eq!(it.clone().count(), 35);
+    it.advance_back_by(5).unwrap();
+    assert_eq!(it.clone().count(), 30);
+    it.advance_by(10).unwrap();
+    assert_eq!(it.clone().count(), 20);
+    it.advance_back_by(8).unwrap();
+    assert_eq!(it.clone().count(), 12);
+    it.advance_by(4).unwrap();
+    assert_eq!(it.clone().count(), 8);
+    it.advance_back_by(5).unwrap();
+    assert_eq!(it.clone().count(), 3);
+    it.advance_by(3).unwrap();
+    assert_eq!(it.clone().count(), 0);
+}
+
+#[test]
+fn test_flatten_last() {
+    let mut it = once(0..10).chain(once(10..30)).chain(once(30..40)).flatten();
+
+    assert_eq!(it.clone().last(), Some(39));
+    it.advance_by(5).unwrap(); // 5..40
+    assert_eq!(it.clone().last(), Some(39));
+    it.advance_back_by(5).unwrap(); // 5..35
+    assert_eq!(it.clone().last(), Some(34));
+    it.advance_by(10).unwrap(); // 15..35
+    assert_eq!(it.clone().last(), Some(34));
+    it.advance_back_by(8).unwrap(); // 15..27
+    assert_eq!(it.clone().last(), Some(26));
+    it.advance_by(4).unwrap(); // 19..27
+    assert_eq!(it.clone().last(), Some(26));
+    it.advance_back_by(5).unwrap(); // 19..22
+    assert_eq!(it.clone().last(), Some(21));
+    it.advance_by(3).unwrap(); // 22..22
+    assert_eq!(it.clone().last(), None);
+}
diff --git a/library/core/tests/lib.rs b/library/core/tests/lib.rs
index 09f1500f564..59510d3cc2a 100644
--- a/library/core/tests/lib.rs
+++ b/library/core/tests/lib.rs
@@ -99,6 +99,7 @@
 #![feature(waker_getters)]
 #![feature(slice_flatten)]
 #![feature(provide_any)]
+#![feature(utf8_chunks)]
 #![deny(unsafe_op_in_unsafe_fn)]
 
 extern crate test;
diff --git a/library/core/tests/str_lossy.rs b/library/core/tests/str_lossy.rs
index d4b47a4708e..9d3f0b65fdb 100644
--- a/library/core/tests/str_lossy.rs
+++ b/library/core/tests/str_lossy.rs
@@ -1,85 +1,85 @@
-use core::str::lossy::*;
+use core::str::Utf8Chunks;
 
 #[test]
 fn chunks() {
-    let mut iter = Utf8Lossy::from_bytes(b"hello").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "hello", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
+    macro_rules! assert_chunks {
+        ( $string:expr, $(($valid:expr, $invalid:expr)),* $(,)? ) => {{
+            let mut iter = Utf8Chunks::new($string);
+            $(
+                let chunk = iter.next().expect("missing chunk");
+                assert_eq!($valid, chunk.valid());
+                assert_eq!($invalid, chunk.invalid());
+            )*
+            assert_eq!(None, iter.next());
+        }};
+    }
 
-    let mut iter = Utf8Lossy::from_bytes("ศไทย中华Việt Nam".as_bytes()).chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "ศไทย中华Việt Nam", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"Hello\xC2 There\xFF Goodbye").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC2" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xFF" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "Hello", broken: b"\xC0" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " There", broken: b"\xE6\x83" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: " Goodbye", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"\xF5foo\xF5\x80bar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF5" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF5" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"\xF1foo\xF1\x80bar\xF1\x80\x80baz").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF1" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF1\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF1\x80\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"\xF4foo\xF4\x80bar\xF4\xBFbaz").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF4" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xF4\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"\xF4" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "baz", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-
-    let mut iter = Utf8Lossy::from_bytes(b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xF0" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo\u{10000}bar", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
+    assert_chunks!(b"hello", ("hello", b""));
+    assert_chunks!("ศไทย中华Việt Nam".as_bytes(), ("ศไทย中华Việt Nam", b""));
+    assert_chunks!(
+        b"Hello\xC2 There\xFF Goodbye",
+        ("Hello", b"\xC2"),
+        (" There", b"\xFF"),
+        (" Goodbye", b""),
+    );
+    assert_chunks!(
+        b"Hello\xC0\x80 There\xE6\x83 Goodbye",
+        ("Hello", b"\xC0"),
+        ("", b"\x80"),
+        (" There", b"\xE6\x83"),
+        (" Goodbye", b""),
+    );
+    assert_chunks!(
+        b"\xF5foo\xF5\x80bar",
+        ("", b"\xF5"),
+        ("foo", b"\xF5"),
+        ("", b"\x80"),
+        ("bar", b""),
+    );
+    assert_chunks!(
+        b"\xF1foo\xF1\x80bar\xF1\x80\x80baz",
+        ("", b"\xF1"),
+        ("foo", b"\xF1\x80"),
+        ("bar", b"\xF1\x80\x80"),
+        ("baz", b""),
+    );
+    assert_chunks!(
+        b"\xF4foo\xF4\x80bar\xF4\xBFbaz",
+        ("", b"\xF4"),
+        ("foo", b"\xF4\x80"),
+        ("bar", b"\xF4"),
+        ("", b"\xBF"),
+        ("baz", b""),
+    );
+    assert_chunks!(
+        b"\xF0\x80\x80\x80foo\xF0\x90\x80\x80bar",
+        ("", b"\xF0"),
+        ("", b"\x80"),
+        ("", b"\x80"),
+        ("", b"\x80"),
+        ("foo\u{10000}bar", b""),
+    );
 
     // surrogates
-    let mut iter = Utf8Lossy::from_bytes(b"\xED\xA0\x80foo\xED\xBF\xBFbar").chunks();
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xED" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xA0" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\x80" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "foo", broken: b"\xED" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "", broken: b"\xBF" }), iter.next());
-    assert_eq!(Some(Utf8LossyChunk { valid: "bar", broken: b"" }), iter.next());
-    assert_eq!(None, iter.next());
-}
-
-#[test]
-fn display() {
-    assert_eq!(
-        "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
-        &Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string()
+    assert_chunks!(
+        b"\xED\xA0\x80foo\xED\xBF\xBFbar",
+        ("", b"\xED"),
+        ("", b"\xA0"),
+        ("", b"\x80"),
+        ("foo", b"\xED"),
+        ("", b"\xBF"),
+        ("", b"\xBF"),
+        ("bar", b""),
     );
 }
 
 #[test]
 fn debug() {
     assert_eq!(
-        "\"Hello\\xc0\\x80 There\\xe6\\x83 Goodbye\\u{10d4ea}\"",
+        "\"Hello\\xC0\\x80 There\\xE6\\x83 Goodbye\\u{10d4ea}\"",
         &format!(
             "{:?}",
-            Utf8Lossy::from_bytes(b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa")
-        )
+            Utf8Chunks::new(b"Hello\xC0\x80 There\xE6\x83 Goodbye\xf4\x8d\x93\xaa").debug(),
+        ),
     );
 }
diff --git a/library/panic_abort/src/android.rs b/library/panic_abort/src/android.rs
index 18bb932f10e..0fd824f8a45 100644
--- a/library/panic_abort/src/android.rs
+++ b/library/panic_abort/src/android.rs
@@ -42,7 +42,7 @@ pub(crate) unsafe fn android_set_abort_message(payload: *mut &mut dyn BoxMeUp) {
         return; // allocation failure
     }
     copy_nonoverlapping(msg.as_ptr(), buf as *mut u8, msg.len());
-    buf.offset(msg.len() as isize).write(0);
+    buf.add(msg.len()).write(0);
 
     let func = transmute::<usize, SetAbortMessageType>(func_addr);
     func(buf);
diff --git a/library/panic_unwind/src/dwarf/eh.rs b/library/panic_unwind/src/dwarf/eh.rs
index 7394feab82f..9aa966b5063 100644
--- a/library/panic_unwind/src/dwarf/eh.rs
+++ b/library/panic_unwind/src/dwarf/eh.rs
@@ -75,7 +75,7 @@ pub unsafe fn find_eh_action(lsda: *const u8, context: &EHContext<'_>) -> Result
 
     let call_site_encoding = reader.read::<u8>();
     let call_site_table_length = reader.read_uleb128();
-    let action_table = reader.ptr.offset(call_site_table_length as isize);
+    let action_table = reader.ptr.add(call_site_table_length as usize);
     let ip = context.ip;
 
     if !USING_SJLJ_EXCEPTIONS {
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 229e546e085..3da9565a86d 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -39,7 +39,7 @@ rand = "0.7"
 dlmalloc = { version = "0.2.3", features = ['rustc-dep-of-std'] }
 
 [target.x86_64-fortanix-unknown-sgx.dependencies]
-fortanix-sgx-abi = { version = "0.3.2", features = ['rustc-dep-of-std'] }
+fortanix-sgx-abi = { version = "0.5.0", features = ['rustc-dep-of-std'] }
 
 [target.'cfg(target_os = "hermit")'.dependencies]
 hermit-abi = { version = "0.2.0", features = ['rustc-dep-of-std'] }
diff --git a/library/std/src/collections/hash/map/tests.rs b/library/std/src/collections/hash/map/tests.rs
index 7ebc41588b3..cb3032719fa 100644
--- a/library/std/src/collections/hash/map/tests.rs
+++ b/library/std/src/collections/hash/map/tests.rs
@@ -268,10 +268,13 @@ fn test_lots_of_insertions() {
 
     // Try this a few times to make sure we never screw up the hashmap's
     // internal state.
-    for _ in 0..10 {
+    let loops = if cfg!(miri) { 2 } else { 10 };
+    for _ in 0..loops {
         assert!(m.is_empty());
 
-        for i in 1..1001 {
+        let count = if cfg!(miri) { 101 } else { 1001 };
+
+        for i in 1..count {
             assert!(m.insert(i, i).is_none());
 
             for j in 1..=i {
@@ -279,42 +282,42 @@ fn test_lots_of_insertions() {
                 assert_eq!(r, Some(&j));
             }
 
-            for j in i + 1..1001 {
+            for j in i + 1..count {
                 let r = m.get(&j);
                 assert_eq!(r, None);
             }
         }
 
-        for i in 1001..2001 {
+        for i in count..(2 * count) {
             assert!(!m.contains_key(&i));
         }
 
         // remove forwards
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(m.remove(&i).is_some());
 
             for j in 1..=i {
                 assert!(!m.contains_key(&j));
             }
 
-            for j in i + 1..1001 {
+            for j in i + 1..count {
                 assert!(m.contains_key(&j));
             }
         }
 
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(!m.contains_key(&i));
         }
 
-        for i in 1..1001 {
+        for i in 1..count {
             assert!(m.insert(i, i).is_none());
         }
 
         // remove backwards
-        for i in (1..1001).rev() {
+        for i in (1..count).rev() {
             assert!(m.remove(&i).is_some());
 
-            for j in i..1001 {
+            for j in i..count {
                 assert!(!m.contains_key(&j));
             }
 
@@ -817,6 +820,7 @@ fn test_retain() {
 }
 
 #[test]
+#[cfg_attr(miri, ignore)] // Miri does not support signalling OOM
 #[cfg_attr(target_os = "android", ignore)] // Android used in CI has a broken dlmalloc
 fn test_try_reserve() {
     let mut empty_bytes: HashMap<u8, u8> = HashMap::new();
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index df7a49d2582..4fbcfd85d7c 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -1,4 +1,4 @@
-//! Interfaces for working with Errors.
+//! The `Error` trait provides common functionality for errors.
 //!
 //! # Error Handling In Rust
 //!
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index 933b52b4dcc..3dd5b12507f 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -1,4 +1,4 @@
-//! Constants specific to the `f32` single-precision floating point type.
+//! Constants for the `f32` single-precision floating point type.
 //!
 //! *[See also the `f32` primitive type](primitive@f32).*
 //!
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index a9aa84f70d1..31351a87978 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -1,4 +1,4 @@
-//! Constants specific to the `f64` double-precision floating point type.
+//! Constants for the `f64` double-precision floating point type.
 //!
 //! *[See also the `f64` primitive type](primitive@f64).*
 //!
diff --git a/library/std/src/ffi/os_str.rs b/library/std/src/ffi/os_str.rs
index a0a5c003d28..80ed34157e6 100644
--- a/library/std/src/ffi/os_str.rs
+++ b/library/std/src/ffi/os_str.rs
@@ -290,7 +290,8 @@ impl OsString {
     /// in the given `OsString`. The string may reserve more space to speculatively avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional` if it returns `Ok(())`.
-    /// Does nothing if capacity is already sufficient.
+    /// Does nothing if capacity is already sufficient. This method preserves
+    /// the contents even if an error occurs.
     ///
     /// See the main `OsString` documentation information about encoding and capacity units.
     ///
diff --git a/library/std/src/io/tests.rs b/library/std/src/io/tests.rs
index f357f33ec52..68a19eccc0e 100644
--- a/library/std/src/io/tests.rs
+++ b/library/std/src/io/tests.rs
@@ -94,7 +94,7 @@ fn read_to_end() {
     assert_eq!(c.read_to_end(&mut v).unwrap(), 1);
     assert_eq!(v, b"1");
 
-    let cap = 1024 * 1024;
+    let cap = if cfg!(miri) { 1024 } else { 1024 * 1024 };
     let data = (0..cap).map(|i| (i / 3) as u8).collect::<Vec<_>>();
     let mut v = Vec::new();
     let (a, b) = data.split_at(data.len() / 2);
@@ -309,6 +309,7 @@ fn chain_zero_length_read_is_not_eof() {
 
 #[bench]
 #[cfg_attr(target_os = "emscripten", ignore)]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_read_to_end(b: &mut test::Bencher) {
     b.iter(|| {
         let mut lr = repeat(1).take(10000000);
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index a8d6645794a..71bbf4317e0 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -187,6 +187,7 @@
 //! [rust-discord]: https://discord.gg/rust-lang
 //! [array]: prim@array
 //! [slice]: prim@slice
+
 #![cfg_attr(not(feature = "restricted-std"), stable(feature = "rust1", since = "1.0.0"))]
 #![cfg_attr(feature = "restricted-std", unstable(feature = "restricted_std", issue = "none"))]
 #![doc(
@@ -201,25 +202,35 @@
     no_global_oom_handling,
     not(no_global_oom_handling)
 ))]
+// To run libstd tests without x.py without ending up with two copies of libstd, Miri needs to be
+// able to "empty" this crate. See <https://github.com/rust-lang/miri-test-libstd/issues/4>.
+// rustc itself never sets the feature, so this line has no affect there.
+#![cfg(any(not(feature = "miri-test-libstd"), test, doctest))]
+// miri-test-libstd also prefers to make std use the sysroot versions of the dependencies.
+#![cfg_attr(feature = "miri-test-libstd", feature(rustc_private))]
 // Don't link to std. We are std.
 #![no_std]
+// Tell the compiler to link to either panic_abort or panic_unwind
+#![needs_panic_runtime]
+//
+// Lints:
 #![warn(deprecated_in_future)]
 #![warn(missing_docs)]
 #![warn(missing_debug_implementations)]
 #![allow(explicit_outlives_requirements)]
 #![allow(unused_lifetimes)]
-// Tell the compiler to link to either panic_abort or panic_unwind
-#![needs_panic_runtime]
+#![deny(rustc::existing_doc_keyword)]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
 #![allow(unused_features)]
+//
+// Features:
 #![cfg_attr(test, feature(internal_output_capture, print_internals, update_panic_count, rt))]
 #![cfg_attr(
     all(target_vendor = "fortanix", target_env = "sgx"),
     feature(slice_index_methods, coerce_unsized, sgx_platform)
 )]
-#![deny(rustc::existing_doc_keyword)]
 //
 // Language features:
 #![feature(alloc_error_handler)]
@@ -258,6 +269,7 @@
 #![feature(staged_api)]
 #![feature(thread_local)]
 #![feature(try_blocks)]
+#![feature(utf8_chunks)]
 //
 // Library features (core):
 #![feature(array_error_internals)]
@@ -284,6 +296,7 @@
 #![feature(panic_can_unwind)]
 #![feature(panic_info_message)]
 #![feature(panic_internals)]
+#![feature(pointer_is_aligned)]
 #![feature(portable_simd)]
 #![feature(prelude_2024)]
 #![feature(provide_any)]
diff --git a/library/std/src/net/ip.rs b/library/std/src/net/ip.rs
index 189754a161e..6004810655e 100644
--- a/library/std/src/net/ip.rs
+++ b/library/std/src/net/ip.rs
@@ -620,25 +620,31 @@ impl Ipv4Addr {
         matches!(self.octets(), [169, 254, ..])
     }
 
-    /// Returns [`true`] if the address appears to be globally routable.
-    /// See [iana-ipv4-special-registry][ipv4-sr].
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv4 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
+    ///
+    /// Most IPv4 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
     ///
-    /// The following return [`false`]:
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
     ///
-    /// - private addresses (see [`Ipv4Addr::is_private()`])
-    /// - the loopback address (see [`Ipv4Addr::is_loopback()`])
-    /// - the link-local address (see [`Ipv4Addr::is_link_local()`])
-    /// - the broadcast address (see [`Ipv4Addr::is_broadcast()`])
-    /// - addresses used for documentation (see [`Ipv4Addr::is_documentation()`])
-    /// - the unspecified address (see [`Ipv4Addr::is_unspecified()`]), and the whole
-    ///   `0.0.0.0/8` block
-    /// - addresses reserved for future protocols, except
-    /// `192.0.0.9/32` and `192.0.0.10/32` which are globally routable
-    /// - addresses reserved for future use (see [`Ipv4Addr::is_reserved()`]
-    /// - addresses reserved for networking devices benchmarking (see
-    /// [`Ipv4Addr::is_benchmarking()`])
+    /// - The [unspecified address] ([`is_unspecified`](Ipv4Addr::is_unspecified))
+    /// - Addresses reserved for private use ([`is_private`](Ipv4Addr::is_private))
+    /// - Addresses in the shared address space ([`is_shared`](Ipv4Addr::is_shared))
+    /// - Loopback addresses ([`is_loopback`](Ipv4Addr::is_loopback))
+    /// - Link-local addresses ([`is_link_local`](Ipv4Addr::is_link_local))
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv4Addr::is_documentation))
+    /// - Addresses reserved for benchmarking ([`is_benchmarking`](Ipv4Addr::is_benchmarking))
+    /// - Reserved addresses ([`is_reserved`](Ipv4Addr::is_reserved))
+    /// - The [broadcast address] ([`is_broadcast`](Ipv4Addr::is_broadcast))
     ///
-    /// [ipv4-sr]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv4 Special-Purpose Address Registry].
+    ///
+    /// [IANA IPv4 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv4-special-registry/iana-ipv4-special-registry.xhtml
+    /// [unspecified address]: Ipv4Addr::UNSPECIFIED
+    /// [broadcast address]: Ipv4Addr::BROADCAST
+
     ///
     /// # Examples
     ///
@@ -647,71 +653,61 @@ impl Ipv4Addr {
     ///
     /// use std::net::Ipv4Addr;
     ///
-    /// // private addresses are not global
+    /// // Most IPv4 addresses are globally reachable:
+    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`0.0.0.0`)
+    /// assert_eq!(Ipv4Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // Addresses reserved for private use (`10.0.0.0/8`, `172.16.0.0/12`, 192.168.0.0/16)
     /// assert_eq!(Ipv4Addr::new(10, 254, 0, 0).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(192, 168, 10, 65).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(172, 16, 10, 65).is_global(), false);
     ///
-    /// // the 0.0.0.0/8 block is not global
-    /// assert_eq!(Ipv4Addr::new(0, 1, 2, 3).is_global(), false);
-    /// // in particular, the unspecified address is not global
-    /// assert_eq!(Ipv4Addr::new(0, 0, 0, 0).is_global(), false);
+    /// // Addresses in the shared address space (`100.64.0.0/10`)
+    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
     ///
-    /// // the loopback address is not global
-    /// assert_eq!(Ipv4Addr::new(127, 0, 0, 1).is_global(), false);
+    /// // The loopback addresses (`127.0.0.0/8`)
+    /// assert_eq!(Ipv4Addr::LOCALHOST.is_global(), false);
     ///
-    /// // link local addresses are not global
+    /// // Link-local addresses (`169.254.0.0/16`)
     /// assert_eq!(Ipv4Addr::new(169, 254, 45, 1).is_global(), false);
     ///
-    /// // the broadcast address is not global
-    /// assert_eq!(Ipv4Addr::new(255, 255, 255, 255).is_global(), false);
-    ///
-    /// // the address space designated for documentation is not global
+    /// // Addresses reserved for documentation (`192.0.2.0/24`, `198.51.100.0/24`, `203.0.113.0/24`)
     /// assert_eq!(Ipv4Addr::new(192, 0, 2, 255).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(198, 51, 100, 65).is_global(), false);
     /// assert_eq!(Ipv4Addr::new(203, 0, 113, 6).is_global(), false);
     ///
-    /// // shared addresses are not global
-    /// assert_eq!(Ipv4Addr::new(100, 100, 0, 0).is_global(), false);
-    ///
-    /// // addresses reserved for protocol assignment are not global
-    /// assert_eq!(Ipv4Addr::new(192, 0, 0, 0).is_global(), false);
-    /// assert_eq!(Ipv4Addr::new(192, 0, 0, 255).is_global(), false);
+    /// // Addresses reserved for benchmarking (`198.18.0.0/15`)
+    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
     ///
-    /// // addresses reserved for future use are not global
+    /// // Reserved addresses (`240.0.0.0/4`)
     /// assert_eq!(Ipv4Addr::new(250, 10, 20, 30).is_global(), false);
     ///
-    /// // addresses reserved for network devices benchmarking are not global
-    /// assert_eq!(Ipv4Addr::new(198, 18, 0, 0).is_global(), false);
+    /// // The broadcast address (`255.255.255.255`)
+    /// assert_eq!(Ipv4Addr::BROADCAST.is_global(), false);
     ///
-    /// // All the other addresses are global
-    /// assert_eq!(Ipv4Addr::new(1, 1, 1, 1).is_global(), true);
-    /// assert_eq!(Ipv4Addr::new(80, 9, 12, 3).is_global(), true);
+    /// // For a complete overview see the IANA IPv4 Special-Purpose Address Registry.
     /// ```
     #[rustc_const_unstable(feature = "const_ipv4", issue = "76205")]
     #[unstable(feature = "ip", issue = "27709")]
     #[must_use]
     #[inline]
     pub const fn is_global(&self) -> bool {
-        // check if this address is 192.0.0.9 or 192.0.0.10. These addresses are the only two
-        // globally routable addresses in the 192.0.0.0/24 range.
-        if u32::from_be_bytes(self.octets()) == 0xc0000009
-            || u32::from_be_bytes(self.octets()) == 0xc000000a
-        {
-            return true;
-        }
-        !self.is_private()
-            && !self.is_loopback()
-            && !self.is_link_local()
-            && !self.is_broadcast()
-            && !self.is_documentation()
-            && !self.is_shared()
+        !(self.octets()[0] == 0 // "This network"
+            || self.is_private()
+            || self.is_shared()
+            || self.is_loopback()
+            || self.is_link_local()
             // addresses reserved for future protocols (`192.0.0.0/24`)
-            && !(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
-            && !self.is_reserved()
-            && !self.is_benchmarking()
-            // Make sure the address is not in 0.0.0.0/8
-            && self.octets()[0] != 0
+            ||(self.octets()[0] == 192 && self.octets()[1] == 0 && self.octets()[2] == 0)
+            || self.is_documentation()
+            || self.is_benchmarking()
+            || self.is_reserved()
+            || self.is_broadcast())
     }
 
     /// Returns [`true`] if this address is part of the Shared Address Space defined in
@@ -1300,13 +1296,33 @@ impl Ipv6Addr {
         u128::from_be_bytes(self.octets()) == u128::from_be_bytes(Ipv6Addr::LOCALHOST.octets())
     }
 
-    /// Returns [`true`] if the address appears to be globally routable.
+    /// Returns [`true`] if the address appears to be globally reachable
+    /// as specified by the [IANA IPv6 Special-Purpose Address Registry].
+    /// Whether or not an address is practically reachable will depend on your network configuration.
     ///
-    /// The following return [`false`]:
+    /// Most IPv6 addresses are globally reachable;
+    /// unless they are specifically defined as *not* globally reachable.
     ///
-    /// - the loopback address
-    /// - link-local and unique local unicast addresses
-    /// - interface-, link-, realm-, admin- and site-local multicast addresses
+    /// Non-exhaustive list of notable addresses that are not globally reachable:
+    /// - The [unspecified address] ([`is_unspecified`](Ipv6Addr::is_unspecified))
+    /// - The [loopback address] ([`is_loopback`](Ipv6Addr::is_loopback))
+    /// - IPv4-mapped addresses
+    /// - Addresses reserved for benchmarking
+    /// - Addresses reserved for documentation ([`is_documentation`](Ipv6Addr::is_documentation))
+    /// - Unique local addresses ([`is_unique_local`](Ipv6Addr::is_unique_local))
+    /// - Unicast addresses with link-local scope ([`is_unicast_link_local`](Ipv6Addr::is_unicast_link_local))
+    ///
+    /// For the complete overview of which addresses are globally reachable, see the table at the [IANA IPv6 Special-Purpose Address Registry].
+    ///
+    /// Note that an address having global scope is not the same as being globally reachable,
+    /// and there is no direct relation between the two concepts: There exist addresses with global scope
+    /// that are not globally reachable (for example unique local addresses),
+    /// and addresses that are globally reachable without having global scope
+    /// (multicast addresses with non-global scope).
+    ///
+    /// [IANA IPv6 Special-Purpose Address Registry]: https://www.iana.org/assignments/iana-ipv6-special-registry/iana-ipv6-special-registry.xhtml
+    /// [unspecified address]: Ipv6Addr::UNSPECIFIED
+    /// [loopback address]: Ipv6Addr::LOCALHOST
     ///
     /// # Examples
     ///
@@ -1315,20 +1331,65 @@ impl Ipv6Addr {
     ///
     /// use std::net::Ipv6Addr;
     ///
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), true);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0, 0, 0x1).is_global(), false);
-    /// assert_eq!(Ipv6Addr::new(0, 0, 0x1c9, 0, 0, 0xafc8, 0, 0x1).is_global(), true);
+    /// // Most IPv6 addresses are globally reachable:
+    /// assert_eq!(Ipv6Addr::new(0x26, 0, 0x1c9, 0, 0, 0xafc8, 0x10, 0x1).is_global(), true);
+    ///
+    /// // However some addresses have been assigned a special meaning
+    /// // that makes them not globally reachable. Some examples are:
+    ///
+    /// // The unspecified address (`::`)
+    /// assert_eq!(Ipv6Addr::UNSPECIFIED.is_global(), false);
+    ///
+    /// // The loopback address (`::1`)
+    /// assert_eq!(Ipv6Addr::LOCALHOST.is_global(), false);
+    ///
+    /// // IPv4-mapped addresses (`::ffff:0:0/96`)
+    /// assert_eq!(Ipv6Addr::new(0, 0, 0, 0, 0, 0xffff, 0xc00a, 0x2ff).is_global(), false);
+    ///
+    /// // Addresses reserved for benchmarking (`2001:2::/48`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 2, 0, 0, 0, 0, 0, 1,).is_global(), false);
+    ///
+    /// // Addresses reserved for documentation (`2001:db8::/32`)
+    /// assert_eq!(Ipv6Addr::new(0x2001, 0xdb8, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unique local addresses (`fc00::/7`)
+    /// assert_eq!(Ipv6Addr::new(0xfc02, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // Unicast addresses with link-local scope (`fe80::/10`)
+    /// assert_eq!(Ipv6Addr::new(0xfe81, 0, 0, 0, 0, 0, 0, 1).is_global(), false);
+    ///
+    /// // For a complete overview see the IANA IPv6 Special-Purpose Address Registry.
     /// ```
     #[rustc_const_unstable(feature = "const_ipv6", issue = "76205")]
     #[unstable(feature = "ip", issue = "27709")]
     #[must_use]
     #[inline]
     pub const fn is_global(&self) -> bool {
-        match self.multicast_scope() {
-            Some(Ipv6MulticastScope::Global) => true,
-            None => self.is_unicast_global(),
-            _ => false,
-        }
+        !(self.is_unspecified()
+            || self.is_loopback()
+            // IPv4-mapped Address (`::ffff:0:0/96`)
+            || matches!(self.segments(), [0, 0, 0, 0, 0, 0xffff, _, _])
+            // IPv4-IPv6 Translat. (`64:ff9b:1::/48`)
+            || matches!(self.segments(), [0x64, 0xff9b, 1, _, _, _, _, _])
+            // Discard-Only Address Block (`100::/64`)
+            || matches!(self.segments(), [0x100, 0, 0, 0, _, _, _, _])
+            // IETF Protocol Assignments (`2001::/23`)
+            || (matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b < 0x200)
+                && !(
+                    // Port Control Protocol Anycast (`2001:1::1`)
+                    u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0001
+                    // Traversal Using Relays around NAT Anycast (`2001:1::2`)
+                    || u128::from_be_bytes(self.octets()) == 0x2001_0001_0000_0000_0000_0000_0000_0002
+                    // AMT (`2001:3::/32`)
+                    || matches!(self.segments(), [0x2001, 3, _, _, _, _, _, _])
+                    // AS112-v6 (`2001:4:112::/48`)
+                    || matches!(self.segments(), [0x2001, 4, 0x112, _, _, _, _, _])
+                    // ORCHIDv2 (`2001:20::/28`)
+                    || matches!(self.segments(), [0x2001, b, _, _, _, _, _, _] if b >= 0x20 && b <= 0x2F)
+                ))
+            || self.is_documentation()
+            || self.is_unique_local()
+            || self.is_unicast_link_local())
     }
 
     /// Returns [`true`] if this is a unique local address (`fc00::/7`).
@@ -1525,6 +1586,7 @@ impl Ipv6Addr {
             && !self.is_unique_local()
             && !self.is_unspecified()
             && !self.is_documentation()
+            && !self.is_benchmarking()
     }
 
     /// Returns the address's multicast scope if the address is multicast.
diff --git a/library/std/src/net/ip/tests.rs b/library/std/src/net/ip/tests.rs
index c29509331d7..7c3430b2b21 100644
--- a/library/std/src/net/ip/tests.rs
+++ b/library/std/src/net/ip/tests.rs
@@ -321,15 +321,15 @@ fn ip_properties() {
     check!("fe80:ffff::");
     check!("febf:ffff::");
     check!("fec0::", global);
-    check!("ff01::", multicast);
-    check!("ff02::", multicast);
-    check!("ff03::", multicast);
-    check!("ff04::", multicast);
-    check!("ff05::", multicast);
-    check!("ff08::", multicast);
+    check!("ff01::", global | multicast);
+    check!("ff02::", global | multicast);
+    check!("ff03::", global | multicast);
+    check!("ff04::", global | multicast);
+    check!("ff05::", global | multicast);
+    check!("ff08::", global | multicast);
     check!("ff0e::", global | multicast);
     check!("2001:db8:85a3::8a2e:370:7334", doc);
-    check!("2001:2::ac32:23ff:21", global | benchmarking);
+    check!("2001:2::ac32:23ff:21", benchmarking);
     check!("102:304:506:708:90a:b0c:d0e:f10", global);
 }
 
@@ -609,6 +609,60 @@ fn ipv6_properties() {
 
     check!("1::", &[0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], global | unicast_global);
 
+    check!(
+        "::ffff:127.0.0.1",
+        &[0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1],
+        unicast_global
+    );
+
+    check!(
+        "64:ff9b:1::",
+        &[0, 0x64, 0xff, 0x9b, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        unicast_global
+    );
+
+    check!("100::", &[0x01, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!("2001::", &[0x20, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:1::1",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:1::2",
+        &[0x20, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 2],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:3::",
+        &[0x20, 1, 0, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:4:112::",
+        &[0x20, 1, 0, 4, 1, 0x12, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!(
+        "2001:20::",
+        &[0x20, 1, 0, 0x20, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
+    check!("2001:30::", &[0x20, 1, 0, 0x30, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unicast_global);
+
+    check!(
+        "2001:200::",
+        &[0x20, 1, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        global | unicast_global
+    );
+
     check!("fc00::", &[0xfc, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], unique_local);
 
     check!(
@@ -666,21 +720,37 @@ fn ipv6_properties() {
     check!(
         "ff01::",
         &[0xff, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_interface_local
+        multicast_interface_local | global
     );
 
-    check!("ff02::", &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_link_local);
+    check!(
+        "ff02::",
+        &[0xff, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_link_local | global
+    );
 
-    check!("ff03::", &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_realm_local);
+    check!(
+        "ff03::",
+        &[0xff, 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_realm_local | global
+    );
 
-    check!("ff04::", &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_admin_local);
+    check!(
+        "ff04::",
+        &[0xff, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_admin_local | global
+    );
 
-    check!("ff05::", &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0], multicast_site_local);
+    check!(
+        "ff05::",
+        &[0xff, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
+        multicast_site_local | global
+    );
 
     check!(
         "ff08::",
         &[0xff, 8, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
-        multicast_organization_local
+        multicast_organization_local | global
     );
 
     check!(
@@ -698,7 +768,7 @@ fn ipv6_properties() {
     check!(
         "2001:2::ac32:23ff:21",
         &[0x20, 1, 0, 2, 0, 0, 0, 0, 0, 0, 0xac, 0x32, 0x23, 0xff, 0, 0x21],
-        global | unicast_global | benchmarking
+        benchmarking
     );
 
     check!(
diff --git a/library/std/src/os/fortanix_sgx/mod.rs b/library/std/src/os/fortanix_sgx/mod.rs
index a40dabe190a..da100b689db 100644
--- a/library/std/src/os/fortanix_sgx/mod.rs
+++ b/library/std/src/os/fortanix_sgx/mod.rs
@@ -26,6 +26,7 @@ pub mod usercalls {
             free, insecure_time, launch_thread, read, read_alloc, send, wait, write,
         };
         pub use crate::sys::abi::usercalls::raw::{do_usercall, Usercalls as UsercallNrs};
+        pub use crate::sys::abi::usercalls::raw::{Register, RegisterArgument, ReturnValue};
 
         // fortanix-sgx-abi re-exports
         pub use crate::sys::abi::usercalls::raw::Error;
diff --git a/library/std/src/os/unix/net/addr.rs b/library/std/src/os/unix/net/addr.rs
index 9aeae4b2cae..bb313c7597b 100644
--- a/library/std/src/os/unix/net/addr.rs
+++ b/library/std/src/os/unix/net/addr.rs
@@ -329,7 +329,7 @@ impl SocketAddr {
 
             crate::ptr::copy_nonoverlapping(
                 namespace.as_ptr(),
-                addr.sun_path.as_mut_ptr().offset(1) as *mut u8,
+                addr.sun_path.as_mut_ptr().add(1) as *mut u8,
                 namespace.len(),
             );
             let len = (sun_path_offset(&addr) + 1 + namespace.len()) as libc::socklen_t;
diff --git a/library/std/src/os/unix/net/listener.rs b/library/std/src/os/unix/net/listener.rs
index 7c0d539504d..3b2601e755a 100644
--- a/library/std/src/os/unix/net/listener.rs
+++ b/library/std/src/os/unix/net/listener.rs
@@ -73,9 +73,13 @@ impl UnixListener {
         unsafe {
             let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
             let (addr, len) = sockaddr_un(path.as_ref())?;
+            #[cfg(target_os = "linux")]
+            const backlog: libc::c_int = -1;
+            #[cfg(not(target_os = "linux"))]
+            const backlog: libc::c_int = 128;
 
             cvt(libc::bind(inner.as_inner().as_raw_fd(), &addr as *const _ as *const _, len as _))?;
-            cvt(libc::listen(inner.as_inner().as_raw_fd(), 128))?;
+            cvt(libc::listen(inner.as_inner().as_raw_fd(), backlog))?;
 
             Ok(UnixListener(inner))
         }
@@ -109,12 +113,16 @@ impl UnixListener {
     pub fn bind_addr(socket_addr: &SocketAddr) -> io::Result<UnixListener> {
         unsafe {
             let inner = Socket::new_raw(libc::AF_UNIX, libc::SOCK_STREAM)?;
+            #[cfg(target_os = "linux")]
+            const backlog: libc::c_int = -1;
+            #[cfg(not(target_os = "linux"))]
+            const backlog: libc::c_int = 128;
             cvt(libc::bind(
                 inner.as_raw_fd(),
                 &socket_addr.addr as *const _ as *const _,
                 socket_addr.len as _,
             ))?;
-            cvt(libc::listen(inner.as_raw_fd(), 128))?;
+            cvt(libc::listen(inner.as_raw_fd(), backlog))?;
             Ok(UnixListener(inner))
         }
     }
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index 351cf698810..dd307022c6d 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1768,6 +1768,7 @@ fn test_windows_absolute() {
 }
 
 #[bench]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
     let prefix = "my/home";
     let mut paths: Vec<_> =
@@ -1781,6 +1782,7 @@ fn bench_path_cmp_fast_path_buf_sort(b: &mut test::Bencher) {
 }
 
 #[bench]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
     let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
     let paths: Vec<_> =
@@ -1799,6 +1801,7 @@ fn bench_path_cmp_fast_path_long(b: &mut test::Bencher) {
 }
 
 #[bench]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
     let prefix = "my/home";
     let paths: Vec<_> =
@@ -1817,6 +1820,7 @@ fn bench_path_cmp_fast_path_short(b: &mut test::Bencher) {
 }
 
 #[bench]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_path_hashset(b: &mut test::Bencher) {
     let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
     let paths: Vec<_> =
@@ -1835,6 +1839,7 @@ fn bench_path_hashset(b: &mut test::Bencher) {
 }
 
 #[bench]
+#[cfg_attr(miri, ignore)] // Miri isn't fast...
 fn bench_path_hashset_miss(b: &mut test::Bencher) {
     let prefix = "/my/home/is/my/castle/and/my/castle/has/a/rusty/workbench/";
     let paths: Vec<_> =
diff --git a/library/std/src/primitive_docs.rs b/library/std/src/primitive_docs.rs
index 1c14b9341ca..2b2ef64fdb1 100644
--- a/library/std/src/primitive_docs.rs
+++ b/library/std/src/primitive_docs.rs
@@ -801,11 +801,53 @@ mod prim_array {}
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Box<[u8]>>());
 /// assert_eq!(2 * pointer_size, std::mem::size_of::<Rc<[u8]>>());
 /// ```
+///
+/// ## Trait Implementations
+///
+/// Some traits are implemented for slices if the element type implements
+/// that trait. This includes [`Eq`], [`Hash`] and [`Ord`].
+///
+/// ## Iteration
+///
+/// The slices implement `IntoIterator`. The iterator yields references to the
+/// slice elements.
+///
+/// ```
+/// let numbers: &[i32] = &[0, 1, 2];
+/// for n in numbers {
+///     println!("{n} is a number!");
+/// }
+/// ```
+///
+/// The mutable slice yields mutable references to the elements:
+///
+/// ```
+/// let mut scores: &mut [i32] = &mut [7, 8, 9];
+/// for score in scores {
+///     *score += 1;
+/// }
+/// ```
+///
+/// This iterator yields mutable references to the slice's elements, so while
+/// the element type of the slice is `i32`, the element type of the iterator is
+/// `&mut i32`.
+///
+/// * [`.iter`] and [`.iter_mut`] are the explicit methods to return the default
+///   iterators.
+/// * Further methods that return iterators are [`.split`], [`.splitn`],
+///   [`.chunks`], [`.windows`] and more.
+///
+/// [`Hash`]: core::hash::Hash
+/// [`.iter`]: slice::iter
+/// [`.iter_mut`]: slice::iter_mut
+/// [`.split`]: slice::split
+/// [`.splitn`]: slice::splitn
+/// [`.chunks`]: slice::chunks
+/// [`.windows`]: slice::windows
 #[stable(feature = "rust1", since = "1.0.0")]
 mod prim_slice {}
 
 #[doc(primitive = "str")]
-//
 /// String slices.
 ///
 /// *[See also the `std::str` module](crate::str).*
@@ -816,19 +858,22 @@ mod prim_slice {}
 ///
 /// String slices are always valid UTF-8.
 ///
-/// # Examples
+/// # Basic Usage
 ///
 /// String literals are string slices:
 ///
 /// ```
-/// let hello = "Hello, world!";
-///
-/// // with an explicit type annotation
-/// let hello: &'static str = "Hello, world!";
+/// let hello_world = "Hello, World!";
 /// ```
 ///
-/// They are `'static` because they're stored directly in the final binary, and
-/// so will be valid for the `'static` duration.
+/// Here we have declared a string slice initialized with a string literal.
+/// String literals have a static lifetime, which means the string `hello_world`
+/// is guaranteed to be valid for the duration of the entire program.
+/// We can explicitly specify `hello_world`'s lifetime as well:
+///
+/// ```
+/// let hello_world: &'static str = "Hello, world!";
+/// ```
 ///
 /// # Representation
 ///
diff --git a/library/std/src/process.rs b/library/std/src/process.rs
index d6cba7e7598..d91d4fa64ca 100644
--- a/library/std/src/process.rs
+++ b/library/std/src/process.rs
@@ -169,15 +169,15 @@ use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 pub struct Child {
     pub(crate) handle: imp::Process,
 
-    /// The handle for writing to the child's standard input (stdin), if it has
-    /// been captured. To avoid partially moving
-    /// the `child` and thus blocking yourself from calling
-    /// functions on `child` while using `stdin`,
-    /// you might find it helpful:
+    /// The handle for writing to the child's standard input (stdin), if it
+    /// has been captured. You might find it helpful to do
     ///
     /// ```compile_fail,E0425
     /// let stdin = child.stdin.take().unwrap();
     /// ```
+    ///
+    /// to avoid partially moving the `child` and thus blocking yourself from calling
+    /// functions on `child` while using `stdin`.
     #[stable(feature = "process", since = "1.0.0")]
     pub stdin: Option<ChildStdin>,
 
diff --git a/library/std/src/sync/mpsc/mpsc_queue/tests.rs b/library/std/src/sync/mpsc/mpsc_queue/tests.rs
index 9f4f31ed051..34b2a9a98ac 100644
--- a/library/std/src/sync/mpsc/mpsc_queue/tests.rs
+++ b/library/std/src/sync/mpsc/mpsc_queue/tests.rs
@@ -13,7 +13,7 @@ fn test_full() {
 #[test]
 fn test() {
     let nthreads = 8;
-    let nmsgs = 1000;
+    let nmsgs = if cfg!(miri) { 100 } else { 1000 };
     let q = Queue::new();
     match q.pop() {
         Empty => {}
diff --git a/library/std/src/sync/mpsc/spsc_queue/tests.rs b/library/std/src/sync/mpsc/spsc_queue/tests.rs
index 467ef3dbdcb..eb6d5c2cf66 100644
--- a/library/std/src/sync/mpsc/spsc_queue/tests.rs
+++ b/library/std/src/sync/mpsc/spsc_queue/tests.rs
@@ -77,12 +77,13 @@ fn stress() {
     }
 
     unsafe fn stress_bound(bound: usize) {
+        let count = if cfg!(miri) { 1000 } else { 100000 };
         let q = Arc::new(Queue::with_additions(bound, (), ()));
 
         let (tx, rx) = channel();
         let q2 = q.clone();
         let _t = thread::spawn(move || {
-            for _ in 0..100000 {
+            for _ in 0..count {
                 loop {
                     match q2.pop() {
                         Some(1) => break,
@@ -93,7 +94,7 @@ fn stress() {
             }
             tx.send(()).unwrap();
         });
-        for _ in 0..100000 {
+        for _ in 0..count {
             q.push(1);
         }
         rx.recv().unwrap();
diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs
index e58649bab6e..63c79436974 100644
--- a/library/std/src/sync/mpsc/sync_tests.rs
+++ b/library/std/src/sync/mpsc/sync_tests.rs
@@ -113,23 +113,25 @@ fn chan_gone_concurrent() {
 
 #[test]
 fn stress() {
+    let count = if cfg!(miri) { 100 } else { 10000 };
     let (tx, rx) = sync_channel::<i32>(0);
     thread::spawn(move || {
-        for _ in 0..10000 {
+        for _ in 0..count {
             tx.send(1).unwrap();
         }
     });
-    for _ in 0..10000 {
+    for _ in 0..count {
         assert_eq!(rx.recv().unwrap(), 1);
     }
 }
 
 #[test]
 fn stress_recv_timeout_two_threads() {
+    let count = if cfg!(miri) { 100 } else { 10000 };
     let (tx, rx) = sync_channel::<i32>(0);
 
     thread::spawn(move || {
-        for _ in 0..10000 {
+        for _ in 0..count {
             tx.send(1).unwrap();
         }
     });
@@ -146,12 +148,12 @@ fn stress_recv_timeout_two_threads() {
         }
     }
 
-    assert_eq!(recv_count, 10000);
+    assert_eq!(recv_count, count);
 }
 
 #[test]
 fn stress_recv_timeout_shared() {
-    const AMT: u32 = 1000;
+    const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
     const NTHREADS: u32 = 8;
     let (tx, rx) = sync_channel::<i32>(0);
     let (dtx, drx) = sync_channel::<()>(0);
@@ -191,7 +193,7 @@ fn stress_recv_timeout_shared() {
 
 #[test]
 fn stress_shared() {
-    const AMT: u32 = 1000;
+    const AMT: u32 = if cfg!(miri) { 100 } else { 1000 };
     const NTHREADS: u32 = 8;
     let (tx, rx) = sync_channel::<i32>(0);
     let (dtx, drx) = sync_channel::<()>(0);
@@ -438,12 +440,13 @@ fn stream_send_recv_stress() {
 
 #[test]
 fn recv_a_lot() {
+    let count = if cfg!(miri) { 1000 } else { 10000 };
     // Regression test that we don't run out of stack in scheduler context
-    let (tx, rx) = sync_channel(10000);
-    for _ in 0..10000 {
+    let (tx, rx) = sync_channel(count);
+    for _ in 0..count {
         tx.send(()).unwrap();
     }
-    for _ in 0..10000 {
+    for _ in 0..count {
         rx.recv().unwrap();
     }
 }
diff --git a/library/std/src/sync/mpsc/tests.rs b/library/std/src/sync/mpsc/tests.rs
index 4deb3e59615..f6d0796f604 100644
--- a/library/std/src/sync/mpsc/tests.rs
+++ b/library/std/src/sync/mpsc/tests.rs
@@ -120,13 +120,14 @@ fn chan_gone_concurrent() {
 
 #[test]
 fn stress() {
+    let count = if cfg!(miri) { 100 } else { 10000 };
     let (tx, rx) = channel::<i32>();
     let t = thread::spawn(move || {
-        for _ in 0..10000 {
+        for _ in 0..count {
             tx.send(1).unwrap();
         }
     });
-    for _ in 0..10000 {
+    for _ in 0..count {
         assert_eq!(rx.recv().unwrap(), 1);
     }
     t.join().ok().expect("thread panicked");
@@ -134,7 +135,7 @@ fn stress() {
 
 #[test]
 fn stress_shared() {
-    const AMT: u32 = 10000;
+    const AMT: u32 = if cfg!(miri) { 100 } else { 10000 };
     const NTHREADS: u32 = 8;
     let (tx, rx) = channel::<i32>();
 
@@ -504,12 +505,13 @@ fn very_long_recv_timeout_wont_panic() {
 
 #[test]
 fn recv_a_lot() {
+    let count = if cfg!(miri) { 1000 } else { 10000 };
     // Regression test that we don't run out of stack in scheduler context
     let (tx, rx) = channel();
-    for _ in 0..10000 {
+    for _ in 0..count {
         tx.send(()).unwrap();
     }
-    for _ in 0..10000 {
+    for _ in 0..count {
         rx.recv().unwrap();
     }
 }
diff --git a/library/std/src/sync/rwlock/tests.rs b/library/std/src/sync/rwlock/tests.rs
index 08255c985f5..b5b3ad9898e 100644
--- a/library/std/src/sync/rwlock/tests.rs
+++ b/library/std/src/sync/rwlock/tests.rs
@@ -19,7 +19,7 @@ fn smoke() {
 #[test]
 fn frob() {
     const N: u32 = 10;
-    const M: usize = 1000;
+    const M: usize = if cfg!(miri) { 100 } else { 1000 };
 
     let r = Arc::new(RwLock::new(()));
 
diff --git a/library/std/src/sys/sgx/abi/usercalls/alloc.rs b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
index 66fa1efbf10..5409bd1777c 100644
--- a/library/std/src/sys/sgx/abi/usercalls/alloc.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/alloc.rs
@@ -56,6 +56,8 @@ unsafe impl UserSafeSized for Usercall {}
 #[unstable(feature = "sgx_platform", issue = "56975")]
 unsafe impl UserSafeSized for Return {}
 #[unstable(feature = "sgx_platform", issue = "56975")]
+unsafe impl UserSafeSized for Cancel {}
+#[unstable(feature = "sgx_platform", issue = "56975")]
 unsafe impl<T: UserSafeSized> UserSafeSized for [T; 2] {}
 
 /// A type that can be represented in memory as one or more `UserSafeSized`s.
@@ -115,7 +117,7 @@ pub unsafe trait UserSafe {
     /// * the pointer is null.
     /// * the pointed-to range is not in user memory.
     unsafe fn check_ptr(ptr: *const Self) {
-        let is_aligned = |p: *const u8| -> bool { 0 == p.addr() & (Self::align_of() - 1) };
+        let is_aligned = |p: *const u8| -> bool { p.is_aligned_to(Self::align_of()) };
 
         assert!(is_aligned(ptr as *const u8));
         assert!(is_user_range(ptr as _, mem::size_of_val(unsafe { &*ptr })));
@@ -305,6 +307,34 @@ where
     }
 }
 
+// Split a memory region ptr..ptr + len into three parts:
+//   +--------+
+//   | small0 | Chunk smaller than 8 bytes
+//   +--------+
+//   |   big  | Chunk 8-byte aligned, and size a multiple of 8 bytes
+//   +--------+
+//   | small1 | Chunk smaller than 8 bytes
+//   +--------+
+fn region_as_aligned_chunks(ptr: *const u8, len: usize) -> (usize, usize, usize) {
+    let small0_size = if ptr as usize % 8 == 0 { 0 } else { 8 - ptr as usize % 8 };
+    let small1_size = (len - small0_size as usize) % 8;
+    let big_size = len - small0_size as usize - small1_size as usize;
+
+    (small0_size, big_size, small1_size)
+}
+
+unsafe fn copy_quadwords(src: *const u8, dst: *mut u8, len: usize) {
+    unsafe {
+        asm!(
+            "rep movsq (%rsi), (%rdi)",
+            inout("rcx") len / 8 => _,
+            inout("rdi") dst => _,
+            inout("rsi") src => _,
+            options(att_syntax, nostack, preserves_flags)
+        );
+    }
+}
+
 /// Copies `len` bytes of data from enclave pointer `src` to userspace `dst`
 ///
 /// This function mitigates stale data vulnerabilities by ensuring all writes to untrusted memory are either:
@@ -343,17 +373,6 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
         }
     }
 
-    unsafe fn copy_aligned_quadwords_to_userspace(src: *const u8, dst: *mut u8, len: usize) {
-        unsafe {
-            asm!(
-                "rep movsq (%rsi), (%rdi)",
-                inout("rcx") len / 8 => _,
-                inout("rdi") dst => _,
-                inout("rsi") src => _,
-                options(att_syntax, nostack, preserves_flags)
-            );
-        }
-    }
     assert!(!src.is_null());
     assert!(!dst.is_null());
     assert!(is_enclave_range(src, len));
@@ -367,10 +386,10 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
         unsafe {
             copy_bytewise_to_userspace(src, dst, len);
         }
-    } else if len % 8 == 0 && dst as usize % 8 == 0 {
+    } else if len % 8 == 0 && dst.is_aligned_to(8) {
         // Copying 8-byte aligned quadwords: copy quad word per quad word
         unsafe {
-            copy_aligned_quadwords_to_userspace(src, dst, len);
+            copy_quadwords(src, dst, len);
         }
     } else {
         // Split copies into three parts:
@@ -381,20 +400,16 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
         //   +--------+
         //   | small1 | Chunk smaller than 8 bytes
         //   +--------+
+        let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
 
         unsafe {
             // Copy small0
-            let small0_size = (8 - dst as usize % 8) as u8;
-            let small0_src = src;
-            let small0_dst = dst;
-            copy_bytewise_to_userspace(small0_src as _, small0_dst, small0_size as _);
+            copy_bytewise_to_userspace(src, dst, small0_size as _);
 
             // Copy big
-            let small1_size = ((len - small0_size as usize) % 8) as u8;
-            let big_size = len - small0_size as usize - small1_size as usize;
             let big_src = src.offset(small0_size as _);
             let big_dst = dst.offset(small0_size as _);
-            copy_aligned_quadwords_to_userspace(big_src as _, big_dst, big_size);
+            copy_quadwords(big_src as _, big_dst, big_size);
 
             // Copy small1
             let small1_src = src.offset(big_size as isize + small0_size as isize);
@@ -404,6 +419,106 @@ pub(crate) unsafe fn copy_to_userspace(src: *const u8, dst: *mut u8, len: usize)
     }
 }
 
+/// Copies `len` bytes of data from userspace pointer `src` to enclave pointer `dst`
+///
+/// This function mitigates AEPIC leak vulnerabilities by ensuring all reads from untrusted memory are 8-byte aligned
+///
+/// # Panics
+/// This function panics if:
+///
+/// * The `src` pointer is null
+/// * The `dst` pointer is null
+/// * The `src` memory range is not in user memory
+/// * The `dst` memory range is not in enclave memory
+///
+/// # References
+///  - https://www.intel.com/content/www/us/en/security-center/advisory/intel-sa-00657.html
+///  - https://www.intel.com/content/www/us/en/developer/articles/technical/software-security-guidance/advisory-guidance/stale-data-read-from-xapic.html
+pub(crate) unsafe fn copy_from_userspace(src: *const u8, dst: *mut u8, len: usize) {
+    // Copies memory region `src..src + len` to the enclave at `dst`. The source memory region
+    // is:
+    //  - strictly less than 8 bytes in size and may be
+    //  - located at a misaligned memory location
+    fn copy_misaligned_chunk_to_enclave(src: *const u8, dst: *mut u8, len: usize) {
+        let mut tmp_buff = [0u8; 16];
+
+        unsafe {
+            // Compute an aligned memory region to read from
+            // +--------+ <-- aligned_src + aligned_len (8B-aligned)
+            // |  pad1  |
+            // +--------+ <-- src + len (misaligned)
+            // |        |
+            // |        |
+            // |        |
+            // +--------+ <-- src (misaligned)
+            // |  pad0  |
+            // +--------+ <-- aligned_src (8B-aligned)
+            let pad0_size = src as usize % 8;
+            let aligned_src = src.sub(pad0_size);
+
+            let pad1_size = 8 - (src.add(len) as usize % 8);
+            let aligned_len = pad0_size + len + pad1_size;
+
+            debug_assert!(len < 8);
+            debug_assert_eq!(aligned_src as usize % 8, 0);
+            debug_assert_eq!(aligned_len % 8, 0);
+            debug_assert!(aligned_len <= 16);
+
+            // Copy the aligned buffer to a temporary buffer
+            // Note: copying from a slightly different memory location is a bit odd. In this case it
+            // can't lead to page faults or inadvertent copying from the enclave as we only ensured
+            // that the `src` pointer is aligned at an 8 byte boundary. As pages are 4096 bytes
+            // aligned, `aligned_src` must be on the same page as `src`. A similar argument can be made
+            // for `src + len`
+            copy_quadwords(aligned_src as _, tmp_buff.as_mut_ptr(), aligned_len);
+
+            // Copy the correct parts of the temporary buffer to the destination
+            ptr::copy(tmp_buff.as_ptr().add(pad0_size), dst, len);
+        }
+    }
+
+    assert!(!src.is_null());
+    assert!(!dst.is_null());
+    assert!(is_user_range(src, len));
+    assert!(is_enclave_range(dst, len));
+    assert!(!(src as usize).overflowing_add(len + 8).1);
+    assert!(!(dst as usize).overflowing_add(len + 8).1);
+
+    if len < 8 {
+        copy_misaligned_chunk_to_enclave(src, dst, len);
+    } else if len % 8 == 0 && src as usize % 8 == 0 {
+        // Copying 8-byte aligned quadwords: copy quad word per quad word
+        unsafe {
+            copy_quadwords(src, dst, len);
+        }
+    } else {
+        // Split copies into three parts:
+        //   +--------+
+        //   | small0 | Chunk smaller than 8 bytes
+        //   +--------+
+        //   |   big  | Chunk 8-byte aligned, and size a multiple of 8 bytes
+        //   +--------+
+        //   | small1 | Chunk smaller than 8 bytes
+        //   +--------+
+        let (small0_size, big_size, small1_size) = region_as_aligned_chunks(dst, len);
+
+        unsafe {
+            // Copy small0
+            copy_misaligned_chunk_to_enclave(src, dst, small0_size);
+
+            // Copy big
+            let big_src = src.add(small0_size);
+            let big_dst = dst.add(small0_size);
+            copy_quadwords(big_src, big_dst, big_size);
+
+            // Copy small1
+            let small1_src = src.add(big_size + small0_size);
+            let small1_dst = dst.add(big_size + small0_size);
+            copy_misaligned_chunk_to_enclave(small1_src, small1_dst, small1_size);
+        }
+    }
+}
+
 #[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: ?Sized> UserRef<T>
 where
@@ -468,7 +583,7 @@ where
     pub fn copy_to_enclave(&self, dest: &mut T) {
         unsafe {
             assert_eq!(mem::size_of_val(dest), mem::size_of_val(&*self.0.get()));
-            ptr::copy(
+            copy_from_userspace(
                 self.0.get() as *const T as *const u8,
                 dest as *mut T as *mut u8,
                 mem::size_of_val(dest),
@@ -494,7 +609,11 @@ where
 {
     /// Copies the value from user memory into enclave memory.
     pub fn to_enclave(&self) -> T {
-        unsafe { ptr::read(self.0.get()) }
+        unsafe {
+            let mut data: T = mem::MaybeUninit::uninit().assume_init();
+            copy_from_userspace(self.0.get() as _, &mut data as *mut T as _, mem::size_of::<T>());
+            data
+        }
     }
 }
 
diff --git a/library/std/src/sys/sgx/abi/usercalls/mod.rs b/library/std/src/sys/sgx/abi/usercalls/mod.rs
index 79d1db5e1c5..e19e843267a 100644
--- a/library/std/src/sys/sgx/abi/usercalls/mod.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/mod.rs
@@ -292,12 +292,17 @@ fn check_os_error(err: Result) -> i32 {
     }
 }
 
-trait FromSgxResult {
+/// Translate the raw result of an SGX usercall.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait FromSgxResult {
+    /// Return type
     type Return;
 
+    /// Translate the raw result of an SGX usercall.
     fn from_sgx_result(self) -> IoResult<Self::Return>;
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T> FromSgxResult for (Result, T) {
     type Return = T;
 
@@ -310,6 +315,7 @@ impl<T> FromSgxResult for (Result, T) {
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl FromSgxResult for Result {
     type Return = ();
 
diff --git a/library/std/src/sys/sgx/abi/usercalls/raw.rs b/library/std/src/sys/sgx/abi/usercalls/raw.rs
index 4267b96ccd5..10c1456d4fd 100644
--- a/library/std/src/sys/sgx/abi/usercalls/raw.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/raw.rs
@@ -37,14 +37,23 @@ pub unsafe fn do_usercall(
     (a, b)
 }
 
-type Register = u64;
+/// A value passed or returned in a CPU register.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub type Register = u64;
 
-trait RegisterArgument {
+/// Translate a type from/to Register to be used as an argument.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait RegisterArgument {
+    /// Translate a Register to Self.
     fn from_register(_: Register) -> Self;
+    /// Translate self to a Register.
     fn into_register(self) -> Register;
 }
 
-trait ReturnValue {
+/// Translate a pair of Registers to the raw usercall return value.
+#[unstable(feature = "sgx_platform", issue = "56975")]
+pub trait ReturnValue {
+    /// Translate a pair of Registers to the raw usercall return value.
     fn from_registers(call: &'static str, regs: (Register, Register)) -> Self;
 }
 
@@ -68,6 +77,7 @@ macro_rules! define_usercalls {
 
 macro_rules! define_ra {
     (< $i:ident > $t:ty) => {
+        #[unstable(feature = "sgx_platform", issue = "56975")]
         impl<$i> RegisterArgument for $t {
             fn from_register(a: Register) -> Self {
                 a as _
@@ -78,6 +88,7 @@ macro_rules! define_ra {
         }
     };
     ($i:ty as $t:ty) => {
+        #[unstable(feature = "sgx_platform", issue = "56975")]
         impl RegisterArgument for $t {
             fn from_register(a: Register) -> Self {
                 a as $i as _
@@ -88,6 +99,7 @@ macro_rules! define_ra {
         }
     };
     ($t:ty) => {
+        #[unstable(feature = "sgx_platform", issue = "56975")]
         impl RegisterArgument for $t {
             fn from_register(a: Register) -> Self {
                 a as _
@@ -112,6 +124,7 @@ define_ra!(usize as isize);
 define_ra!(<T> *const T);
 define_ra!(<T> *mut T);
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl RegisterArgument for bool {
     fn from_register(a: Register) -> bool {
         if a != 0 { true } else { false }
@@ -121,6 +134,7 @@ impl RegisterArgument for bool {
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
     fn from_register(a: Register) -> Option<NonNull<T>> {
         NonNull::new(a as _)
@@ -130,12 +144,14 @@ impl<T: RegisterArgument> RegisterArgument for Option<NonNull<T>> {
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl ReturnValue for ! {
     fn from_registers(call: &'static str, _regs: (Register, Register)) -> Self {
         rtabort!("Usercall {call}: did not expect to be re-entered");
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl ReturnValue for () {
     fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
         rtassert!(usercall_retval.0 == 0);
@@ -144,6 +160,7 @@ impl ReturnValue for () {
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: RegisterArgument> ReturnValue for T {
     fn from_registers(call: &'static str, usercall_retval: (Register, Register)) -> Self {
         rtassert!(usercall_retval.1 == 0);
@@ -151,6 +168,7 @@ impl<T: RegisterArgument> ReturnValue for T {
     }
 }
 
+#[unstable(feature = "sgx_platform", issue = "56975")]
 impl<T: RegisterArgument, U: RegisterArgument> ReturnValue for (T, U) {
     fn from_registers(_call: &'static str, regs: (Register, Register)) -> Self {
         (T::from_register(regs.0), U::from_register(regs.1))
diff --git a/library/std/src/sys/sgx/abi/usercalls/tests.rs b/library/std/src/sys/sgx/abi/usercalls/tests.rs
index cbf7d7d54f7..58b8eb215d7 100644
--- a/library/std/src/sys/sgx/abi/usercalls/tests.rs
+++ b/library/std/src/sys/sgx/abi/usercalls/tests.rs
@@ -1,8 +1,8 @@
-use super::alloc::copy_to_userspace;
 use super::alloc::User;
+use super::alloc::{copy_from_userspace, copy_to_userspace};
 
 #[test]
-fn test_copy_function() {
+fn test_copy_to_userspace_function() {
     let mut src = [0u8; 100];
     let mut dst = User::<[u8]>::uninitialized(100);
 
@@ -17,12 +17,38 @@ fn test_copy_function() {
             dst.copy_from_enclave(&[0u8; 100]);
 
             // Copy src[0..size] to dst + offset
-            unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().offset(offset), size) };
+            unsafe { copy_to_userspace(src.as_ptr(), dst.as_mut_ptr().add(offset), size) };
 
             // Verify copy
             for byte in 0..size {
                 unsafe {
-                    assert_eq!(*dst.as_ptr().offset(offset + byte as isize), src[byte as usize]);
+                    assert_eq!(*dst.as_ptr().add(offset + byte), src[byte as usize]);
+                }
+            }
+        }
+    }
+}
+
+#[test]
+fn test_copy_from_userspace_function() {
+    let mut dst = [0u8; 100];
+    let mut src = User::<[u8]>::uninitialized(100);
+
+    src.copy_from_enclave(&[0u8; 100]);
+
+    for size in 0..48 {
+        // For all possible alignment
+        for offset in 0..8 {
+            // overwrite complete dst
+            dst = [0u8; 100];
+
+            // Copy src[0..size] to dst + offset
+            unsafe { copy_from_userspace(src.as_ptr().offset(offset), dst.as_mut_ptr(), size) };
+
+            // Verify copy
+            for byte in 0..size {
+                unsafe {
+                    assert_eq!(dst[byte as usize], *src.as_ptr().offset(offset + byte as isize));
                 }
             }
         }
diff --git a/library/std/src/sys/unix/fs.rs b/library/std/src/sys/unix/fs.rs
index 7778033eaa9..f38d2fd3d70 100644
--- a/library/std/src/sys/unix/fs.rs
+++ b/library/std/src/sys/unix/fs.rs
@@ -829,6 +829,7 @@ impl DirEntry {
         target_os = "fuchsia",
         target_os = "redox"
     )))]
+    #[cfg_attr(miri, allow(unused))]
     fn name_cstr(&self) -> &CStr {
         unsafe { CStr::from_ptr(self.entry.d_name.as_ptr()) }
     }
@@ -840,6 +841,7 @@ impl DirEntry {
         target_os = "fuchsia",
         target_os = "redox"
     ))]
+    #[cfg_attr(miri, allow(unused))]
     fn name_cstr(&self) -> &CStr {
         &self.name
     }
diff --git a/library/std/src/sys/unix/os_str.rs b/library/std/src/sys/unix/os_str.rs
index ccbc182240c..017e2af29d4 100644
--- a/library/std/src/sys/unix/os_str.rs
+++ b/library/std/src/sys/unix/os_str.rs
@@ -11,7 +11,7 @@ use crate::str;
 use crate::sync::Arc;
 use crate::sys_common::{AsInner, IntoInner};
 
-use core::str::lossy::{Utf8Lossy, Utf8LossyChunk};
+use core::str::Utf8Chunks;
 
 #[cfg(test)]
 #[path = "../unix/os_str/tests.rs"]
@@ -29,26 +29,32 @@ pub struct Slice {
 }
 
 impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        // Writes out a valid unicode string with the correct escape sequences
-
-        formatter.write_str("\"")?;
-        for Utf8LossyChunk { valid, broken } in Utf8Lossy::from_bytes(&self.inner).chunks() {
-            for c in valid.chars().flat_map(|c| c.escape_debug()) {
-                formatter.write_char(c)?
-            }
-
-            for b in broken {
-                write!(formatter, "\\x{:02X}", b)?;
-            }
-        }
-        formatter.write_str("\"")
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&Utf8Chunks::new(&self.inner).debug(), f)
     }
 }
 
 impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&Utf8Lossy::from_bytes(&self.inner), formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        // If we're the empty string then our iterator won't actually yield
+        // anything, so perform the formatting manually
+        if self.inner.is_empty() {
+            return "".fmt(f);
+        }
+
+        for chunk in Utf8Chunks::new(&self.inner) {
+            let valid = chunk.valid();
+            // If we successfully decoded the whole chunk as a valid string then
+            // we can return a direct formatting of the string which will also
+            // respect various formatting flags if possible.
+            if chunk.invalid().is_empty() {
+                return valid.fmt(f);
+            }
+
+            f.write_str(valid)?;
+            f.write_char(char::REPLACEMENT_CHARACTER)?;
+        }
+        Ok(())
     }
 }
 
diff --git a/library/std/src/sys/unix/os_str/tests.rs b/library/std/src/sys/unix/os_str/tests.rs
index 213277f01f2..22ba0c92350 100644
--- a/library/std/src/sys/unix/os_str/tests.rs
+++ b/library/std/src/sys/unix/os_str/tests.rs
@@ -8,3 +8,11 @@ fn slice_debug_output() {
 
     assert_eq!(output, expected);
 }
+
+#[test]
+fn display() {
+    assert_eq!(
+        "Hello\u{FFFD}\u{FFFD} There\u{FFFD} Goodbye",
+        Slice::from_u8_slice(b"Hello\xC0\x80 There\xE6\x83 Goodbye").to_string(),
+    );
+}
diff --git a/library/std/src/sys/windows/alloc.rs b/library/std/src/sys/windows/alloc.rs
index fdc81cdea7d..fe00c08aa6a 100644
--- a/library/std/src/sys/windows/alloc.rs
+++ b/library/std/src/sys/windows/alloc.rs
@@ -168,7 +168,7 @@ unsafe fn allocate(layout: Layout, zeroed: bool) -> *mut u8 {
         // SAFETY: Because the size and alignment of a header is <= `MIN_ALIGN` and `aligned`
         // is aligned to at least `MIN_ALIGN` and has at least `MIN_ALIGN` bytes of padding before
         // it, it is safe to write a header directly before it.
-        unsafe { ptr::write((aligned as *mut Header).offset(-1), Header(ptr)) };
+        unsafe { ptr::write((aligned as *mut Header).sub(1), Header(ptr)) };
 
         // SAFETY: The returned pointer does not point to the to the start of an allocated block,
         // but there is a header readable directly before it containing the location of the start
@@ -213,7 +213,7 @@ unsafe impl GlobalAlloc for System {
 
                 // SAFETY: Because of the contract of `System`, `ptr` is guaranteed to be non-null
                 // and have a header readable directly before it.
-                unsafe { ptr::read((ptr as *mut Header).offset(-1)).0 }
+                unsafe { ptr::read((ptr as *mut Header).sub(1)).0 }
             }
         };
 
diff --git a/library/std/src/sys/windows/c.rs b/library/std/src/sys/windows/c.rs
index c5a30f8bac8..ef3f6a9ba17 100644
--- a/library/std/src/sys/windows/c.rs
+++ b/library/std/src/sys/windows/c.rs
@@ -228,6 +228,8 @@ pub const IPV6_ADD_MEMBERSHIP: c_int = 12;
 pub const IPV6_DROP_MEMBERSHIP: c_int = 13;
 pub const MSG_PEEK: c_int = 0x2;
 
+pub const LOAD_LIBRARY_SEARCH_SYSTEM32: u32 = 0x800;
+
 #[repr(C)]
 #[derive(Copy, Clone)]
 pub struct linger {
@@ -1030,6 +1032,7 @@ extern "system" {
     pub fn GetProcAddress(handle: HMODULE, name: LPCSTR) -> *mut c_void;
     pub fn GetModuleHandleA(lpModuleName: LPCSTR) -> HMODULE;
     pub fn GetModuleHandleW(lpModuleName: LPCWSTR) -> HMODULE;
+    pub fn LoadLibraryExA(lplibfilename: *const i8, hfile: HANDLE, dwflags: u32) -> HINSTANCE;
 
     pub fn GetSystemTimeAsFileTime(lpSystemTimeAsFileTime: LPFILETIME);
     pub fn GetSystemInfo(lpSystemInfo: LPSYSTEM_INFO);
@@ -1250,21 +1253,16 @@ compat_fn_with_fallback! {
     }
 }
 
-compat_fn_with_fallback! {
-    pub static SYNCH_API: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
-    #[allow(unused)]
-    fn WakeByAddressSingle(Address: LPVOID) -> () {
-        // This fallback is currently tightly coupled to its use in Parker::unpark.
-        //
-        // FIXME: If `WakeByAddressSingle` needs to be used anywhere other than
-        // Parker::unpark then this fallback will be wrong and will need to be decoupled.
-        crate::sys::windows::thread_parker::unpark_keyed_event(Address)
-    }
+compat_fn_optional! {
+    crate::sys::compat::load_synch_functions();
+    pub fn WaitOnAddress(
+        Address: LPVOID,
+        CompareAddress: LPVOID,
+        AddressSize: SIZE_T,
+        dwMilliseconds: DWORD
+    );
+    pub fn WakeByAddressSingle(Address: LPVOID);
 }
-pub use crate::sys::compat::WaitOnAddress;
-// Change exported name of `WakeByAddressSingle` to make the strange fallback
-// behaviour clear.
-pub use WakeByAddressSingle::call as wake_by_address_single_or_unpark_keyed_event;
 
 compat_fn_with_fallback! {
     pub static NTDLL: &CStr = ansi_str!("ntdll");
diff --git a/library/std/src/sys/windows/compat.rs b/library/std/src/sys/windows/compat.rs
index 473544c4d4f..9c8ddc3aa1d 100644
--- a/library/std/src/sys/windows/compat.rs
+++ b/library/std/src/sys/windows/compat.rs
@@ -21,6 +21,7 @@
 
 use crate::ffi::{c_void, CStr};
 use crate::ptr::NonNull;
+use crate::sync::atomic::{AtomicBool, Ordering};
 use crate::sys::c;
 
 /// Helper macro for creating CStrs from literals and symbol names.
@@ -74,6 +75,20 @@ impl Module {
         NonNull::new(module).map(Self)
     }
 
+    /// Load the library (if not already loaded)
+    ///
+    /// # Safety
+    ///
+    /// The module must not be unloaded.
+    pub unsafe fn load_system_library(name: &CStr) -> Option<Self> {
+        let module = c::LoadLibraryExA(
+            name.as_ptr(),
+            crate::ptr::null_mut(),
+            c::LOAD_LIBRARY_SEARCH_SYSTEM32,
+        );
+        NonNull::new(module).map(Self)
+    }
+
     // Try to get the address of a function.
     pub fn proc_address(self, name: &CStr) -> Option<NonNull<c_void>> {
         // SAFETY:
@@ -144,61 +159,63 @@ macro_rules! compat_fn_with_fallback {
     )*)
 }
 
-/// Optionally load `WaitOnAddress`.
-/// Unlike the dynamic loading described above, this does not have a fallback.
+/// Optionally loaded functions.
 ///
-/// This is rexported from sys::c. You should prefer to import
-/// from there in case this changes again in the future.
-pub mod WaitOnAddress {
-    use super::*;
-    use crate::mem;
-    use crate::ptr;
-    use crate::sync::atomic::{AtomicBool, AtomicPtr, Ordering};
-    use crate::sys::c;
-
-    static MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
-    static SYMBOL_NAME: &CStr = ansi_str!("WaitOnAddress");
-
-    // WaitOnAddress function signature.
-    type F = unsafe extern "system" fn(
-        Address: c::LPVOID,
-        CompareAddress: c::LPVOID,
-        AddressSize: c::SIZE_T,
-        dwMilliseconds: c::DWORD,
-    );
-
-    // A place to store the loaded function atomically.
-    static WAIT_ON_ADDRESS: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
-
-    // We can skip trying to load again if we already tried.
-    static LOAD_MODULE: AtomicBool = AtomicBool::new(true);
-
-    #[inline(always)]
-    pub fn option() -> Option<F> {
-        let f = WAIT_ON_ADDRESS.load(Ordering::Acquire);
-        if !f.is_null() { Some(unsafe { mem::transmute(f) }) } else { try_load() }
-    }
+/// Actual loading of the function defers to $load_functions.
+macro_rules! compat_fn_optional {
+    ($load_functions:expr;
+    $(
+        $(#[$meta:meta])*
+        $vis:vis fn $symbol:ident($($argname:ident: $argtype:ty),*) $(-> $rettype:ty)?;
+    )+) => (
+        $(
+            pub mod $symbol {
+                use super::*;
+                use crate::ffi::c_void;
+                use crate::mem;
+                use crate::ptr::{self, NonNull};
+                use crate::sync::atomic::{AtomicPtr, Ordering};
+
+                pub(in crate::sys) static PTR: AtomicPtr<c_void> = AtomicPtr::new(ptr::null_mut());
+
+                type F = unsafe extern "system" fn($($argtype),*) $(-> $rettype)?;
+
+                #[inline(always)]
+                pub fn option() -> Option<F> {
+                    let f = PTR.load(Ordering::Acquire);
+                    if !f.is_null() { Some(unsafe { mem::transmute(f) }) } else { try_load() }
+                }
 
-    #[cold]
-    fn try_load() -> Option<F> {
-        if LOAD_MODULE.load(Ordering::Acquire) {
-            // load the module
-            let mut wait_on_address = None;
-            if let Some(func) = try_load_inner() {
-                WAIT_ON_ADDRESS.store(func.as_ptr(), Ordering::Release);
-                wait_on_address = Some(unsafe { mem::transmute(func) });
+                #[cold]
+                fn try_load() -> Option<F> {
+                    $load_functions;
+                    NonNull::new(PTR.load(Ordering::Acquire)).map(|f| unsafe { mem::transmute(f) })
+                }
             }
-            // Don't try to load the module again even if loading failed.
-            LOAD_MODULE.store(false, Ordering::Release);
-            wait_on_address
-        } else {
-            None
-        }
-    }
+        )+
+    )
+}
 
-    // In the future this could be a `try` block but until then I think it's a
-    // little bit cleaner as a separate function.
-    fn try_load_inner() -> Option<NonNull<c_void>> {
-        unsafe { Module::new(MODULE_NAME)?.proc_address(SYMBOL_NAME) }
+/// Load all needed functions from "api-ms-win-core-synch-l1-2-0".
+pub(super) fn load_synch_functions() {
+    fn try_load() -> Option<()> {
+        const MODULE_NAME: &CStr = ansi_str!("api-ms-win-core-synch-l1-2-0");
+        const WAIT_ON_ADDRESS: &CStr = ansi_str!("WaitOnAddress");
+        const WAKE_BY_ADDRESS_SINGLE: &CStr = ansi_str!("WakeByAddressSingle");
+
+        // Try loading the library and all the required functions.
+        // If any step fails, then they all fail.
+        let library = unsafe { Module::load_system_library(MODULE_NAME) }?;
+        let wait_on_address = library.proc_address(WAIT_ON_ADDRESS)?;
+        let wake_by_address_single = library.proc_address(WAKE_BY_ADDRESS_SINGLE)?;
+
+        c::WaitOnAddress::PTR.store(wait_on_address.as_ptr(), Ordering::Release);
+        c::WakeByAddressSingle::PTR.store(wake_by_address_single.as_ptr(), Ordering::Release);
+        Some(())
     }
+
+    // Try to load the module but skip loading if a previous attempt failed.
+    static LOAD_MODULE: AtomicBool = AtomicBool::new(true);
+    let module_loaded = LOAD_MODULE.load(Ordering::Acquire) && try_load().is_some();
+    LOAD_MODULE.store(module_loaded, Ordering::Release)
 }
diff --git a/library/std/src/sys/windows/fs.rs b/library/std/src/sys/windows/fs.rs
index aed082b3e0a..1361b9c90c0 100644
--- a/library/std/src/sys/windows/fs.rs
+++ b/library/std/src/sys/windows/fs.rs
@@ -512,7 +512,7 @@ impl File {
                     ));
                 }
             };
-            let subst_ptr = path_buffer.offset(subst_off as isize);
+            let subst_ptr = path_buffer.add(subst_off.into());
             let mut subst = slice::from_raw_parts(subst_ptr, subst_len as usize);
             // Absolute paths start with an NT internal namespace prefix `\??\`
             // We should not let it leak through.
@@ -1345,10 +1345,10 @@ fn symlink_junction_inner(original: &Path, junction: &Path) -> io::Result<()> {
         let v = br"\??\";
         let v = v.iter().map(|x| *x as u16);
         for c in v.chain(original.as_os_str().encode_wide()) {
-            *buf.offset(i) = c;
+            *buf.add(i) = c;
             i += 1;
         }
-        *buf.offset(i) = 0;
+        *buf.add(i) = 0;
         i += 1;
         (*db).ReparseTag = c::IO_REPARSE_TAG_MOUNT_POINT;
         (*db).ReparseTargetMaximumLength = (i * 2) as c::WORD;
diff --git a/library/std/src/sys/windows/mod.rs b/library/std/src/sys/windows/mod.rs
index b3f6d2d0aae..a9846a48488 100644
--- a/library/std/src/sys/windows/mod.rs
+++ b/library/std/src/sys/windows/mod.rs
@@ -2,6 +2,7 @@
 
 use crate::ffi::{CStr, OsStr, OsString};
 use crate::io::ErrorKind;
+use crate::mem::MaybeUninit;
 use crate::os::windows::ffi::{OsStrExt, OsStringExt};
 use crate::path::PathBuf;
 use crate::time::Duration;
@@ -204,8 +205,8 @@ where
     // This initial size also works around `GetFullPathNameW` returning
     // incorrect size hints for some short paths:
     // https://github.com/dylni/normpath/issues/5
-    let mut stack_buf = [0u16; 512];
-    let mut heap_buf = Vec::new();
+    let mut stack_buf: [MaybeUninit<u16>; 512] = MaybeUninit::uninit_array();
+    let mut heap_buf: Vec<MaybeUninit<u16>> = Vec::new();
     unsafe {
         let mut n = stack_buf.len();
         loop {
@@ -214,6 +215,11 @@ where
             } else {
                 let extra = n - heap_buf.len();
                 heap_buf.reserve(extra);
+                // We used `reserve` and not `reserve_exact`, so in theory we
+                // may have gotten more than requested. If so, we'd like to use
+                // it... so long as we won't cause overflow.
+                n = heap_buf.capacity().min(c::DWORD::MAX as usize);
+                // Safety: MaybeUninit<u16> does not need initialization
                 heap_buf.set_len(n);
                 &mut heap_buf[..]
             };
@@ -228,13 +234,13 @@ where
             // error" is still 0 then we interpret it as a 0 length buffer and
             // not an actual error.
             c::SetLastError(0);
-            let k = match f1(buf.as_mut_ptr(), n as c::DWORD) {
+            let k = match f1(buf.as_mut_ptr().cast::<u16>(), n as c::DWORD) {
                 0 if c::GetLastError() == 0 => 0,
                 0 => return Err(crate::io::Error::last_os_error()),
                 n => n,
             } as usize;
             if k == n && c::GetLastError() == c::ERROR_INSUFFICIENT_BUFFER {
-                n *= 2;
+                n = n.saturating_mul(2).min(c::DWORD::MAX as usize);
             } else if k > n {
                 n = k;
             } else if k == n {
@@ -244,7 +250,9 @@ where
                 // Therefore k never equals n.
                 unreachable!();
             } else {
-                return Ok(f2(&buf[..k]));
+                // Safety: First `k` values are initialized.
+                let slice: &[u16] = MaybeUninit::slice_assume_init_ref(&buf[..k]);
+                return Ok(f2(slice));
             }
         }
     }
diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs
index bcac996c024..352337ba322 100644
--- a/library/std/src/sys/windows/os.rs
+++ b/library/std/src/sys/windows/os.rs
@@ -99,11 +99,11 @@ impl Iterator for Env {
                 }
                 let p = self.cur as *const u16;
                 let mut len = 0;
-                while *p.offset(len) != 0 {
+                while *p.add(len) != 0 {
                     len += 1;
                 }
-                let s = slice::from_raw_parts(p, len as usize);
-                self.cur = self.cur.offset(len + 1);
+                let s = slice::from_raw_parts(p, len);
+                self.cur = self.cur.add(len + 1);
 
                 // Windows allows environment variables to start with an equals
                 // symbol (in any other position, this is the separator between
diff --git a/library/std/src/sys/windows/thread_parker.rs b/library/std/src/sys/windows/thread_parker.rs
index 16863c9903a..2f7ae863b6a 100644
--- a/library/std/src/sys/windows/thread_parker.rs
+++ b/library/std/src/sys/windows/thread_parker.rs
@@ -198,8 +198,18 @@ impl Parker {
         // with park().
         if self.state.swap(NOTIFIED, Release) == PARKED {
             unsafe {
-                // This calls either WakeByAddressSingle or unpark_keyed_event (see below).
-                c::wake_by_address_single_or_unpark_keyed_event(self.ptr());
+                if let Some(wake_by_address_single) = c::WakeByAddressSingle::option() {
+                    wake_by_address_single(self.ptr());
+                } else {
+                    // If we run NtReleaseKeyedEvent before the waiting thread runs
+                    // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
+                    // If the waiting thread wakes up before we run NtReleaseKeyedEvent
+                    // (e.g. due to a timeout), this blocks until we do wake up a thread.
+                    // To prevent this thread from blocking indefinitely in that case,
+                    // park_impl() will, after seeing the state set to NOTIFIED after
+                    // waking up, call NtWaitForKeyedEvent again to unblock us.
+                    c::NtReleaseKeyedEvent(keyed_event_handle(), self.ptr(), 0, ptr::null_mut());
+                }
             }
         }
     }
@@ -209,19 +219,6 @@ impl Parker {
     }
 }
 
-// This function signature makes it compatible with c::WakeByAddressSingle
-// so that it can be used as a fallback for that function.
-pub unsafe extern "C" fn unpark_keyed_event(address: c::LPVOID) {
-    // If we run NtReleaseKeyedEvent before the waiting thread runs
-    // NtWaitForKeyedEvent, this (shortly) blocks until we can wake it up.
-    // If the waiting thread wakes up before we run NtReleaseKeyedEvent
-    // (e.g. due to a timeout), this blocks until we do wake up a thread.
-    // To prevent this thread from blocking indefinitely in that case,
-    // park_impl() will, after seeing the state set to NOTIFIED after
-    // waking up, call NtWaitForKeyedEvent again to unblock us.
-    c::NtReleaseKeyedEvent(keyed_event_handle(), address, 0, ptr::null_mut());
-}
-
 fn keyed_event_handle() -> c::HANDLE {
     const INVALID: c::HANDLE = ptr::invalid_mut(!0);
     static HANDLE: AtomicPtr<libc::c_void> = AtomicPtr::new(INVALID);
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 57fa4989358..33e20756163 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -236,7 +236,8 @@ impl Wtf8Buf {
     /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid
     /// frequent reallocations. After calling `try_reserve`, capacity will be
     /// greater than or equal to `self.len() + additional`. Does nothing if
-    /// capacity is already sufficient.
+    /// capacity is already sufficient. This method preserves the contents even
+    /// if an error occurs.
     ///
     /// # Errors
     ///
diff --git a/library/std/src/thread/tests.rs b/library/std/src/thread/tests.rs
index ec68b529188..130e47c8d44 100644
--- a/library/std/src/thread/tests.rs
+++ b/library/std/src/thread/tests.rs
@@ -329,3 +329,22 @@ fn test_scoped_threads_nll() {
     let x = 42_u8;
     foo(&x);
 }
+
+// Regression test for https://github.com/rust-lang/rust/issues/98498.
+#[test]
+#[cfg(miri)] // relies on Miri's data race detector
+fn scope_join_race() {
+    for _ in 0..100 {
+        let a_bool = AtomicBool::new(false);
+
+        thread::scope(|s| {
+            for _ in 0..5 {
+                s.spawn(|| a_bool.load(Ordering::Relaxed));
+            }
+
+            for _ in 0..5 {
+                s.spawn(|| a_bool.load(Ordering::Relaxed));
+            }
+        });
+    }
+}
diff --git a/library/std/src/time/tests.rs b/library/std/src/time/tests.rs
index d710a574465..6229556c85f 100644
--- a/library/std/src/time/tests.rs
+++ b/library/std/src/time/tests.rs
@@ -31,7 +31,8 @@ fn instant_monotonic_concurrent() -> crate::thread::Result<()> {
         .map(|_| {
             crate::thread::spawn(|| {
                 let mut old = Instant::now();
-                for _ in 0..5_000_000 {
+                let count = if cfg!(miri) { 1_000 } else { 5_000_000 };
+                for _ in 0..count {
                     let new = Instant::now();
                     assert!(new >= old);
                     old = new;
diff --git a/src/bootstrap/bin/rustc.rs b/src/bootstrap/bin/rustc.rs
index 40a3cc6d12c..bd5790d2ea8 100644
--- a/src/bootstrap/bin/rustc.rs
+++ b/src/bootstrap/bin/rustc.rs
@@ -25,10 +25,11 @@ use std::time::Instant;
 
 fn main() {
     let args = env::args_os().skip(1).collect::<Vec<_>>();
+    let arg = |name| args.windows(2).find(|args| args[0] == name).and_then(|args| args[1].to_str());
 
     // Detect whether or not we're a build script depending on whether --target
     // is passed (a bit janky...)
-    let target = args.windows(2).find(|w| &*w[0] == "--target").and_then(|w| w[1].to_str());
+    let target = arg("--target");
     let version = args.iter().find(|w| &**w == "-vV");
 
     let verbose = match env::var("RUSTC_VERBOSE") {
@@ -59,8 +60,7 @@ fn main() {
     cmd.args(&args).env(dylib_path_var(), env::join_paths(&dylib_path).unwrap());
 
     // Get the name of the crate we're compiling, if any.
-    let crate_name =
-        args.windows(2).find(|args| args[0] == "--crate-name").and_then(|args| args[1].to_str());
+    let crate_name = arg("--crate-name");
 
     if let Some(crate_name) = crate_name {
         if let Some(target) = env::var_os("RUSTC_TIME") {
@@ -106,6 +106,15 @@ fn main() {
         {
             cmd.arg("-C").arg("panic=abort");
         }
+
+        // `-Ztls-model=initial-exec` must not be applied to proc-macros, see
+        // issue https://github.com/rust-lang/rust/issues/100530
+        if env::var("RUSTC_TLS_MODEL_INITIAL_EXEC").is_ok()
+            && arg("--crate-type") != Some("proc-macro")
+            && !matches!(crate_name, Some("proc_macro2" | "quote" | "syn" | "synstructure"))
+        {
+            cmd.arg("-Ztls-model=initial-exec");
+        }
     } else {
         // FIXME(rust-lang/cargo#5754) we shouldn't be using special env vars
         // here, but rather Cargo should know what flags to pass rustc itself.
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index 0ab4824ac0a..945299d2dcd 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -1850,7 +1850,7 @@ impl<'a> Builder<'a> {
         // so we can't use it by default in general, but we can use it for tools
         // and our own internal libraries.
         if !mode.must_support_dlopen() && !target.triple.starts_with("powerpc-") {
-            rustflags.arg("-Ztls-model=initial-exec");
+            cargo.env("RUSTC_TLS_MODEL_INITIAL_EXEC", "1");
         }
 
         if self.config.incremental {
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 203db2d3876..13e3049f2c8 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -990,42 +990,7 @@ impl Config {
             config.llvm_from_ci = match llvm.download_ci_llvm {
                 Some(StringOrBool::String(s)) => {
                     assert!(s == "if-available", "unknown option `{}` for download-ci-llvm", s);
-                    // This is currently all tier 1 targets and tier 2 targets with host tools
-                    // (since others may not have CI artifacts)
-                    // https://doc.rust-lang.org/rustc/platform-support.html#tier-1
-                    // FIXME: this is duplicated in bootstrap.py
-                    let supported_platforms = [
-                        // tier 1
-                        "aarch64-unknown-linux-gnu",
-                        "i686-pc-windows-gnu",
-                        "i686-pc-windows-msvc",
-                        "i686-unknown-linux-gnu",
-                        "x86_64-unknown-linux-gnu",
-                        "x86_64-apple-darwin",
-                        "x86_64-pc-windows-gnu",
-                        "x86_64-pc-windows-msvc",
-                        // tier 2 with host tools
-                        "aarch64-apple-darwin",
-                        "aarch64-pc-windows-msvc",
-                        "aarch64-unknown-linux-musl",
-                        "arm-unknown-linux-gnueabi",
-                        "arm-unknown-linux-gnueabihf",
-                        "armv7-unknown-linux-gnueabihf",
-                        "mips-unknown-linux-gnu",
-                        "mips64-unknown-linux-gnuabi64",
-                        "mips64el-unknown-linux-gnuabi64",
-                        "mipsel-unknown-linux-gnu",
-                        "powerpc-unknown-linux-gnu",
-                        "powerpc64-unknown-linux-gnu",
-                        "powerpc64le-unknown-linux-gnu",
-                        "riscv64gc-unknown-linux-gnu",
-                        "s390x-unknown-linux-gnu",
-                        "x86_64-unknown-freebsd",
-                        "x86_64-unknown-illumos",
-                        "x86_64-unknown-linux-musl",
-                        "x86_64-unknown-netbsd",
-                    ];
-                    supported_platforms.contains(&&*config.build.triple)
+                    crate::native::is_ci_llvm_available(&config, llvm_assertions.unwrap_or(false))
                 }
                 Some(StringOrBool::Bool(b)) => b,
                 None => false,
@@ -1176,6 +1141,7 @@ impl Config {
 
         if config.llvm_from_ci {
             let triple = &config.build.triple;
+            let ci_llvm_bin = config.ci_llvm_root().join("bin");
             let mut build_target = config
                 .target_config
                 .entry(config.build)
@@ -1183,7 +1149,6 @@ impl Config {
 
             check_ci_llvm!(build_target.llvm_config);
             check_ci_llvm!(build_target.llvm_filecheck);
-            let ci_llvm_bin = config.out.join(&*config.build.triple).join("ci-llvm/bin");
             build_target.llvm_config = Some(ci_llvm_bin.join(exe("llvm-config", config.build)));
             build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
         }
diff --git a/src/bootstrap/native.rs b/src/bootstrap/native.rs
index 1bba5e68be4..7ecf74d3068 100644
--- a/src/bootstrap/native.rs
+++ b/src/bootstrap/native.rs
@@ -114,23 +114,20 @@ pub fn prebuilt_llvm_config(
     Err(Meta { stamp, build_llvm_config, out_dir, root: root.into() })
 }
 
-pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
-    let config = &builder.config;
-    if !config.llvm_from_ci {
-        return;
-    }
+/// This retrieves the LLVM sha we *want* to use, according to git history.
+pub(crate) fn detect_llvm_sha(config: &crate::config::Config) -> String {
     let mut rev_list = config.git();
     rev_list.args(&[
         PathBuf::from("rev-list"),
-        format!("--author={}", builder.config.stage0_metadata.config.git_merge_commit_email).into(),
+        format!("--author={}", config.stage0_metadata.config.git_merge_commit_email).into(),
         "-n1".into(),
         "--first-parent".into(),
         "HEAD".into(),
         "--".into(),
-        builder.src.join("src/llvm-project"),
-        builder.src.join("src/bootstrap/download-ci-llvm-stamp"),
+        config.src.join("src/llvm-project"),
+        config.src.join("src/bootstrap/download-ci-llvm-stamp"),
         // the LLVM shared object file is named `LLVM-12-rust-{version}-nightly`
-        builder.src.join("src/version"),
+        config.src.join("src/version"),
     ]);
     let llvm_sha = output(&mut rev_list);
     let llvm_sha = llvm_sha.trim();
@@ -143,8 +140,82 @@ pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
         panic!();
     }
 
+    llvm_sha.to_owned()
+}
+
+/// Returns whether the CI-found LLVM is currently usable.
+///
+/// This checks both the build triple platform to confirm we're usable at all,
+/// and then verifies if the current HEAD matches the detected LLVM SHA head,
+/// in which case LLVM is indicated as not available.
+pub(crate) fn is_ci_llvm_available(config: &crate::config::Config, asserts: bool) -> bool {
+    // This is currently all tier 1 targets and tier 2 targets with host tools
+    // (since others may not have CI artifacts)
+    // https://doc.rust-lang.org/rustc/platform-support.html#tier-1
+    let supported_platforms = [
+        // tier 1
+        "aarch64-unknown-linux-gnu",
+        "i686-pc-windows-gnu",
+        "i686-pc-windows-msvc",
+        "i686-unknown-linux-gnu",
+        "x86_64-unknown-linux-gnu",
+        "x86_64-apple-darwin",
+        "x86_64-pc-windows-gnu",
+        "x86_64-pc-windows-msvc",
+        // tier 2 with host tools
+        "aarch64-apple-darwin",
+        "aarch64-pc-windows-msvc",
+        "aarch64-unknown-linux-musl",
+        "arm-unknown-linux-gnueabi",
+        "arm-unknown-linux-gnueabihf",
+        "armv7-unknown-linux-gnueabihf",
+        "mips-unknown-linux-gnu",
+        "mips64-unknown-linux-gnuabi64",
+        "mips64el-unknown-linux-gnuabi64",
+        "mipsel-unknown-linux-gnu",
+        "powerpc-unknown-linux-gnu",
+        "powerpc64-unknown-linux-gnu",
+        "powerpc64le-unknown-linux-gnu",
+        "riscv64gc-unknown-linux-gnu",
+        "s390x-unknown-linux-gnu",
+        "x86_64-unknown-freebsd",
+        "x86_64-unknown-illumos",
+        "x86_64-unknown-linux-musl",
+        "x86_64-unknown-netbsd",
+    ];
+    if !supported_platforms.contains(&&*config.build.triple) {
+        return false;
+    }
+
+    let triple = &*config.build.triple;
+    if (triple == "aarch64-unknown-linux-gnu" || triple.contains("i686")) && asserts {
+        // No alt builder for aarch64-unknown-linux-gnu today.
+        return false;
+    }
+
+    if crate::util::CiEnv::is_ci() {
+        let llvm_sha = detect_llvm_sha(config);
+        let head_sha = output(config.git().arg("rev-parse").arg("HEAD"));
+        let head_sha = head_sha.trim();
+        if llvm_sha == head_sha {
+            eprintln!(
+                "Detected LLVM as non-available: running in CI and modified LLVM in this change"
+            );
+            return false;
+        }
+    }
+
+    true
+}
+
+pub(crate) fn maybe_download_ci_llvm(builder: &Builder<'_>) {
+    let config = &builder.config;
+    if !config.llvm_from_ci {
+        return;
+    }
     let llvm_root = config.ci_llvm_root();
     let llvm_stamp = llvm_root.join(".llvm-stamp");
+    let llvm_sha = detect_llvm_sha(&config);
     let key = format!("{}{}", llvm_sha, config.llvm_assertions);
     if program_out_of_date(&llvm_stamp, &key) && !config.dry_run {
         download_ci_llvm(builder, &llvm_sha);
diff --git a/src/bootstrap/util.rs b/src/bootstrap/util.rs
index 1895e290148..3a00e258e00 100644
--- a/src/bootstrap/util.rs
+++ b/src/bootstrap/util.rs
@@ -258,6 +258,10 @@ impl CiEnv {
         }
     }
 
+    pub fn is_ci() -> bool {
+        Self::current() != CiEnv::None
+    }
+
     /// If in a CI environment, forces the command to run with colors.
     pub fn force_coloring_in_ci(self, cmd: &mut Command) {
         if self != CiEnv::None {
diff --git a/src/ci/docker/host-x86_64/arm-android/Dockerfile b/src/ci/docker/host-x86_64/arm-android/Dockerfile
index a2335687ab3..d0d367b39b4 100644
--- a/src/ci/docker/host-x86_64/arm-android/Dockerfile
+++ b/src/ci/docker/host-x86_64/arm-android/Dockerfile
@@ -29,6 +29,10 @@ ENV PATH=$PATH:/android/sdk/platform-tools
 
 ENV TARGETS=arm-linux-androideabi
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS --arm-linux-androideabi-ndk=/android/ndk/arm-14 \
     --set llvm.allow-old-toolchain
 
diff --git a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
index e2dbc7cfd7c..69f88e49520 100644
--- a/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/armhf-gnu/Dockerfile
@@ -78,6 +78,8 @@ RUN curl -O https://ci-mirrors.rust-lang.org/rustc/vexpress-v2p-ca15-tc1.dtb
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+COPY static/gitconfig /etc/gitconfig
+
 ENV RUST_CONFIGURE_ARGS --qemu-armhf-rootfs=/tmp/rootfs
 ENV SCRIPT python3 ../x.py --stage 2 test --host='' --target arm-unknown-linux-gnueabihf
 
diff --git a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
index 1f8d0a64ea4..71ea13071bd 100644
--- a/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu-nopt/Dockerfile
@@ -27,6 +27,10 @@ RUN mkdir -p /config
 RUN echo "[rust]" > /config/nopt-std-config.toml
 RUN echo "optimize = false" >> /config/nopt-std-config.toml
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu --disable-optimize-tests \
     --set llvm.allow-old-toolchain
 ENV SCRIPT python3 ../x.py test --stage 0 --config /config/nopt-std-config.toml library/std \
diff --git a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
index 7bca0398dea..ebeab3dbdb7 100644
--- a/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
+++ b/src/ci/docker/host-x86_64/i686-gnu/Dockerfile
@@ -23,6 +23,9 @@ RUN sh /scripts/sccache.sh
 COPY scripts/cmake.sh /scripts/
 RUN /scripts/cmake.sh
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
 ENV RUST_CONFIGURE_ARGS --build=i686-unknown-linux-gnu \
     --set llvm.allow-old-toolchain
 # Exclude some tests that are unlikely to be platform specific, to speed up
diff --git a/src/ci/docker/host-x86_64/mingw-check/Dockerfile b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
index 9ee84f420b9..c6723d91c8b 100644
--- a/src/ci/docker/host-x86_64/mingw-check/Dockerfile
+++ b/src/ci/docker/host-x86_64/mingw-check/Dockerfile
@@ -1,4 +1,7 @@
 FROM ubuntu:18.04
+# FIXME: when bumping the version, remove the Python 3.6-specific changes in
+# the reuse-requirements.in file, regenerate reuse-requirements.txt and remove
+# this comment.
 
 RUN apt-get update && apt-get install -y --no-install-recommends \
   g++ \
@@ -8,6 +11,8 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
   curl \
   ca-certificates \
   python3 \
+  python3-pip \
+  python3-pkg-resources \
   git \
   cmake \
   sudo \
@@ -27,6 +32,9 @@ RUN npm install eslint@8.6.0 -g
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+COPY host-x86_64/mingw-check/reuse-requirements.txt /tmp/
+RUN pip3 install --no-deps --require-hashes -r /tmp/reuse-requirements.txt
+
 COPY host-x86_64/mingw-check/validate-toolstate.sh /scripts/
 COPY host-x86_64/mingw-check/validate-error-codes.sh /scripts/
 
@@ -40,6 +48,7 @@ ENV SCRIPT python3 ../x.py --stage 2 test src/tools/expand-yaml-anchors && \
            python3 ../x.py doc --stage 0 library/test && \
            /scripts/validate-toolstate.sh && \
            /scripts/validate-error-codes.sh && \
+           reuse lint && \
            # Runs checks to ensure that there are no ES5 issues in our JS code.
            es-check es6 ../src/librustdoc/html/static/js/*.js && \
            eslint -c ../src/librustdoc/html/static/.eslintrc.js ../src/librustdoc/html/static/js/*.js
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
new file mode 100644
index 00000000000..4964f40aa39
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.in
@@ -0,0 +1,22 @@
+# This is the template for reuse-requirements.txt.
+#
+# The pip-tools project is used to generate the file again. To install it, the
+# recommended way is to:
+#
+# - Install pipx from https://github.com/pypa/pipx
+# - Run `pipx install pip-tools`
+#
+# Once pip-tools is installed, run this command to regenerate the .txt file:
+#
+#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
+#
+
+reuse
+
+# Some packages dropped support for Python 3.6, which is the version used in
+# this builder (due to Ubuntu 18.04). This should be removed once we bump the
+# Ubuntu version of the builder.
+jinja2 < 3.1
+markupsafe < 2.1
+requests < 2.28
+setuptools < 59.7
diff --git a/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
new file mode 100644
index 00000000000..10a5f738790
--- /dev/null
+++ b/src/ci/docker/host-x86_64/mingw-check/reuse-requirements.txt
@@ -0,0 +1,145 @@
+#
+# This file is autogenerated by pip-compile with python 3.10
+# To update, run:
+#
+#    pip-compile --allow-unsafe --generate-hashes reuse-requirements.in
+#
+binaryornot==0.4.4 \
+    --hash=sha256:359501dfc9d40632edc9fac890e19542db1a287bbcfa58175b66658392018061 \
+    --hash=sha256:b8b71173c917bddcd2c16070412e369c3ed7f0528926f70cac18a6c97fd563e4
+    # via reuse
+boolean-py==3.8 \
+    --hash=sha256:cc24e20f985d60cd4a3a5a1c0956dd12611159d32a75081dabd0c9ab981acaa4 \
+    --hash=sha256:d75da0fd0354425fa64f6bbc6cec6ae1485d0eec3447b73187ff8cbf9b572e26
+    # via
+    #   license-expression
+    #   reuse
+certifi==2022.6.15 \
+    --hash=sha256:84c85a9078b11105f04f3036a9482ae10e4621616db313fe045dd24743a0820d \
+    --hash=sha256:fe86415d55e84719d75f8b69414f6438ac3547d2078ab91b67e779ef69378412
+    # via requests
+chardet==5.0.0 \
+    --hash=sha256:0368df2bfd78b5fc20572bb4e9bb7fb53e2c094f60ae9993339e8671d0afb8aa \
+    --hash=sha256:d3e64f022d254183001eccc5db4040520c0f23b1a3f33d6413e099eb7f126557
+    # via
+    #   binaryornot
+    #   python-debian
+charset-normalizer==2.0.12 \
+    --hash=sha256:2857e29ff0d34db842cd7ca3230549d1a697f96ee6d3fb071cfa6c7393832597 \
+    --hash=sha256:6881edbebdb17b39b4eaaa821b438bf6eddffb4468cf344f09f89def34a8b1df
+    # via requests
+idna==3.3 \
+    --hash=sha256:84d9dd047ffa80596e0f246e2eab0b391788b0503584e8945f2368256d2735ff \
+    --hash=sha256:9d643ff0a55b762d5cdb124b8eaa99c66322e2157b69160bc32796e824360e6d
+    # via requests
+jinja2==3.0.3 \
+    --hash=sha256:077ce6014f7b40d03b47d1f1ca4b0fc8328a692bd284016f806ed0eaca390ad8 \
+    --hash=sha256:611bb273cd68f3b993fabdc4064fc858c5b47a973cb5aa7999ec1ba405c87cd7
+    # via
+    #   -r reuse-requirements.in
+    #   reuse
+license-expression==21.6.14 \
+    --hash=sha256:324246eed8e138b4139fefdc0e9dc4161d5075e3929e56983966d37298dca30e \
+    --hash=sha256:9de87a427c9a449eee7913472fb9ed03b63036295547369fdbf95f76a8b924b2
+    # via
+    #   -r reuse-requirements.in
+    #   reuse
+markupsafe==2.0.1 \
+    --hash=sha256:01a9b8ea66f1658938f65b93a85ebe8bc016e6769611be228d797c9d998dd298 \
+    --hash=sha256:023cb26ec21ece8dc3907c0e8320058b2e0cb3c55cf9564da612bc325bed5e64 \
+    --hash=sha256:0446679737af14f45767963a1a9ef7620189912317d095f2d9ffa183a4d25d2b \
+    --hash=sha256:04635854b943835a6ea959e948d19dcd311762c5c0c6e1f0e16ee57022669194 \
+    --hash=sha256:0717a7390a68be14b8c793ba258e075c6f4ca819f15edfc2a3a027c823718567 \
+    --hash=sha256:0955295dd5eec6cb6cc2fe1698f4c6d84af2e92de33fbcac4111913cd100a6ff \
+    --hash=sha256:0d4b31cc67ab36e3392bbf3862cfbadac3db12bdd8b02a2731f509ed5b829724 \
+    --hash=sha256:10f82115e21dc0dfec9ab5c0223652f7197feb168c940f3ef61563fc2d6beb74 \
+    --hash=sha256:168cd0a3642de83558a5153c8bd34f175a9a6e7f6dc6384b9655d2697312a646 \
+    --hash=sha256:1d609f577dc6e1aa17d746f8bd3c31aa4d258f4070d61b2aa5c4166c1539de35 \
+    --hash=sha256:1f2ade76b9903f39aa442b4aadd2177decb66525062db244b35d71d0ee8599b6 \
+    --hash=sha256:20dca64a3ef2d6e4d5d615a3fd418ad3bde77a47ec8a23d984a12b5b4c74491a \
+    --hash=sha256:2a7d351cbd8cfeb19ca00de495e224dea7e7d919659c2841bbb7f420ad03e2d6 \
+    --hash=sha256:2d7d807855b419fc2ed3e631034685db6079889a1f01d5d9dac950f764da3dad \
+    --hash=sha256:2ef54abee730b502252bcdf31b10dacb0a416229b72c18b19e24a4509f273d26 \
+    --hash=sha256:36bc903cbb393720fad60fc28c10de6acf10dc6cc883f3e24ee4012371399a38 \
+    --hash=sha256:37205cac2a79194e3750b0af2a5720d95f786a55ce7df90c3af697bfa100eaac \
+    --hash=sha256:3c112550557578c26af18a1ccc9e090bfe03832ae994343cfdacd287db6a6ae7 \
+    --hash=sha256:3dd007d54ee88b46be476e293f48c85048603f5f516008bee124ddd891398ed6 \
+    --hash=sha256:4296f2b1ce8c86a6aea78613c34bb1a672ea0e3de9c6ba08a960efe0b0a09047 \
+    --hash=sha256:47ab1e7b91c098ab893b828deafa1203de86d0bc6ab587b160f78fe6c4011f75 \
+    --hash=sha256:49e3ceeabbfb9d66c3aef5af3a60cc43b85c33df25ce03d0031a608b0a8b2e3f \
+    --hash=sha256:4dc8f9fb58f7364b63fd9f85013b780ef83c11857ae79f2feda41e270468dd9b \
+    --hash=sha256:4efca8f86c54b22348a5467704e3fec767b2db12fc39c6d963168ab1d3fc9135 \
+    --hash=sha256:53edb4da6925ad13c07b6d26c2a852bd81e364f95301c66e930ab2aef5b5ddd8 \
+    --hash=sha256:5855f8438a7d1d458206a2466bf82b0f104a3724bf96a1c781ab731e4201731a \
+    --hash=sha256:594c67807fb16238b30c44bdf74f36c02cdf22d1c8cda91ef8a0ed8dabf5620a \
+    --hash=sha256:5b6d930f030f8ed98e3e6c98ffa0652bdb82601e7a016ec2ab5d7ff23baa78d1 \
+    --hash=sha256:5bb28c636d87e840583ee3adeb78172efc47c8b26127267f54a9c0ec251d41a9 \
+    --hash=sha256:60bf42e36abfaf9aff1f50f52644b336d4f0a3fd6d8a60ca0d054ac9f713a864 \
+    --hash=sha256:611d1ad9a4288cf3e3c16014564df047fe08410e628f89805e475368bd304914 \
+    --hash=sha256:6300b8454aa6930a24b9618fbb54b5a68135092bc666f7b06901f897fa5c2fee \
+    --hash=sha256:63f3268ba69ace99cab4e3e3b5840b03340efed0948ab8f78d2fd87ee5442a4f \
+    --hash=sha256:6557b31b5e2c9ddf0de32a691f2312a32f77cd7681d8af66c2692efdbef84c18 \
+    --hash=sha256:693ce3f9e70a6cf7d2fb9e6c9d8b204b6b39897a2c4a1aa65728d5ac97dcc1d8 \
+    --hash=sha256:6a7fae0dd14cf60ad5ff42baa2e95727c3d81ded453457771d02b7d2b3f9c0c2 \
+    --hash=sha256:6c4ca60fa24e85fe25b912b01e62cb969d69a23a5d5867682dd3e80b5b02581d \
+    --hash=sha256:6fcf051089389abe060c9cd7caa212c707e58153afa2c649f00346ce6d260f1b \
+    --hash=sha256:7d91275b0245b1da4d4cfa07e0faedd5b0812efc15b702576d103293e252af1b \
+    --hash=sha256:89c687013cb1cd489a0f0ac24febe8c7a666e6e221b783e53ac50ebf68e45d86 \
+    --hash=sha256:8d206346619592c6200148b01a2142798c989edcb9c896f9ac9722a99d4e77e6 \
+    --hash=sha256:905fec760bd2fa1388bb5b489ee8ee5f7291d692638ea5f67982d968366bef9f \
+    --hash=sha256:97383d78eb34da7e1fa37dd273c20ad4320929af65d156e35a5e2d89566d9dfb \
+    --hash=sha256:984d76483eb32f1bcb536dc27e4ad56bba4baa70be32fa87152832cdd9db0833 \
+    --hash=sha256:99df47edb6bda1249d3e80fdabb1dab8c08ef3975f69aed437cb69d0a5de1e28 \
+    --hash=sha256:9f02365d4e99430a12647f09b6cc8bab61a6564363f313126f775eb4f6ef798e \
+    --hash=sha256:a30e67a65b53ea0a5e62fe23682cfe22712e01f453b95233b25502f7c61cb415 \
+    --hash=sha256:ab3ef638ace319fa26553db0624c4699e31a28bb2a835c5faca8f8acf6a5a902 \
+    --hash=sha256:aca6377c0cb8a8253e493c6b451565ac77e98c2951c45f913e0b52facdcff83f \
+    --hash=sha256:add36cb2dbb8b736611303cd3bfcee00afd96471b09cda130da3581cbdc56a6d \
+    --hash=sha256:b2f4bf27480f5e5e8ce285a8c8fd176c0b03e93dcc6646477d4630e83440c6a9 \
+    --hash=sha256:b7f2d075102dc8c794cbde1947378051c4e5180d52d276987b8d28a3bd58c17d \
+    --hash=sha256:baa1a4e8f868845af802979fcdbf0bb11f94f1cb7ced4c4b8a351bb60d108145 \
+    --hash=sha256:be98f628055368795d818ebf93da628541e10b75b41c559fdf36d104c5787066 \
+    --hash=sha256:bf5d821ffabf0ef3533c39c518f3357b171a1651c1ff6827325e4489b0e46c3c \
+    --hash=sha256:c47adbc92fc1bb2b3274c4b3a43ae0e4573d9fbff4f54cd484555edbf030baf1 \
+    --hash=sha256:cdfba22ea2f0029c9261a4bd07e830a8da012291fbe44dc794e488b6c9bb353a \
+    --hash=sha256:d6c7ebd4e944c85e2c3421e612a7057a2f48d478d79e61800d81468a8d842207 \
+    --hash=sha256:d7f9850398e85aba693bb640262d3611788b1f29a79f0c93c565694658f4071f \
+    --hash=sha256:d8446c54dc28c01e5a2dbac5a25f071f6653e6e40f3a8818e8b45d790fe6ef53 \
+    --hash=sha256:deb993cacb280823246a026e3b2d81c493c53de6acfd5e6bfe31ab3402bb37dd \
+    --hash=sha256:e0f138900af21926a02425cf736db95be9f4af72ba1bb21453432a07f6082134 \
+    --hash=sha256:e9936f0b261d4df76ad22f8fee3ae83b60d7c3e871292cd42f40b81b70afae85 \
+    --hash=sha256:f0567c4dc99f264f49fe27da5f735f414c4e7e7dd850cfd8e69f0862d7c74ea9 \
+    --hash=sha256:f5653a225f31e113b152e56f154ccbe59eeb1c7487b39b9d9f9cdb58e6c79dc5 \
+    --hash=sha256:f826e31d18b516f653fe296d967d700fddad5901ae07c622bb3705955e1faa94 \
+    --hash=sha256:f8ba0e8349a38d3001fae7eadded3f6606f0da5d748ee53cc1dab1d6527b9509 \
+    --hash=sha256:f9081981fe268bd86831e5c75f7de206ef275defcb82bc70740ae6dc507aee51 \
+    --hash=sha256:fa130dd50c57d53368c9d59395cb5526eda596d3ffe36666cd81a44d56e48872
+    # via
+    #   -r reuse-requirements.in
+    #   jinja2
+python-debian==0.1.44 \
+    --hash=sha256:11bd6f01c46da57982bdd66dd595e2d240feb32a85de3fd37c452102fd0337ab \
+    --hash=sha256:65592fe3b64f6c6c93d94e2d2599db5e0c22831d3bcff07cb7b96d3840b1333e
+    # via reuse
+requests==2.26.0 \
+    --hash=sha256:6c1246513ecd5ecd4528a0906f910e8f0f9c6b8ec72030dc9fd154dc1a6efd24 \
+    --hash=sha256:b8aa58f8cf793ffd8782d3d8cb19e66ef36f7aba4353eec859e74678b01b07a7
+    # via
+    #   -r reuse-requirements.in
+    #   reuse
+reuse==1.0.0 \
+    --hash=sha256:db3022be2d87f69c8f508b928023de3026f454ce17d01e22f770f7147ac1e8d4 \
+    --hash=sha256:e2605e796311c424465d741ea2a1e1ad03bbb90b921d74750119c331ca5af46e
+    # via -r reuse-requirements.in
+urllib3==1.26.10 \
+    --hash=sha256:8298d6d56d39be0e3bc13c1c97d133f9b45d797169a0e11cdd0e0489d786f7ec \
+    --hash=sha256:879ba4d1e89654d9769ce13121e0f94310ea32e8d2f8cf587b77c08bbcdb30d6
+    # via requests
+
+# The following packages are considered to be unsafe in a requirements file:
+setuptools==59.6.0 \
+    --hash=sha256:22c7348c6d2976a52632c67f7ab0cdf40147db7789f9aed18734643fe9cf3373 \
+    --hash=sha256:4ce92f1e1f8f01233ee9952c04f6b81d1e02939d6e1b488428154974a4d0783e
+    # via
+    #   -r reuse-requirements.in
+    #   reuse
diff --git a/src/ci/docker/host-x86_64/test-various/Dockerfile b/src/ci/docker/host-x86_64/test-various/Dockerfile
index 4d554a2852a..b75e2f085cd 100644
--- a/src/ci/docker/host-x86_64/test-various/Dockerfile
+++ b/src/ci/docker/host-x86_64/test-various/Dockerfile
@@ -30,6 +30,10 @@ WORKDIR /
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
+# We are disabling CI LLVM since this builder needs to build LLD, which is
+# currently unsupported when downloading pre-built LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS \
   --musl-root-x86_64=/usr/local/x86_64-linux-musl \
   --set build.nodejs=/node-v15.14.0-linux-x64/bin/node \
diff --git a/src/ci/docker/host-x86_64/wasm32/Dockerfile b/src/ci/docker/host-x86_64/wasm32/Dockerfile
index 878c4e34158..9e37c2822e8 100644
--- a/src/ci/docker/host-x86_64/wasm32/Dockerfile
+++ b/src/ci/docker/host-x86_64/wasm32/Dockerfile
@@ -48,6 +48,8 @@ ENV TARGETS=wasm32-unknown-emscripten
 # Use -O1 optimizations in the link step to reduce time spent optimizing.
 ENV EMCC_CFLAGS=-O1
 
+COPY static/gitconfig /etc/gitconfig
+
 # Emscripten installation is user-specific
 ENV NO_CHANGE_USER=1
 
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
index bfc6975c19d..321b3d6ace4 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-aux/Dockerfile
@@ -26,6 +26,10 @@ RUN sh /scripts/sccache.sh
 COPY scripts/cmake.sh /scripts/
 RUN /scripts/cmake.sh
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu \
     --set llvm.allow-old-toolchain
 ENV RUST_CHECK_TARGET check-aux
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
index 13d440423b2..739045248fe 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-debug/Dockerfile
@@ -31,6 +31,9 @@ RUN sh /scripts/sccache.sh
 ENV RUSTBUILD_FORCE_CLANG_BASED_TESTS 1
 ENV RUN_CHECK_WITH_PARALLEL_QUERIES 1
 
+# llvm.use-linker conflicts with downloading CI LLVM
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --enable-debug \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
index 4bb4042cd7e..be4def85f14 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-distcheck/Dockerfile
@@ -22,6 +22,10 @@ RUN sh /scripts/sccache.sh
 COPY scripts/cmake.sh /scripts/
 RUN /scripts/cmake.sh
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS --build=x86_64-unknown-linux-gnu --set rust.ignore-git=false \
     --set llvm.allow-old-toolchain
 ENV SCRIPT python3 ../x.py --stage 2 test distcheck
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
index 21891c1244d..23f2215c2d9 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13-stage1/Dockerfile
@@ -26,7 +26,11 @@ RUN apt-get update && apt-get install -y --no-install-recommends \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-# using llvm-link-shared due to libffi issues -- see #34486
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
 ENV RUST_CONFIGURE_ARGS \
     --build=x86_64-unknown-linux-gnu \
     --llvm-root=/usr/lib/llvm-13 \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
index 5f3af2f47ca..8f6831bc54e 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-llvm-13/Dockerfile
@@ -37,7 +37,11 @@ RUN apt-get update && \
 COPY scripts/sccache.sh /scripts/
 RUN sh /scripts/sccache.sh
 
-# using llvm-link-shared due to libffi issues -- see #34486
+# We are disabling CI LLVM since this builder is intentionally using a host
+# LLVM, rather than the typical src/llvm-project LLVM.
+ENV NO_DOWNLOAD_CI_LLVM 1
+
+# Using llvm-link-shared due to libffi issues -- see #34486
 ENV RUST_CONFIGURE_ARGS \
       --build=x86_64-unknown-linux-gnu \
       --llvm-root=/usr/lib/llvm-13 \
diff --git a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
index f442a477a7b..e2ec4f27500 100644
--- a/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
+++ b/src/ci/docker/host-x86_64/x86_64-gnu-tools/Dockerfile
@@ -80,6 +80,10 @@ COPY host-x86_64/x86_64-gnu-tools/browser-ui-test.version /tmp/
 # the local version of the package is different than the one used by the CI.
 RUN npm install -g browser-ui-test@$(head -n 1 /tmp/browser-ui-test.version) --unsafe-perm=true
 
+# We are intentionally allowing an old toolchain on this builder (and that's
+# incompatible with LLVM downloads today).
+ENV NO_DOWNLOAD_CI_LLVM 1
+
 ENV RUST_CONFIGURE_ARGS \
   --set llvm.allow-old-toolchain \
   --build=x86_64-unknown-linux-gnu \
diff --git a/src/ci/docker/static/gitconfig b/src/ci/docker/static/gitconfig
new file mode 100644
index 00000000000..6bad35f01ce
--- /dev/null
+++ b/src/ci/docker/static/gitconfig
@@ -0,0 +1,2 @@
+[safe]
+directory = *
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 91204eb0b05..a6bdd9f3186 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -600,6 +600,9 @@ jobs:
                 --build=i686-pc-windows-gnu
                 --set llvm.allow-old-toolchain
               SCRIPT: make ci-mingw-subset-1
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             <<: *job-windows-xl
 
@@ -609,6 +612,9 @@ jobs:
                 --build=i686-pc-windows-gnu
                 --set llvm.allow-old-toolchain
               SCRIPT: make ci-mingw-subset-2
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             <<: *job-windows-xl
 
@@ -619,6 +625,9 @@ jobs:
                 --build=x86_64-pc-windows-gnu
                 --enable-profiler
                 --set llvm.allow-old-toolchain
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             <<: *job-windows-xl
 
@@ -629,6 +638,9 @@ jobs:
                 --build=x86_64-pc-windows-gnu
                 --enable-profiler
                 --set llvm.allow-old-toolchain
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
             <<: *job-windows-xl
 
@@ -678,6 +690,9 @@ jobs:
                 --enable-full-tools
                 --enable-profiler
                 --set llvm.allow-old-toolchain
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               SCRIPT: python x.py dist
               CUSTOM_MINGW: 1
               DIST_REQUIRE_ALL_TOOLS: 1
@@ -691,6 +706,9 @@ jobs:
                 --enable-full-tools
                 --enable-profiler
                 --set llvm.allow-old-toolchain
+              # We are intentionally allowing an old toolchain on this builder (and that's
+              # incompatible with LLVM downloads today).
+              NO_DOWNLOAD_CI_LLVM: 1
               CUSTOM_MINGW: 1
               DIST_REQUIRE_ALL_TOOLS: 1
             <<: *job-windows-xl
diff --git a/src/ci/run.sh b/src/ci/run.sh
index 6545475d996..9a247fb60a8 100755
--- a/src/ci/run.sh
+++ b/src/ci/run.sh
@@ -11,6 +11,16 @@ if [ "$NO_CHANGE_USER" = "" ]; then
     useradd --shell /bin/bash -u $LOCAL_USER_ID -o -c "" -m user
     export HOME=/home/user
     unset LOCAL_USER_ID
+
+    # Ensure that runners are able to execute git commands in the worktree,
+    # overriding the typical git protections. In our docker container we're running
+    # as root, while the user owning the checkout is not root.
+    # This is only necessary when we change the user, otherwise we should
+    # already be running with the right user.
+    #
+    # For NO_CHANGE_USER done in the small number of Dockerfiles affected.
+    echo -e '[safe]\n\tdirectory = *' > /home/user/gitconfig
+
     exec su --preserve-environment -c "env PATH=$PATH \"$0\"" user
   fi
 fi
@@ -102,6 +112,18 @@ else
   fi
 
   RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set rust.verify-llvm-ir"
+
+  # We enable this for non-dist builders, since those aren't trying to produce
+  # fresh binaries. We currently don't entirely support distributing a fresh
+  # copy of the compiler (including llvm tools, etc.) if we haven't actually
+  # built LLVM, since not everything necessary is copied into the
+  # local-usage-only LLVM artifacts. If that changes, this could maybe be made
+  # true for all builds. In practice it's probably a good idea to keep building
+  # LLVM continuously on at least some builders to ensure it works, though.
+  # (And PGO is its own can of worms).
+  if [ "$NO_DOWNLOAD_CI_LLVM" = "" ]; then
+    RUST_CONFIGURE_ARGS="$RUST_CONFIGURE_ARGS --set llvm.download-ci-llvm=if-available"
+  fi
 fi
 
 if [ "$RUST_RELEASE_CHANNEL" = "nightly" ] || [ "$DIST_REQUIRE_ALL_TOOLS" = "" ]; then
diff --git a/src/ci/scripts/install-clang.sh b/src/ci/scripts/install-clang.sh
index 0bc8a0389a8..02b72625d6e 100755
--- a/src/ci/scripts/install-clang.sh
+++ b/src/ci/scripts/install-clang.sh
@@ -61,6 +61,10 @@ elif isWindows && [[ ${CUSTOM_MINGW-0} -ne 1 ]]; then
     7z x -oclang-rust/ "LLVM-${LLVM_VERSION}-win64.exe"
     ciCommandSetEnv RUST_CONFIGURE_ARGS \
         "${RUST_CONFIGURE_ARGS} --set llvm.clang-cl=$(pwd)/clang-rust/bin/clang-cl.exe"
+
+    # Disable downloading CI LLVM on this builder;
+    # setting up clang-cl just above conflicts with the default if-available option.
+    ciCommandSetEnv NO_DOWNLOAD_CI_LLVM 1
 fi
 
 if isWindows; then
diff --git a/src/doc/rustc/src/platform-support/fuchsia.md b/src/doc/rustc/src/platform-support/fuchsia.md
index c526e4d1fa8..8b204949a6e 100644
--- a/src/doc/rustc/src/platform-support/fuchsia.md
+++ b/src/doc/rustc/src/platform-support/fuchsia.md
@@ -121,7 +121,10 @@ following files inside:
 
 **`package/meta/package`**
 ```json
-{"name":"hello_fuchsia","version":0}
+{
+  "name": "hello_fuchsia",
+  "version": "0"
+}
 ```
 
 The `package` file describes our package's name and version number. Every
@@ -232,10 +235,17 @@ ${SDK_PATH}/tools/${ARCH}/ffx product-bundle get workstation_eng.qemu-${ARCH}
 ${SDK_PATH}/tools/${ARCH}/ffx emu start workstation_eng.qemu-${ARCH} --headless
 ```
 
-Then, once the emulator has been started:
+Once the emulator is running, start a package repository server to serve our
+package to the emulator:
 
 ```sh
-${SDK_PATH}/tools/${ARCH}/ffx target repository register
+${SDK_PATH}/tools/${ARCH}/ffx repository server start
+```
+
+Once the repository server is up and running, register our repository:
+
+```sh
+${SDK_PATH}/tools/${ARCH}/ffx target repository register --repository hello-fuchsia
 ```
 
 And watch the logs from the emulator in a separate terminal:
@@ -253,6 +263,10 @@ ${SDK_PATH}/tools/${ARCH}/ffx component run fuchsia-pkg://hello-fuchsia/hello_fu
 On reruns of the component, the `--recreate` argument may also need to be
 passed.
 
+```sh
+${SDK_PATH}/tools/${ARCH}/ffx component run --recreate fuchsia-pkg://hello-fuchsia/hello_fuchsia#meta/hello_fuchsia.cm
+```
+
 ## Testing
 
 ### Running unit tests
diff --git a/src/librustdoc/Cargo.toml b/src/librustdoc/Cargo.toml
index ddaa7438e17..cbdfea89efb 100644
--- a/src/librustdoc/Cargo.toml
+++ b/src/librustdoc/Cargo.toml
@@ -11,7 +11,7 @@ arrayvec = { version = "0.7", default-features = false }
 askama = { version = "0.11", default-features = false, features = ["config"] }
 atty = "0.2"
 pulldown-cmark = { version = "0.9.2", default-features = false }
-minifier = "0.2.1"
+minifier = "0.2.2"
 serde = { version = "1.0", features = ["derive"] }
 serde_json = "1.0"
 smallvec = "1.8.1"
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index a94520b1219..5441a7bd29e 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -551,13 +551,15 @@ where
                 }
                 WherePredicate::EqPredicate { lhs, rhs } => {
                     match lhs {
-                        Type::QPath { ref assoc, ref self_type, ref trait_, .. } => {
+                        Type::QPath(box QPathData {
+                            ref assoc, ref self_type, ref trait_, ..
+                        }) => {
                             let ty = &*self_type;
                             let mut new_trait = trait_.clone();
 
                             if self.is_fn_trait(trait_) && assoc.name == sym::Output {
                                 ty_to_fn
-                                    .entry(*ty.clone())
+                                    .entry(ty.clone())
                                     .and_modify(|e| {
                                         *e = (e.0.clone(), Some(rhs.ty().unwrap().clone()))
                                     })
@@ -582,7 +584,7 @@ where
                                 // to 'T: Iterator<Item=u8>'
                                 GenericArgs::AngleBracketed { ref mut bindings, .. } => {
                                     bindings.push(TypeBinding {
-                                        assoc: *assoc.clone(),
+                                        assoc: assoc.clone(),
                                         kind: TypeBindingKind::Equality { term: rhs },
                                     });
                                 }
@@ -596,7 +598,7 @@ where
                                 }
                             }
 
-                            let bounds = ty_to_bounds.entry(*ty.clone()).or_default();
+                            let bounds = ty_to_bounds.entry(ty.clone()).or_default();
 
                             bounds.insert(GenericBound::TraitBound(
                                 PolyTrait { trait_: new_trait, generic_params: Vec::new() },
@@ -613,7 +615,7 @@ where
                             ));
                             // Avoid creating any new duplicate bounds later in the outer
                             // loop
-                            ty_to_traits.entry(*ty.clone()).or_default().insert(trait_.clone());
+                            ty_to_traits.entry(ty.clone()).or_default().insert(trait_.clone());
                         }
                         _ => panic!("Unexpected LHS {:?} for {:?}", lhs, item_def_id),
                     }
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index e56a715e857..a7048e788b6 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -62,7 +62,7 @@ pub(crate) fn try_inline(
         Res::Def(DefKind::Trait, did) => {
             record_extern_fqn(cx, did, ItemType::Trait);
             build_impls(cx, Some(parent_module), did, attrs, &mut ret);
-            clean::TraitItem(build_external_trait(cx, did))
+            clean::TraitItem(Box::new(build_external_trait(cx, did)))
         }
         Res::Def(DefKind::Fn, did) => {
             record_extern_fqn(cx, did, ItemType::Function);
@@ -672,7 +672,7 @@ fn filter_non_trait_generics(trait_did: DefId, mut g: clean::Generics) -> clean:
 
     g.where_predicates.retain(|pred| match pred {
         clean::WherePredicate::BoundPredicate {
-            ty: clean::QPath { self_type: box clean::Generic(ref s), trait_, .. },
+            ty: clean::QPath(box clean::QPathData { self_type: clean::Generic(ref s), trait_, .. }),
             bounds,
             ..
         } => !(bounds.is_empty() || *s == kw::SelfUpper && trait_.def_id() == trait_did),
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 971617a8400..5507ffb871b 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -410,12 +410,12 @@ fn clean_projection<'tcx>(
         self_type.def_id(&cx.cache)
     };
     let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
-    Type::QPath {
-        assoc: Box::new(projection_to_path_segment(ty, cx)),
+    Type::QPath(Box::new(QPathData {
+        assoc: projection_to_path_segment(ty, cx),
         should_show_cast,
-        self_type: Box::new(self_type),
+        self_type,
         trait_,
-    }
+    }))
 }
 
 fn compute_should_show_cast(self_def_id: Option<DefId>, trait_: &Path, self_type: &Type) -> bool {
@@ -1182,7 +1182,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                     .where_predicates
                     .drain_filter(|pred| match *pred {
                         WherePredicate::BoundPredicate {
-                            ty: QPath { ref assoc, ref self_type, ref trait_, .. },
+                            ty: QPath(box QPathData { ref assoc, ref self_type, ref trait_, .. }),
                             ..
                         } => {
                             if assoc.name != my_name {
@@ -1191,7 +1191,7 @@ pub(crate) fn clean_middle_assoc_item<'tcx>(
                             if trait_.def_id() != assoc_item.container_id(tcx) {
                                 return false;
                             }
-                            match **self_type {
+                            match *self_type {
                                 Generic(ref s) if *s == kw::SelfUpper => {}
                                 _ => return false,
                             }
@@ -1324,15 +1324,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             let self_def_id = DefId::local(qself.hir_id.owner.local_def_index);
             let self_type = clean_ty(qself, cx);
             let should_show_cast = compute_should_show_cast(Some(self_def_id), &trait_, &self_type);
-            Type::QPath {
-                assoc: Box::new(clean_path_segment(
-                    p.segments.last().expect("segments were empty"),
-                    cx,
-                )),
+            Type::QPath(Box::new(QPathData {
+                assoc: clean_path_segment(p.segments.last().expect("segments were empty"), cx),
                 should_show_cast,
-                self_type: Box::new(self_type),
+                self_type,
                 trait_,
-            }
+            }))
         }
         hir::QPath::TypeRelative(qself, segment) => {
             let ty = hir_ty_to_ty(cx.tcx, hir_ty);
@@ -1347,12 +1344,12 @@ fn clean_qpath<'tcx>(hir_ty: &hir::Ty<'tcx>, cx: &mut DocContext<'tcx>) -> Type
             let self_def_id = res.opt_def_id();
             let self_type = clean_ty(qself, cx);
             let should_show_cast = compute_should_show_cast(self_def_id, &trait_, &self_type);
-            Type::QPath {
-                assoc: Box::new(clean_path_segment(segment, cx)),
+            Type::QPath(Box::new(QPathData {
+                assoc: clean_path_segment(segment, cx),
                 should_show_cast,
-                self_type: Box::new(self_type),
+                self_type,
                 trait_,
-            }
+            }))
         }
         hir::QPath::LangItem(..) => bug!("clean: requiring documentation of lang item"),
     }
@@ -1954,12 +1951,12 @@ fn clean_maybe_renamed_item<'tcx>(
                     .map(|ti| clean_trait_item(cx.tcx.hir().trait_item(ti.id), cx))
                     .collect();
 
-                TraitItem(Trait {
+                TraitItem(Box::new(Trait {
                     def_id,
                     items,
                     generics: clean_generics(generics, cx),
                     bounds: bounds.iter().filter_map(|x| clean_generic_bound(x, cx)).collect(),
-                })
+                }))
             }
             ItemKind::ExternCrate(orig_name) => {
                 return clean_extern_crate(item, name, orig_name, cx);
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 1a4786c9b06..4c39021903c 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -727,7 +727,7 @@ pub(crate) enum ItemKind {
     OpaqueTyItem(OpaqueTy),
     StaticItem(Static),
     ConstantItem(Constant),
-    TraitItem(Trait),
+    TraitItem(Box<Trait>),
     TraitAliasItem(TraitAlias),
     ImplItem(Box<Impl>),
     /// A required method in a trait declaration meaning it's only a function signature.
@@ -820,8 +820,6 @@ pub(crate) trait AttributesExt {
 
     fn inner_docs(&self) -> bool;
 
-    fn other_attrs(&self) -> Vec<ast::Attribute>;
-
     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>>;
 }
 
@@ -848,10 +846,6 @@ impl AttributesExt for [ast::Attribute] {
         self.iter().find(|a| a.doc_str().is_some()).map_or(true, |a| a.style == AttrStyle::Inner)
     }
 
-    fn other_attrs(&self) -> Vec<ast::Attribute> {
-        self.iter().filter(|attr| attr.doc_str().is_none()).cloned().collect()
-    }
-
     fn cfg(&self, tcx: TyCtxt<'_>, hidden_cfg: &FxHashSet<Cfg>) -> Option<Arc<Cfg>> {
         let sess = tcx.sess;
         let doc_cfg_active = tcx.features().doc_cfg;
@@ -1136,7 +1130,7 @@ pub struct RenderedLink {
 #[derive(Clone, Debug, Default)]
 pub(crate) struct Attributes {
     pub(crate) doc_strings: Vec<DocFragment>,
-    pub(crate) other_attrs: Vec<ast::Attribute>,
+    pub(crate) other_attrs: ast::AttrVec,
 }
 
 impl Attributes {
@@ -1179,7 +1173,7 @@ impl Attributes {
         doc_only: bool,
     ) -> Attributes {
         let mut doc_strings = Vec::new();
-        let mut other_attrs = Vec::new();
+        let mut other_attrs = ast::AttrVec::new();
         for (attr, parent_module) in attrs {
             if let Some((doc_str, comment_kind)) = attr.doc_str_and_comment_kind() {
                 trace!("got doc_str={doc_str:?}");
@@ -1556,13 +1550,7 @@ pub(crate) enum Type {
     BorrowedRef { lifetime: Option<Lifetime>, mutability: Mutability, type_: Box<Type> },
 
     /// A qualified path to an associated item: `<Type as Trait>::Name`
-    QPath {
-        assoc: Box<PathSegment>,
-        self_type: Box<Type>,
-        /// FIXME: compute this field on demand.
-        should_show_cast: bool,
-        trait_: Path,
-    },
+    QPath(Box<QPathData>),
 
     /// A type that is inferred: `_`
     Infer,
@@ -1660,8 +1648,8 @@ impl Type {
     }
 
     pub(crate) fn projection(&self) -> Option<(&Type, DefId, PathSegment)> {
-        if let QPath { self_type, trait_, assoc, .. } = self {
-            Some((self_type, trait_.def_id(), *assoc.clone()))
+        if let QPath(box QPathData { self_type, trait_, assoc, .. }) = self {
+            Some((self_type, trait_.def_id(), assoc.clone()))
         } else {
             None
         }
@@ -1685,7 +1673,7 @@ impl Type {
             Slice(..) => PrimitiveType::Slice,
             Array(..) => PrimitiveType::Array,
             RawPointer(..) => PrimitiveType::RawPointer,
-            QPath { ref self_type, .. } => return self_type.inner_def_id(cache),
+            QPath(box QPathData { ref self_type, .. }) => return self_type.inner_def_id(cache),
             Generic(_) | Infer | ImplTrait(_) => return None,
         };
         cache.and_then(|c| Primitive(t).def_id(c))
@@ -1699,6 +1687,15 @@ impl Type {
     }
 }
 
+#[derive(Clone, PartialEq, Eq, Debug, Hash)]
+pub(crate) struct QPathData {
+    pub assoc: PathSegment,
+    pub self_type: Type,
+    /// FIXME: compute this field on demand.
+    pub should_show_cast: bool,
+    pub trait_: Path,
+}
+
 /// A primitive (aka, builtin) type.
 ///
 /// This represents things like `i32`, `str`, etc.
@@ -2490,11 +2487,11 @@ mod size_asserts {
     // These are in alphabetical order, which is easy to maintain.
     static_assert_size!(Crate, 72); // frequently moved by-value
     static_assert_size!(DocFragment, 32);
-    static_assert_size!(GenericArg, 80);
+    static_assert_size!(GenericArg, 64);
     static_assert_size!(GenericArgs, 32);
     static_assert_size!(GenericParamDef, 56);
     static_assert_size!(Item, 56);
-    static_assert_size!(ItemKind, 112);
+    static_assert_size!(ItemKind, 96);
     static_assert_size!(PathSegment, 40);
-    static_assert_size!(Type, 72);
+    static_assert_size!(Type, 56);
 }
diff --git a/src/librustdoc/formats/cache.rs b/src/librustdoc/formats/cache.rs
index 2b2691e53bb..86392610d2c 100644
--- a/src/librustdoc/formats/cache.rs
+++ b/src/librustdoc/formats/cache.rs
@@ -227,7 +227,7 @@ impl<'a, 'tcx> DocFolder for CacheBuilder<'a, 'tcx> {
         if let clean::TraitItem(ref t) = *item.kind {
             self.cache.traits.entry(item.item_id.expect_def_id()).or_insert_with(|| {
                 clean::TraitWithExtraInfo {
-                    trait_: t.clone(),
+                    trait_: *t.clone(),
                     is_notable: item.attrs.has_doc_flag(sym::notable_trait),
                 }
             });
diff --git a/src/librustdoc/html/format.rs b/src/librustdoc/html/format.rs
index 3dee4d1acc8..b023792e95a 100644
--- a/src/librustdoc/html/format.rs
+++ b/src/librustdoc/html/format.rs
@@ -1079,7 +1079,12 @@ fn fmt_type<'cx>(
                 write!(f, "impl {}", print_generic_bounds(bounds, cx))
             }
         }
-        clean::QPath { ref assoc, ref self_type, ref trait_, should_show_cast } => {
+        clean::QPath(box clean::QPathData {
+            ref assoc,
+            ref self_type,
+            ref trait_,
+            should_show_cast,
+        }) => {
             if f.alternate() {
                 if should_show_cast {
                     write!(f, "<{:#} as {:#}>::", self_type.print(cx), trait_.print(cx))?
diff --git a/src/librustdoc/html/highlight.rs b/src/librustdoc/html/highlight.rs
index 9d8ee52a3fa..4a12d74ddef 100644
--- a/src/librustdoc/html/highlight.rs
+++ b/src/librustdoc/html/highlight.rs
@@ -111,53 +111,6 @@ fn write_header(out: &mut Buffer, class: &str, extra_content: Option<Buffer>) {
     write!(out, "<code>");
 }
 
-/// Write all the pending elements sharing a same (or at mergeable) `Class`.
-///
-/// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged
-/// with the elements' class, then we simply write the elements since the `ExitSpan` event will
-/// close the tag.
-///
-/// Otherwise, if there is only one pending element, we let the `string` function handle both
-/// opening and closing the tag, otherwise we do it into this function.
-fn write_pending_elems(
-    out: &mut Buffer,
-    href_context: &Option<HrefContext<'_, '_, '_>>,
-    pending_elems: &mut Vec<(&str, Option<Class>)>,
-    current_class: &mut Option<Class>,
-    closing_tags: &[(&str, Class)],
-) {
-    if pending_elems.is_empty() {
-        return;
-    }
-    let mut done = false;
-    if let Some((_, parent_class)) = closing_tags.last() {
-        if can_merge(*current_class, Some(*parent_class), "") {
-            for (text, class) in pending_elems.iter() {
-                string(out, Escape(text), *class, &href_context, false);
-            }
-            done = true;
-        }
-    }
-    if !done {
-        // We only want to "open" the tag ourselves if we have more than one pending and if the current
-        // parent tag is not the same as our pending content.
-        let open_tag_ourselves = pending_elems.len() > 1;
-        let close_tag = if open_tag_ourselves {
-            enter_span(out, current_class.unwrap(), &href_context)
-        } else {
-            ""
-        };
-        for (text, class) in pending_elems.iter() {
-            string(out, Escape(text), *class, &href_context, !open_tag_ourselves);
-        }
-        if open_tag_ourselves {
-            exit_span(out, close_tag);
-        }
-    }
-    pending_elems.clear();
-    *current_class = None;
-}
-
 /// Check if two `Class` can be merged together. In the following rules, "unclassified" means `None`
 /// basically (since it's `Option<Class>`). The following rules apply:
 ///
@@ -171,7 +124,88 @@ fn can_merge(class1: Option<Class>, class2: Option<Class>, text: &str) -> bool {
         (Some(c1), Some(c2)) => c1.is_equal_to(c2),
         (Some(Class::Ident(_)), None) | (None, Some(Class::Ident(_))) => true,
         (Some(_), None) | (None, Some(_)) => text.trim().is_empty(),
-        _ => false,
+        (None, None) => true,
+    }
+}
+
+/// This type is used as a conveniency to prevent having to pass all its fields as arguments into
+/// the various functions (which became its methods).
+struct TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    out: &'a mut Buffer,
+    /// It contains the closing tag and the associated `Class`.
+    closing_tags: Vec<(&'static str, Class)>,
+    /// This is used because we don't automatically generate the closing tag on `ExitSpan` in
+    /// case an `EnterSpan` event with the same class follows.
+    pending_exit_span: Option<Class>,
+    /// `current_class` and `pending_elems` are used to group HTML elements with same `class`
+    /// attributes to reduce the DOM size.
+    current_class: Option<Class>,
+    /// We need to keep the `Class` for each element because it could contain a `Span` which is
+    /// used to generate links.
+    pending_elems: Vec<(&'b str, Option<Class>)>,
+    href_context: Option<HrefContext<'c, 'd, 'e>>,
+}
+
+impl<'a, 'b, 'c, 'd, 'e> TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    fn handle_exit_span(&mut self) {
+        // We can't get the last `closing_tags` element using `pop()` because `closing_tags` is
+        // being used in `write_pending_elems`.
+        let class = self.closing_tags.last().expect("ExitSpan without EnterSpan").1;
+        // We flush everything just in case...
+        self.write_pending_elems(Some(class));
+
+        exit_span(self.out, self.closing_tags.pop().expect("ExitSpan without EnterSpan").0);
+        self.pending_exit_span = None;
+    }
+
+    /// Write all the pending elements sharing a same (or at mergeable) `Class`.
+    ///
+    /// If there is a "parent" (if a `EnterSpan` event was encountered) and the parent can be merged
+    /// with the elements' class, then we simply write the elements since the `ExitSpan` event will
+    /// close the tag.
+    ///
+    /// Otherwise, if there is only one pending element, we let the `string` function handle both
+    /// opening and closing the tag, otherwise we do it into this function.
+    ///
+    /// It returns `true` if `current_class` must be set to `None` afterwards.
+    fn write_pending_elems(&mut self, current_class: Option<Class>) -> bool {
+        if self.pending_elems.is_empty() {
+            return false;
+        }
+        if let Some((_, parent_class)) = self.closing_tags.last() &&
+            can_merge(current_class, Some(*parent_class), "")
+        {
+            for (text, class) in self.pending_elems.iter() {
+                string(self.out, Escape(text), *class, &self.href_context, false);
+            }
+        } else {
+            // We only want to "open" the tag ourselves if we have more than one pending and if the
+            // current parent tag is not the same as our pending content.
+            let close_tag = if self.pending_elems.len() > 1 && current_class.is_some() {
+                Some(enter_span(self.out, current_class.unwrap(), &self.href_context))
+            } else {
+                None
+            };
+            for (text, class) in self.pending_elems.iter() {
+                string(self.out, Escape(text), *class, &self.href_context, close_tag.is_none());
+            }
+            if let Some(close_tag) = close_tag {
+                exit_span(self.out, close_tag);
+            }
+        }
+        self.pending_elems.clear();
+        true
+    }
+}
+
+impl<'a, 'b, 'c, 'd, 'e> Drop for TokenHandler<'a, 'b, 'c, 'd, 'e> {
+    /// When leaving, we need to flush all pending data to not have missing content.
+    fn drop(&mut self) {
+        if self.pending_exit_span.is_some() {
+            self.handle_exit_span();
+        } else {
+            self.write_pending_elems(self.current_class);
+        }
     }
 }
 
@@ -194,64 +228,72 @@ fn write_code(
 ) {
     // This replace allows to fix how the code source with DOS backline characters is displayed.
     let src = src.replace("\r\n", "\n");
-    // It contains the closing tag and the associated `Class`.
-    let mut closing_tags: Vec<(&'static str, Class)> = Vec::new();
-    // The following two variables are used to group HTML elements with same `class` attributes
-    // to reduce the DOM size.
-    let mut current_class: Option<Class> = None;
-    // We need to keep the `Class` for each element because it could contain a `Span` which is
-    // used to generate links.
-    let mut pending_elems: Vec<(&str, Option<Class>)> = Vec::new();
+    let mut token_handler = TokenHandler {
+        out,
+        closing_tags: Vec::new(),
+        pending_exit_span: None,
+        current_class: None,
+        pending_elems: Vec::new(),
+        href_context,
+    };
 
     Classifier::new(
         &src,
-        href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
+        token_handler.href_context.as_ref().map(|c| c.file_span).unwrap_or(DUMMY_SP),
         decoration_info,
     )
     .highlight(&mut |highlight| {
         match highlight {
             Highlight::Token { text, class } => {
+                // If we received a `ExitSpan` event and then have a non-compatible `Class`, we
+                // need to close the `<span>`.
+                let need_current_class_update = if let Some(pending) = token_handler.pending_exit_span &&
+                    !can_merge(Some(pending), class, text) {
+                        token_handler.handle_exit_span();
+                        true
                 // If the two `Class` are different, time to flush the current content and start
                 // a new one.
-                if !can_merge(current_class, class, text) {
-                    write_pending_elems(
-                        out,
-                        &href_context,
-                        &mut pending_elems,
-                        &mut current_class,
-                        &closing_tags,
-                    );
-                    current_class = class.map(Class::dummy);
-                } else if current_class.is_none() {
-                    current_class = class.map(Class::dummy);
+                } else if !can_merge(token_handler.current_class, class, text) {
+                    token_handler.write_pending_elems(token_handler.current_class);
+                    true
+                } else {
+                    token_handler.current_class.is_none()
+                };
+
+                if need_current_class_update {
+                    token_handler.current_class = class.map(Class::dummy);
                 }
-                pending_elems.push((text, class));
+                token_handler.pending_elems.push((text, class));
             }
             Highlight::EnterSpan { class } => {
-                // We flush everything just in case...
-                write_pending_elems(
-                    out,
-                    &href_context,
-                    &mut pending_elems,
-                    &mut current_class,
-                    &closing_tags,
-                );
-                closing_tags.push((enter_span(out, class, &href_context), class))
+                let mut should_add = true;
+                if let Some(pending_exit_span) = token_handler.pending_exit_span {
+                    if class.is_equal_to(pending_exit_span) {
+                        should_add = false;
+                    } else {
+                        token_handler.handle_exit_span();
+                    }
+                } else {
+                    // We flush everything just in case...
+                    if token_handler.write_pending_elems(token_handler.current_class) {
+                        token_handler.current_class = None;
+                    }
+                }
+                if should_add {
+                    let closing_tag = enter_span(token_handler.out, class, &token_handler.href_context);
+                    token_handler.closing_tags.push((closing_tag, class));
+                }
+
+                token_handler.current_class = None;
+                token_handler.pending_exit_span = None;
             }
             Highlight::ExitSpan => {
-                // We flush everything just in case...
-                write_pending_elems(
-                    out,
-                    &href_context,
-                    &mut pending_elems,
-                    &mut current_class,
-                    &closing_tags,
-                );
-                exit_span(out, closing_tags.pop().expect("ExitSpan without EnterSpan").0)
+                token_handler.current_class = None;
+                token_handler.pending_exit_span =
+                    Some(token_handler.closing_tags.last().as_ref().expect("ExitSpan without EnterSpan").1);
             }
         };
     });
-    write_pending_elems(out, &href_context, &mut pending_elems, &mut current_class, &closing_tags);
 }
 
 fn write_footer(out: &mut Buffer, playground_button: Option<&str>) {
@@ -291,8 +333,8 @@ impl Class {
         match (self, other) {
             (Self::Self_(_), Self::Self_(_))
             | (Self::Macro(_), Self::Macro(_))
-            | (Self::Ident(_), Self::Ident(_))
-            | (Self::Decoration(_), Self::Decoration(_)) => true,
+            | (Self::Ident(_), Self::Ident(_)) => true,
+            (Self::Decoration(c1), Self::Decoration(c2)) => c1 == c2,
             (x, y) => x == y,
         }
     }
@@ -761,7 +803,7 @@ impl<'a> Classifier<'a> {
             TokenKind::CloseBracket => {
                 if self.in_attribute {
                     self.in_attribute = false;
-                    sink(Highlight::Token { text: "]", class: Some(Class::Attribute) });
+                    sink(Highlight::Token { text: "]", class: None });
                     sink(Highlight::ExitSpan);
                     return;
                 }
diff --git a/src/librustdoc/html/highlight/fixtures/decorations.html b/src/librustdoc/html/highlight/fixtures/decorations.html
index 21848978721..ebf29f9cb3a 100644
--- a/src/librustdoc/html/highlight/fixtures/decorations.html
+++ b/src/librustdoc/html/highlight/fixtures/decorations.html
@@ -1,2 +1,4 @@
-<span class="example"><span class="kw">let </span>x = <span class="number">1</span>;</span>
-<span class="kw">let </span>y = <span class="number">2</span>;
\ No newline at end of file
+<span class="example"><span class="kw">let </span>x = <span class="number">1</span>;
+<span class="kw">let </span>y = <span class="number">2</span>;
+</span><span class="example2"><span class="kw">let </span>z = <span class="number">3</span>;
+</span><span class="kw">let </span>a = <span class="number">4</span>;
\ No newline at end of file
diff --git a/src/librustdoc/html/highlight/fixtures/sample.html b/src/librustdoc/html/highlight/fixtures/sample.html
index ae2650528eb..4a5a3cf609c 100644
--- a/src/librustdoc/html/highlight/fixtures/sample.html
+++ b/src/librustdoc/html/highlight/fixtures/sample.html
@@ -8,12 +8,13 @@
 .lifetime { color: #B76514; }
 .question-mark { color: #ff9011; }
 </style>
-<pre><code><span class="attribute">#![crate_type = <span class="string">&quot;lib&quot;</span>]</span>
+<pre><code><span class="attribute">#![crate_type = <span class="string">&quot;lib&quot;</span>]
 
-<span class="kw">use </span>std::path::{Path, PathBuf};
+</span><span class="kw">use </span>std::path::{Path, PathBuf};
 
-<span class="attribute">#[cfg(target_os = <span class="string">&quot;linux&quot;</span>)]</span>
-<span class="kw">fn </span>main() -&gt; () {
+<span class="attribute">#[cfg(target_os = <span class="string">&quot;linux&quot;</span>)]
+#[cfg(target_os = <span class="string">&quot;windows&quot;</span>)]
+</span><span class="kw">fn </span>main() -&gt; () {
     <span class="kw">let </span>foo = <span class="bool-val">true </span>&amp;&amp; <span class="bool-val">false </span>|| <span class="bool-val">true</span>;
     <span class="kw">let _</span>: <span class="kw-2">*const </span>() = <span class="number">0</span>;
     <span class="kw">let _ </span>= <span class="kw-2">&amp;</span>foo;
@@ -22,8 +23,8 @@
     <span class="macro">mac!</span>(foo, <span class="kw-2">&amp;mut </span>bar);
     <span class="macro">assert!</span>(<span class="self">self</span>.length &lt; N &amp;&amp; index &lt;= <span class="self">self</span>.length);
     ::std::env::var(<span class="string">&quot;gateau&quot;</span>).is_ok();
-    <span class="attribute">#[rustfmt::skip]</span>
-    <span class="kw">let </span>s:std::path::PathBuf = std::path::PathBuf::new();
+    <span class="attribute">#[rustfmt::skip]
+    </span><span class="kw">let </span>s:std::path::PathBuf = std::path::PathBuf::new();
     <span class="kw">let </span><span class="kw-2">mut </span>s = String::new();
 
     <span class="kw">match </span><span class="kw-2">&amp;</span>s {
@@ -31,7 +32,7 @@
     }
 }
 
-<span class="macro">macro_rules!</span> bar {
+<span class="macro">macro_rules! </span>bar {
     (<span class="macro-nonterminal">$foo</span>:tt) =&gt; {};
 }
 </code></pre>
diff --git a/src/librustdoc/html/highlight/fixtures/sample.rs b/src/librustdoc/html/highlight/fixtures/sample.rs
index fbfdc676733..ef85b566cb3 100644
--- a/src/librustdoc/html/highlight/fixtures/sample.rs
+++ b/src/librustdoc/html/highlight/fixtures/sample.rs
@@ -3,6 +3,7 @@
 use std::path::{Path, PathBuf};
 
 #[cfg(target_os = "linux")]
+#[cfg(target_os = "windows")]
 fn main() -> () {
     let foo = true && false || true;
     let _: *const () = 0;
diff --git a/src/librustdoc/html/highlight/tests.rs b/src/librustdoc/html/highlight/tests.rs
index 4861a8ad32d..a5e633df434 100644
--- a/src/librustdoc/html/highlight/tests.rs
+++ b/src/librustdoc/html/highlight/tests.rs
@@ -69,9 +69,12 @@ fn test_union_highlighting() {
 fn test_decorations() {
     create_default_session_globals_then(|| {
         let src = "let x = 1;
-let y = 2;";
+let y = 2;
+let z = 3;
+let a = 4;";
         let mut decorations = FxHashMap::default();
-        decorations.insert("example", vec![(0, 10)]);
+        decorations.insert("example", vec![(0, 10), (11, 21)]);
+        decorations.insert("example2", vec![(22, 32)]);
 
         let mut html = Buffer::new();
         write_code(&mut html, src, None, Some(DecorationInfo(decorations)));
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 5ed5299e09b..f9d6b4619cc 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -569,7 +569,10 @@ fn short_item_info(
             message.push_str(&format!(": {}", html.into_string()));
         }
         extra_info.push(format!(
-            "<div class=\"stab deprecated\"><span class=\"emoji\">👎</span> {}</div>",
+            "<div class=\"stab deprecated\">\
+                 <span class=\"emoji\">👎</span>\
+                 <span>{}</span>\
+             </div>",
             message,
         ));
     }
@@ -582,8 +585,9 @@ fn short_item_info(
         .filter(|stab| stab.feature != sym::rustc_private)
         .map(|stab| (stab.level, stab.feature))
     {
-        let mut message =
-            "<span class=\"emoji\">🔬</span> This is a nightly-only experimental API.".to_owned();
+        let mut message = "<span class=\"emoji\">🔬</span>\
+             <span>This is a nightly-only experimental API."
+            .to_owned();
 
         let mut feature = format!("<code>{}</code>", Escape(feature.as_str()));
         if let (Some(url), Some(issue)) = (&cx.shared.issue_tracker_base_url, issue) {
@@ -594,7 +598,7 @@ fn short_item_info(
             ));
         }
 
-        message.push_str(&format!(" ({})", feature));
+        message.push_str(&format!(" ({})</span>", feature));
 
         extra_info.push(format!("<div class=\"stab unstable\">{}</div>", message));
     }
@@ -1985,7 +1989,7 @@ fn sidebar_assoc_items(cx: &Context<'_>, out: &mut Buffer, it: &clean::Item) {
             {
                 let mut derefs = FxHashSet::default();
                 derefs.insert(did);
-                sidebar_deref_methods(cx, out, impl_, v, &mut derefs);
+                sidebar_deref_methods(cx, out, impl_, v, &mut derefs, &mut used_links);
             }
 
             let format_impls = |impls: Vec<&Impl>, id_map: &mut IdMap| {
@@ -2057,6 +2061,7 @@ fn sidebar_deref_methods(
     impl_: &Impl,
     v: &[Impl],
     derefs: &mut FxHashSet<DefId>,
+    used_links: &mut FxHashSet<String>,
 ) {
     let c = cx.cache();
 
@@ -2089,13 +2094,10 @@ fn sidebar_deref_methods(
             .and_then(|did| c.impls.get(&did));
         if let Some(impls) = inner_impl {
             debug!("found inner_impl: {:?}", impls);
-            let mut used_links = FxHashSet::default();
             let mut ret = impls
                 .iter()
                 .filter(|i| i.inner_impl().trait_.is_none())
-                .flat_map(|i| {
-                    get_methods(i.inner_impl(), true, &mut used_links, deref_mut, cx.tcx())
-                })
+                .flat_map(|i| get_methods(i.inner_impl(), true, used_links, deref_mut, cx.tcx()))
                 .collect::<Vec<_>>();
             if !ret.is_empty() {
                 let id = if let Some(target_def_id) = real_target.def_id(c) {
@@ -2124,7 +2126,14 @@ fn sidebar_deref_methods(
                         .map(|t| Some(t.def_id()) == cx.tcx().lang_items().deref_trait())
                         .unwrap_or(false)
                 }) {
-                    sidebar_deref_methods(cx, out, target_deref_impl, target_impls, derefs);
+                    sidebar_deref_methods(
+                        cx,
+                        out,
+                        target_deref_impl,
+                        target_impls,
+                        derefs,
+                        used_links,
+                    );
                 }
             }
         }
@@ -2623,8 +2632,8 @@ fn collect_paths_for_type(first_ty: clean::Type, cache: &Cache) -> Vec<String> {
             clean::Type::BorrowedRef { type_, .. } => {
                 work.push_back(*type_);
             }
-            clean::Type::QPath { self_type, trait_, .. } => {
-                work.push_back(*self_type);
+            clean::Type::QPath(box clean::QPathData { self_type, trait_, .. }) => {
+                work.push_back(self_type);
                 process_path(trait_.def_id());
             }
             _ => {}
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index 710ca3ee7c7..b1fa5e7d86d 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -693,8 +693,13 @@ h2.location a {
 	flex-grow: 1;
 	margin: 0px;
 	padding: 0px;
+	/* We use overflow-wrap: break-word for Safari, which doesn't recognize
+	   `anywhere`: https://developer.mozilla.org/en-US/docs/Web/CSS/overflow-wrap */
 	overflow-wrap: break-word;
+	/* Then override it with `anywhere`, which is required to make non-Safari browsers break
+	   more aggressively when we want them to. */
 	overflow-wrap: anywhere;
+	background-color: var(--main-background-color);
 }
 
 .in-band > code, .in-band > .code-header {
@@ -731,13 +736,13 @@ pre, .rustdoc.source .example-wrap {
 
 .docblock table td {
 	padding: .5em;
-	border: 1px dashed;
+	border: 1px dashed var(--border-color);
 }
 
 .docblock table th {
 	padding: .5em;
 	text-align: left;
-	border: 1px solid;
+	border: 1px solid var(--border-color);
 }
 
 .fields + table {
@@ -835,20 +840,6 @@ nav.sub {
 .source nav.sub {
 	margin-left: 32px;
 }
-nav.main {
-	padding: 20px 0;
-	text-align: center;
-}
-nav.main .current {
-	border-top: 1px solid;
-	border-bottom: 1px solid;
-}
-nav.main .separator {
-	border: 1px solid;
-	display: inline-block;
-	height: 23px;
-	margin: 0 20px;
-}
 nav.sum { text-align: right; }
 nav.sub form { display: inline; }
 
@@ -974,7 +965,7 @@ table,
 	max-width: 100%;
 	/* contents can overflow because of max-width limit, then show ellipsis */
 	text-overflow: ellipsis;
-	border: 1px solid;
+	border: 1px solid var(--border-color);
 	border-radius: 4px;
 	outline: none;
 	cursor: pointer;
@@ -1027,11 +1018,12 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	-moz-box-sizing: border-box !important;
 	box-sizing: border-box !important;
 	outline: none;
-	border: 1px solid;
+	border: 1px solid var(--border-color);
 	border-radius: 2px;
 	padding: 8px;
 	font-size: 1rem;
 	width: 100%;
+	background-color: var(--button-background-color);
 }
 
 .search-results {
@@ -1087,7 +1079,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	display: block;
 	margin-top: 7px;
 	border-radius: 3px;
-	border: 1px solid;
+	border: 1px solid var(--border-color);
 	font-size: 1rem;
 }
 
@@ -1096,7 +1088,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	content: '';
 	position: absolute;
 	right: 11px;
-	border: solid;
+	border: solid var(--border-color);
 	border-width: 1px 1px 0 0;
 	display: inline-block;
 	padding: 4px;
@@ -1132,13 +1124,13 @@ so that we can apply CSS-filters to change the arrow color in themes */
 	text-align: center;
 	display: block;
 	margin: 10px 0;
-	border-bottom: 1px solid;
+	border-bottom: 1px solid var(--border-color);
 	padding-bottom: 4px;
 	margin-bottom: 6px;
 }
 #help-button span.bottom {
 	clear: both;
-	border-top: 1px solid;
+	border-top: 1px solid var(--border-color);
 }
 .side-by-side {
 	text-align: initial;
@@ -1172,6 +1164,7 @@ so that we can apply CSS-filters to change the arrow color in themes */
 
 .stab .emoji {
 	font-size: 1.25rem;
+	margin-right: 0.3rem;
 }
 
 /* Black one-pixel outline around emoji shapes */
@@ -1331,6 +1324,7 @@ h3.variant {
 	border-radius: 6px;
 	margin-left: 5px;
 	font-size: 1rem;
+	border: 1px solid var(--border-color);
 }
 
 .tooltip.ignore::after {
@@ -1496,7 +1490,7 @@ pre.rust {
 #source-sidebar > .title {
 	font-size: 1.5rem;
 	text-align: center;
-	border-bottom: 1px solid;
+	border-bottom: 1px solid var(--border-color);
 	margin-bottom: 6px;
 }
 #sidebar-toggle > button {
@@ -1524,11 +1518,12 @@ pre.rust {
 
 #copy-path {
 	height: 34px;
+	background-color: var(--main-background-color);
 }
 #settings-menu > a, #help-button > button, #copy-path {
 	padding: 5px;
 	width: 33px;
-	border: 1px solid;
+	border: 1px solid var(--border-color);
 	border-radius: 2px;
 	cursor: pointer;
 }
@@ -1539,6 +1534,7 @@ pre.rust {
 	padding: 5px;
 	height: 100%;
 	display: block;
+	background-color: var(--button-background-color);
 }
 
 @keyframes rotating {
@@ -1588,37 +1584,13 @@ input:checked + .slider {
 	border: 0;
 }
 
-#theme-choices {
-	display: none;
-	position: absolute;
-	left: 0;
-	top: 28px;
-	border: 1px solid;
-	border-radius: 3px;
-	z-index: 1;
-	cursor: pointer;
-}
-
-#theme-choices > button {
-	border: none;
-	width: 100%;
-	padding: 4px 8px;
-	text-align: center;
-	background: rgba(0,0,0,0);
-	overflow-wrap: normal;
-}
-
-#theme-choices > button:not(:first-child) {
-	border-top: 1px solid;
-}
-
 kbd {
 	display: inline-block;
 	padding: 3px 5px;
 	font: 15px monospace;
 	line-height: 10px;
 	vertical-align: middle;
-	border: solid 1px;
+	border: solid 1px var(--border-color);
 	border-radius: 3px;
 	cursor: default;
 }
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index 4dfb64abbeb..e7ccd402dd0 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -14,6 +14,8 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--scrollbar-thumb-background-color: #5c6773;
 	--scrollbar-color: #5c6773 #24292f;
 	--headings-border-bottom-color: #5c6773;
+	--border-color: #5c6773;
+	--button-background-color: #141920;
 }
 
 .slider {
@@ -36,10 +38,6 @@ h4 {
 	border: none;
 }
 
-.in-band {
-	background-color: #0f1419;
-}
-
 .docblock code {
 	color: #ffb454;
 }
@@ -84,10 +82,6 @@ pre, .rustdoc.source .example-wrap {
 	border-right: 1px solid #ffb44c;
 }
 
-.docblock table td, .docblock table th {
-	border-color: #5c6773;
-}
-
 .search-results a:hover {
 	background-color: #777;
 }
@@ -151,13 +145,6 @@ pre, .rustdoc.source .example-wrap {
 pre.rust .comment { color: #788797; }
 pre.rust .doccomment { color: #a1ac88; }
 
-nav.main .current {
-	border-top-color: #5c6773;
-	border-bottom-color: #5c6773;
-}
-nav.main .separator {
-	border: 1px solid #5c6773;
-}
 a {
 	color: #39AFD7;
 }
@@ -182,17 +169,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(100%);
 }
 
-.search-input {
-	background-color: #141920;
-	border-color: #424c57;
-}
-
-#crate-search {
-	/* Without the `!important`, the border-color is ignored for `<select>`...
-	   It cannot be in the group above because `.search-input` has a different border color on
-	   hover. */
-	border-color: #5c6773 !important;
-}
 #crate-search-div::after {
 	/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
 	filter: invert(41%) sepia(12%) saturate(487%) hue-rotate(171deg) brightness(94%) contrast(94%);
@@ -205,7 +181,7 @@ details.rustdoc-toggle > summary::before {
 }
 
 .search-input {
-	color: #ffffff;
+	color: #fff;
 }
 
 .module-item .stab,
@@ -333,7 +309,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 .tooltip::after {
 	background-color: #314559;
 	color: #c5c5c5;
-	border: 1px solid #5c6773;
 }
 
 .tooltip::before {
@@ -342,11 +317,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 
 .notable-traits-tooltiptext {
 	background-color: #314559;
-	border-color: #5c6773;
-}
-
-.notable-traits-tooltiptext .notable {
-	border-bottom-color: #5c6773;
 }
 
 #titles > button.selected {
@@ -449,23 +419,13 @@ a.result-keyword:focus {}
 .sidebar a.current.tymethod {}
 .sidebar a.current.keyword {}
 
-@media (max-width: 700px) {
-	.sidebar-elems {
-		border-right-color: #5c6773;
-	}
-}
-
 kbd {
 	color: #c5c5c5;
 	background-color: #314559;
-	border-color: #5c6773;
-	border-bottom-color: #5c6773;
 	box-shadow: inset 0 -1px 0 #5c6773;
 }
 
 #settings-menu > a, #help-button > button {
-	border-color: #5c6773;
-	background-color: #0f1419;
 	color: #fff;
 }
 
@@ -473,11 +433,6 @@ kbd {
 	filter: invert(100);
 }
 
-.popover, .popover::before,
-#help-button span.top, #help-button span.bottom {
-	border-color: #5c6773;
-}
-
 #copy-path {
 	color: #fff;
 }
@@ -493,19 +448,6 @@ kbd {
 	border-color: #e0e0e0;
 }
 
-#theme-choices {
-	border-color: #5c6773;
-	background-color: #0f1419;
-}
-
-#theme-choices > button:not(:first-child) {
-	border-top-color: #5c6773;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-	background-color: rgba(110, 110, 110, 0.33);
-}
-
 .search-results .result-name span.alias {
 	color: #c5c5c5;
 }
@@ -515,7 +457,6 @@ kbd {
 
 #source-sidebar > .title {
 	color: #fff;
-	border-bottom-color: #5c6773;
 }
 #source-sidebar div.files > a:hover, details.dir-entry summary:hover,
 #source-sidebar div.files > a:focus, details.dir-entry summary:focus {
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 39f83c99808..1fcda22b6f4 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -9,6 +9,8 @@
 	--scrollbar-thumb-background-color: rgba(32, 34, 37, .6);
 	--scrollbar-color: rgba(32,34,37,.6) #5a5a5a;
 	--headings-border-bottom-color: #d2d2d2;
+	--border-color: #e0e0e0;
+	--button-background-color: #f0f0f0;
 }
 
 .slider {
@@ -21,10 +23,6 @@ input:focus + .slider {
 	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
 }
 
-.in-band {
-	background-color: #353535;
-}
-
 .rust-logo {
 	filter: drop-shadow(1px 0 0px #fff)
 		drop-shadow(0 1px 0 #fff)
@@ -42,10 +40,6 @@ input:focus + .slider {
 	background-color: #0a042f !important;
 }
 
-.docblock table td, .docblock table th {
-	border-color: #ddd;
-}
-
 .search-results a:hover {
 	background-color: #777;
 }
@@ -127,14 +121,6 @@ a.result-keyword:focus { background-color: #884719; }
 pre.rust .comment { color: #8d8d8b; }
 pre.rust .doccomment { color: #8ca375; }
 
-nav.main .current {
-	border-top-color: #eee;
-	border-bottom-color: #eee;
-}
-nav.main .separator {
-	border-color: #eee;
-}
-
 a {
 	color: #D2991D;
 }
@@ -154,16 +140,9 @@ details.rustdoc-toggle > summary::before {
 
 .search-input {
 	color: #111;
-	background-color: #f0f0f0;
 	border-color: #f0f0f0;
 }
 
-#crate-search {
-	/* Without the `!important`, the border-color is ignored for `<select>`...
-	   It cannot be in the group above because `.search-input` has a different border color on
-	   hover. */
-	border-color: #d2d2d2 !important;
-}
 #crate-search-div::after {
 	/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
 	filter: invert(94%) sepia(0%) saturate(721%) hue-rotate(255deg) brightness(90%) contrast(90%);
@@ -175,10 +154,6 @@ details.rustdoc-toggle > summary::before {
 	filter: invert(69%) sepia(60%) saturate(6613%) hue-rotate(184deg) brightness(100%) contrast(91%);
 }
 
-.search-input {
-	border-color: #e0e0e0;
-}
-
 .search-input:focus {
 	border-color: #008dfd;
 }
@@ -296,11 +271,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 
 .notable-traits-tooltiptext {
 	background-color: #111;
-	border-color: #777;
-}
-
-.notable-traits-tooltiptext .notable {
-	border-bottom-color: #d2d2d2;
 }
 
 #titles > button:not(.selected) {
@@ -317,23 +287,13 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: #888;
 }
 
-@media (max-width: 700px) {
-	.sidebar-elems {
-		border-right-color: #000;
-	}
-}
-
 kbd {
 	color: #000;
 	background-color: #fafbfc;
-	border-color: #d1d5da;
-	border-bottom-color: #c6cbd1;
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
 #settings-menu > a, #help-button > button {
-	border-color: #e0e0e0;
-	background: #f0f0f0;
 	color: #000;
 }
 
@@ -342,11 +302,6 @@ kbd {
 	border-color: #ffb900;
 }
 
-.popover, .popover::before,
-#help-button span.top, #help-button span.bottom {
-	border-color: #d2d2d2;
-}
-
 #copy-path {
 	color: #999;
 }
@@ -357,19 +312,6 @@ kbd {
 	filter: invert(65%);
 }
 
-#theme-choices {
-	border-color: #e0e0e0;
-	background-color: #353535;
-}
-
-#theme-choices > button:not(:first-child) {
-	border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-	background-color: #4e4e4e;
-}
-
 .search-results .result-name span.alias {
 	color: #fff;
 }
@@ -377,9 +319,6 @@ kbd {
 	color: #ccc;
 }
 
-#source-sidebar > .title {
-	border-bottom-color: #ccc;
-}
 #source-sidebar div.files > a:hover, details.dir-entry summary:hover,
 #source-sidebar div.files > a:focus, details.dir-entry summary:focus {
 	background-color: #444;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 5698088c790..7139c199729 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -9,6 +9,8 @@
 	--scrollbar-thumb-background-color: rgba(36, 37, 39, 0.6);
 	--scrollbar-color: rgba(36, 37, 39, 0.6) #d9d9d9;
 	--headings-border-bottom-color: #ddd;
+	--border-color: #e0e0e0;
+	--button-background-color: #fff;
 }
 
 .slider {
@@ -21,10 +23,6 @@ input:focus + .slider {
 	box-shadow: 0 0 0 2px #0a84ff, 0 0 0 6px rgba(10, 132, 255, 0.3);
 }
 
-.in-band {
-	background-color: white;
-}
-
 .rust-logo {
 	/* This rule exists to force other themes to explicitly style the logo.
 	 * Rustdoc has a custom linter for this purpose.
@@ -41,10 +39,6 @@ input:focus + .slider {
 	background-color: #FDFFD3 !important;
 }
 
-.docblock table td, .docblock table th {
-	border-color: #ddd;
-}
-
 .search-results a:hover {
 	background-color: #ddd;
 }
@@ -123,14 +117,6 @@ a.result-keyword:focus { background-color: #afc6e4; }
 .sidebar a.current.tymethod { color: #a67736; }
 .sidebar a.current.keyword { color: #356da4; }
 
-nav.main .current {
-	border-top-color: #000;
-	border-bottom-color: #000;
-}
-nav.main .separator {
-	border: 1px solid #000;
-}
-
 a {
 	color: #3873AD;
 }
@@ -144,16 +130,6 @@ details.rustdoc-toggle > summary::before {
 	color: #999;
 }
 
-.search-input {
-	background-color: white;
-	border-color: #e0e0e0;
-}
-#crate-search {
-	/* Without the `!important`, the border-color is ignored for `<select>`...
-	   It cannot be in the group above because `.search-input` has a different border color on
-	   hover. */
-	border-color: #e0e0e0 !important;
-}
 #crate-search-div::after {
 	/* match border-color; uses https://codepen.io/sosuke/pen/Pjoqqp */
 	filter: invert(100%) sepia(0%) saturate(4223%) hue-rotate(289deg) brightness(114%) contrast(76%);
@@ -279,11 +255,6 @@ pre.ignore:hover, .information:hover + pre.ignore {
 
 .notable-traits-tooltiptext {
 	background-color: #eee;
-	border-color: #999;
-}
-
-.notable-traits-tooltiptext .notable {
-	border-bottom-color: #DDDDDD;
 }
 
 #titles > button:not(.selected) {
@@ -300,35 +271,17 @@ pre.ignore:hover, .information:hover + pre.ignore {
 	color: #888;
 }
 
-@media (max-width: 700px) {
-	.sidebar-elems {
-		border-right-color: #000;
-	}
-}
-
 kbd {
 	color: #000;
 	background-color: #fafbfc;
-	border-color: #d1d5da;
-	border-bottom-color: #c6cbd1;
 	box-shadow: inset 0 -1px 0 #c6cbd1;
 }
 
-#settings-menu > a, #help-button > button {
-	border-color: #e0e0e0;
-	background-color: #fff;
-}
-
 #settings-menu > a:hover, #settings-menu > a:focus,
 #help-button > button:hover, #help-button > button:focus {
 	border-color: #717171;
 }
 
-.popover, .popover::before,
-#help-button span.top, #help-button span.bottom {
-	border-color: #e0e0e0;
-}
-
 #copy-path {
 	color: #999;
 }
@@ -339,19 +292,6 @@ kbd {
 	filter: invert(35%);
 }
 
-#theme-choices {
-	border-color: #ccc;
-	background-color: #fff;
-}
-
-#theme-choices > button:not(:first-child) {
-	border-top-color: #e0e0e0;
-}
-
-#theme-choices > button:hover, #theme-choices > button:focus {
-	background-color: #eee;
-}
-
 .search-results .result-name span.alias {
 	color: #000;
 }
@@ -359,9 +299,6 @@ kbd {
 	color: #999;
 }
 
-#source-sidebar > .title {
-	border-bottom-color: #ccc;
-}
 #source-sidebar div.files > a:hover, details.dir-entry summary:hover,
 #source-sidebar div.files > a:focus, details.dir-entry summary:focus {
 	background-color: #E0E0E0;
diff --git a/src/librustdoc/json/conversions.rs b/src/librustdoc/json/conversions.rs
index 1fedb0144d1..c4e8b6f5f84 100644
--- a/src/librustdoc/json/conversions.rs
+++ b/src/librustdoc/json/conversions.rs
@@ -248,7 +248,7 @@ fn from_clean_item(item: clean::Item, tcx: TyCtxt<'_>) -> ItemEnum {
         VariantItem(v) => ItemEnum::Variant(v.into_tcx(tcx)),
         FunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
         ForeignFunctionItem(f) => ItemEnum::Function(from_function(f, header.unwrap(), tcx)),
-        TraitItem(t) => ItemEnum::Trait(t.into_tcx(tcx)),
+        TraitItem(t) => ItemEnum::Trait((*t).into_tcx(tcx)),
         TraitAliasItem(t) => ItemEnum::TraitAlias(t.into_tcx(tcx)),
         MethodItem(m, _) => ItemEnum::Method(from_function_method(m, true, header.unwrap(), tcx)),
         TyMethodItem(m) => ItemEnum::Method(from_function_method(m, false, header.unwrap(), tcx)),
@@ -480,10 +480,10 @@ impl FromWithTcx<clean::Type> for Type {
                 mutable: mutability == ast::Mutability::Mut,
                 type_: Box::new((*type_).into_tcx(tcx)),
             },
-            QPath { assoc, self_type, trait_, .. } => Type::QualifiedPath {
+            QPath(box clean::QPathData { assoc, self_type, trait_, .. }) => Type::QualifiedPath {
                 name: assoc.name.to_string(),
                 args: Box::new(assoc.args.clone().into_tcx(tcx)),
-                self_type: Box::new((*self_type).into_tcx(tcx)),
+                self_type: Box::new(self_type.into_tcx(tcx)),
                 trait_: trait_.into_tcx(tcx),
             },
         }
diff --git a/src/test/assembly/x86_64-floating-point-clamp.rs b/src/test/assembly/x86_64-floating-point-clamp.rs
new file mode 100644
index 00000000000..0f3b465d08d
--- /dev/null
+++ b/src/test/assembly/x86_64-floating-point-clamp.rs
@@ -0,0 +1,25 @@
+// Floating-point clamp is designed to be implementable as max+min,
+// so check to make sure that's what it's actually emitting.
+
+// assembly-output: emit-asm
+// compile-flags: --crate-type=lib -O -C llvm-args=-x86-asm-syntax=intel
+// only-x86_64
+
+// CHECK-LABEL: clamp_demo:
+#[no_mangle]
+pub fn clamp_demo(a: f32, x: f32, y: f32) -> f32 {
+    // CHECK: maxss
+    // CHECK: minss
+    a.clamp(x, y)
+}
+
+// CHECK-LABEL: clamp12_demo:
+#[no_mangle]
+pub fn clamp12_demo(a: f32) -> f32 {
+    // CHECK: movss   xmm1
+    // CHECK-NEXT: maxss   xmm1, xmm0
+    // CHECK-NEXT: movss   xmm0
+    // CHECK-NEXT: minss   xmm0, xmm1
+    // CHECK: ret
+    a.clamp(1.0, 2.0)
+}
diff --git a/src/test/codegen/README.md b/src/test/codegen/README.md
index 00de55eeab1..8f2daaafcc7 100644
--- a/src/test/codegen/README.md
+++ b/src/test/codegen/README.md
@@ -1,2 +1,24 @@
 The files here use the LLVM FileCheck framework, documented at
 <https://llvm.org/docs/CommandGuide/FileCheck.html>.
+
+One extension worth noting is the use of revisions as custom prefixes for
+FileCheck. If your codegen test has different behavior based on the chosen
+target or different compiler flags that you want to exercise, you can use a
+revisions annotation, like so:
+
+```rust
+// revisions: aaa bbb
+// [bbb] compile-flags: --flags-for-bbb
+```
+
+After specifying those variations, you can write different expected, or
+explicitly *unexpected* output by using `<prefix>-SAME:` and `<prefix>-NOT:`,
+like so:
+
+```rust
+// CHECK: expected code
+// aaa-SAME: emitted-only-for-aaa
+// aaa-NOT:                        emitted-only-for-bbb
+// bbb-NOT:  emitted-only-for-aaa
+// bbb-SAME:                       emitted-only-for-bbb
+```
diff --git a/src/test/codegen/pic-relocation-model.rs b/src/test/codegen/pic-relocation-model.rs
index 6e1d5a6c3f2..bcfe2f9af50 100644
--- a/src/test/codegen/pic-relocation-model.rs
+++ b/src/test/codegen/pic-relocation-model.rs
@@ -13,4 +13,4 @@ pub fn call_foreign_fn() -> u8 {
 // CHECK: declare zeroext i8 @foreign_fn()
 extern "C" {fn foreign_fn() -> u8;}
 
-// CHECK: !{i32 7, !"PIC Level", i32 2}
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
diff --git a/src/test/codegen/pie-relocation-model.rs b/src/test/codegen/pie-relocation-model.rs
index a843202a94f..ec44edc0667 100644
--- a/src/test/codegen/pie-relocation-model.rs
+++ b/src/test/codegen/pie-relocation-model.rs
@@ -18,5 +18,5 @@ pub fn call_foreign_fn() -> u8 {
 // CHECK: declare zeroext i8 @foreign_fn()
 extern "C" {fn foreign_fn() -> u8;}
 
-// CHECK: !{i32 7, !"PIC Level", i32 2}
+// CHECK: !{i32 {{[78]}}, !"PIC Level", i32 2}
 // CHECK: !{i32 7, !"PIE Level", i32 2}
diff --git a/src/test/codegen/try_question_mark_nop.rs b/src/test/codegen/try_question_mark_nop.rs
new file mode 100644
index 00000000000..d239387768e
--- /dev/null
+++ b/src/test/codegen/try_question_mark_nop.rs
@@ -0,0 +1,54 @@
+// min-llvm-version: 15.0
+// compile-flags: -O -Z merge-functions=disabled --edition=2021
+// only-x86_64
+
+#![crate_type = "lib"]
+#![feature(try_blocks)]
+
+// These are now NOPs in LLVM 15, presumably thanks to nikic's change mentioned in
+// <https://github.com/rust-lang/rust/issues/85133#issuecomment-1072168354>.
+// Unfortunately, as of 2022-08-17 they're not yet nops for `u64`s nor `Option`.
+
+use std::ops::ControlFlow::{self, Continue, Break};
+
+// CHECK-LABEL: @result_nop_match_32
+#[no_mangle]
+pub fn result_nop_match_32(x: Result<i32, u32>) -> Result<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    match x {
+        Ok(x) => Ok(x),
+        Err(x) => Err(x),
+    }
+}
+
+// CHECK-LABEL: @result_nop_traits_32
+#[no_mangle]
+pub fn result_nop_traits_32(x: Result<i32, u32>) -> Result<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    try {
+        x?
+    }
+}
+
+// CHECK-LABEL: @control_flow_nop_match_32
+#[no_mangle]
+pub fn control_flow_nop_match_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    match x {
+        Continue(x) => Continue(x),
+        Break(x) => Break(x),
+    }
+}
+
+// CHECK-LABEL: @control_flow_nop_traits_32
+#[no_mangle]
+pub fn control_flow_nop_traits_32(x: ControlFlow<i32, u32>) -> ControlFlow<i32, u32> {
+    // CHECK: start
+    // CHECK-NEXT: ret i64 %0
+    try {
+        x?
+    }
+}
diff --git a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
index 833d620cc6c..bde2f04fac9 100644
--- a/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
+++ b/src/test/mir-opt/combine_clone_of_primitives.{impl#0}-clone.InstCombine.diff
@@ -4,63 +4,63 @@
   fn <impl at $DIR/combine_clone_of_primitives.rs:6:10: 6:15>::clone(_1: &MyThing<T>) -> MyThing<T> {
       debug self => _1;                    // in scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
       let mut _0: MyThing<T>;              // return place in scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
-      let mut _2: T;                       // in scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-      let mut _3: &T;                      // in scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-      let _4: &T;                          // in scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-      let mut _5: u64;                     // in scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-      let mut _6: &u64;                    // in scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-      let _7: &u64;                        // in scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-      let mut _8: [f32; 3];                // in scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-      let mut _9: &[f32; 3];               // in scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-      let _10: &[f32; 3];                  // in scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
+      let mut _2: T;                       // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+      let mut _3: &T;                      // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+      let _4: &T;                          // in scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+      let mut _5: u64;                     // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+      let mut _6: &u64;                    // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+      let _7: &u64;                        // in scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+      let mut _8: [f32; 3];                // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+      let mut _9: &[f32; 3];               // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+      let _10: &[f32; 3];                  // in scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
   
       bb0: {
-          StorageLive(_2);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-          StorageLive(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-          StorageLive(_4);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-          _4 = &((*_1).0: T);              // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
--         _3 = &(*_4);                     // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-+         _3 = _4;                         // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
-          _2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:5: +2:9
+          StorageLive(_2);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          StorageLive(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          StorageLive(_4);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          _4 = &((*_1).0: T);              // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+-         _3 = &(*_4);                     // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
++         _3 = _4;                         // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
+          _2 = <T as Clone>::clone(move _3) -> bb1; // scope 0 at $DIR/combine_clone_of_primitives.rs:8:5: 8:9
                                            // mir::Constant
                                            // + span: $DIR/combine_clone_of_primitives.rs:8:5: 8:9
                                            // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
       }
   
       bb1: {
-          StorageDead(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+2:8: +2:9
-          StorageLive(_5);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-          StorageLive(_6);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-          StorageLive(_7);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-          _7 = &((*_1).1: u64);            // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
--         _6 = &(*_7);                     // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
--         _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
+          StorageDead(_3);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:8:8: 8:9
+          StorageLive(_5);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          StorageLive(_6);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          StorageLive(_7);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+          _7 = &((*_1).1: u64);            // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+-         _6 = &(*_7);                     // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
+-         _5 = <u64 as Clone>::clone(move _6) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
 -                                          // mir::Constant
 -                                          // + span: $DIR/combine_clone_of_primitives.rs:9:5: 9:11
 -                                          // + literal: Const { ty: for<'r> fn(&'r u64) -> u64 {<u64 as Clone>::clone}, val: Value(<ZST>) }
-+         _6 = _7;                         // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-+         _5 = (*_6);                      // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
-+         goto -> bb2;                     // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:5: +3:11
++         _6 = _7;                         // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
++         _5 = (*_6);                      // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
++         goto -> bb2;                     // scope 0 at $DIR/combine_clone_of_primitives.rs:9:5: 9:11
       }
   
       bb2: {
-          StorageDead(_6);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+3:10: +3:11
-          StorageLive(_8);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-          StorageLive(_9);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-          StorageLive(_10);                // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-          _10 = &((*_1).2: [f32; 3]);      // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
--         _9 = &(*_10);                    // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
--         _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
+          StorageDead(_6);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:9:10: 9:11
+          StorageLive(_8);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          StorageLive(_9);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          StorageLive(_10);                // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+          _10 = &((*_1).2: [f32; 3]);      // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+-         _9 = &(*_10);                    // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
+-         _8 = <[f32; 3] as Clone>::clone(move _9) -> [return: bb3, unwind: bb4]; // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
 -                                          // mir::Constant
 -                                          // + span: $DIR/combine_clone_of_primitives.rs:10:5: 10:16
 -                                          // + literal: Const { ty: for<'r> fn(&'r [f32; 3]) -> [f32; 3] {<[f32; 3] as Clone>::clone}, val: Value(<ZST>) }
-+         _9 = _10;                        // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-+         _8 = (*_9);                      // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
-+         goto -> bb3;                     // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:5: +4:16
++         _9 = _10;                        // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
++         _8 = (*_9);                      // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
++         goto -> bb3;                     // scope 0 at $DIR/combine_clone_of_primitives.rs:10:5: 10:16
       }
   
       bb3: {
-          StorageDead(_9);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:+4:15: +4:16
+          StorageDead(_9);                 // scope 0 at $DIR/combine_clone_of_primitives.rs:10:15: 10:16
           Deinit(_0);                      // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
           (_0.0: T) = move _2;             // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
           (_0.1: u64) = move _5;           // scope 0 at $DIR/combine_clone_of_primitives.rs:+0:10: +0:15
diff --git a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
index f58ba56b943..b5439d9d239 100644
--- a/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.BAR.PromoteTemps.diff
@@ -40,11 +40,11 @@
 -         StorageDead(_5);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44
 -         StorageDead(_3);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44
           StorageDead(_1);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:43: +0:44
-          return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:28
+          return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:44
       }
   
       bb2 (cleanup): {
-          resume;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:28
+          resume;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:44
       }
 - }
 - 
diff --git a/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir b/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir
index deb467977d7..20d73afda27 100644
--- a/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir
+++ b/src/test/mir-opt/const_promotion_extern_static.BOP.mir_map.0.mir
@@ -12,6 +12,6 @@ static BOP: &i32 = {
         _1 = &_2;                        // scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23
         _0 = &(*_1);                     // scope 0 at $DIR/const-promotion-extern-static.rs:+0:20: +0:23
         StorageDead(_1);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:22: +0:23
-        return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:17
+        return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:23
     }
 }
diff --git a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 5300f555fdf..4df4c9636a5 100644
--- a/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/src/test/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -42,11 +42,11 @@
 -         StorageDead(_5);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55
 -         StorageDead(_3);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55
           StorageDead(_1);                 // scope 0 at $DIR/const-promotion-extern-static.rs:+0:54: +0:55
-          return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:28
+          return;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:55
       }
   
       bb2 (cleanup): {
-          resume;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:28
+          resume;                          // scope 0 at $DIR/const-promotion-extern-static.rs:+0:1: +0:55
       }
   }
 - 
diff --git a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
index 836443bf4d2..04378dbf374 100644
--- a/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/aggregate.main.ConstProp.diff
@@ -24,7 +24,7 @@
 +         _1 = const 1_i32;                // scope 0 at $DIR/aggregate.rs:+1:13: +1:28
           StorageDead(_2);                 // scope 0 at $DIR/aggregate.rs:+1:27: +1:28
           StorageDead(_3);                 // scope 0 at $DIR/aggregate.rs:+1:28: +1:29
-          nop;                             // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/aggregate.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/aggregate.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/aggregate.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/aggregate.rs b/src/test/mir-opt/const_prop/aggregate.rs
index 7a3b26a7317..493d0508a04 100644
--- a/src/test/mir-opt/const_prop/aggregate.rs
+++ b/src/test/mir-opt/const_prop/aggregate.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 
 // EMIT_MIR aggregate.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
index bb9abdd1020..439b2a3e16b 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.32bit.diff
@@ -18,11 +18,12 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
           StorageLive(_3);                 // scope 0 at $DIR/array_index.rs:+1:31: +1:32
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:+1:31: +1:32
-          _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
+-         _4 = Len(_2);                    // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
       }
   
       bb1: {
@@ -30,7 +31,7 @@
 +         _1 = const 2_u32;                // scope 0 at $DIR/array_index.rs:+1:18: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
           StorageDead(_2);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
-          nop;                             // scope 0 at $DIR/array_index.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/array_index.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/array_index.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/array_index.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
index bb9abdd1020..439b2a3e16b 100644
--- a/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/array_index.main.ConstProp.64bit.diff
@@ -18,11 +18,12 @@
           _2 = [const 0_u32, const 1_u32, const 2_u32, const 3_u32]; // scope 0 at $DIR/array_index.rs:+1:18: +1:30
           StorageLive(_3);                 // scope 0 at $DIR/array_index.rs:+1:31: +1:32
           _3 = const 2_usize;              // scope 0 at $DIR/array_index.rs:+1:31: +1:32
-          _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
+-         _4 = Len(_2);                    // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         _5 = Lt(_3, _4);                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 -         assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         _4 = const 4_usize;              // scope 0 at $DIR/array_index.rs:+1:18: +1:33
 +         _5 = const true;                 // scope 0 at $DIR/array_index.rs:+1:18: +1:33
-+         assert(const true, "index out of bounds: the length is {} but the index is {}", const 4_usize, const 2_usize) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
++         assert(const true, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> bb1; // scope 0 at $DIR/array_index.rs:+1:18: +1:33
       }
   
       bb1: {
@@ -30,7 +31,7 @@
 +         _1 = const 2_u32;                // scope 0 at $DIR/array_index.rs:+1:18: +1:33
           StorageDead(_3);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
           StorageDead(_2);                 // scope 0 at $DIR/array_index.rs:+1:33: +1:34
-          nop;                             // scope 0 at $DIR/array_index.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/array_index.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/array_index.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/array_index.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/array_index.rs b/src/test/mir-opt/const_prop/array_index.rs
index 2c5254b5deb..d31c2827b4e 100644
--- a/src/test/mir-opt/const_prop/array_index.rs
+++ b/src/test/mir-opt/const_prop/array_index.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR array_index.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
index 45134a3fdff..bea32a67ef4 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.main.ConstProp.diff
@@ -24,10 +24,9 @@
           StorageLive(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 -         _3 = _1;                         // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 -         _4 = Eq(_3, const 0_i32);        // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
--         assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _3 = const 0_i32;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
 +         _4 = const true;                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         assert(!const true, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+          assert(!move _4, "attempt to divide `{}` by zero", const 1_i32) -> bb1; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
       }
   
       bb1: {
@@ -38,14 +37,13 @@
 +         _5 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _6 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
 +         _7 = const false;                // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
++         assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, _3) -> bb2; // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
       }
   
       bb2: {
--         _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
-+         _2 = Div(const 1_i32, const 0_i32); // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
+          _2 = Div(const 1_i32, move _3);  // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:14: +2:19
           StorageDead(_3);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+2:18: +2:19
-          nop;                             // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
+          _0 = const ();                   // scope 0 at $DIR/bad_op_div_by_zero.rs:+0:11: +3:2
           StorageDead(_2);                 // scope 1 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
           StorageDead(_1);                 // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/bad_op_div_by_zero.rs:+3:2: +3:2
diff --git a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
index 6f39209b970..a6fd325ece0 100644
--- a/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
+++ b/src/test/mir-opt/const_prop/bad_op_div_by_zero.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
diff --git a/src/test/mir-opt/const_prop/boolean_identities.rs b/src/test/mir-opt/const_prop/boolean_identities.rs
index 57164e3e794..c7b609949cd 100644
--- a/src/test/mir-opt/const_prop/boolean_identities.rs
+++ b/src/test/mir-opt/const_prop/boolean_identities.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O -Zmir-opt-level=4
 
 // EMIT_MIR boolean_identities.test.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
index 73fdf140498..cb82a7bea14 100644
--- a/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/boxes.main.ConstProp.diff
@@ -24,12 +24,11 @@
           StorageLive(_3);                 // scope 0 at $DIR/boxes.rs:+1:14: +1:22
 -         _4 = SizeOf(i32);                // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 -         _5 = AlignOf(i32);               // scope 2 at $DIR/boxes.rs:+1:14: +1:22
--         _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 +         _4 = const 4_usize;              // scope 2 at $DIR/boxes.rs:+1:14: +1:22
 +         _5 = const 4_usize;              // scope 2 at $DIR/boxes.rs:+1:14: +1:22
-+         _6 = alloc::alloc::exchange_malloc(const 4_usize, const 4_usize) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
+          _6 = alloc::alloc::exchange_malloc(move _4, move _5) -> bb1; // scope 2 at $DIR/boxes.rs:+1:14: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/boxes.rs:12:14: 12:22
+                                           // + span: $DIR/boxes.rs:13:14: 13:22
                                            // + literal: Const { ty: unsafe fn(usize, usize) -> *mut u8 {alloc::alloc::exchange_malloc}, val: Value(<ZST>) }
       }
   
@@ -53,7 +52,7 @@
   
       bb2: {
           StorageDead(_3);                 // scope 0 at $DIR/boxes.rs:+1:26: +1:27
-          nop;                             // scope 0 at $DIR/boxes.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/boxes.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/boxes.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/boxes.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/boxes.rs b/src/test/mir-opt/const_prop/boxes.rs
index fea666a4455..d287830db5a 100644
--- a/src/test/mir-opt/const_prop/boxes.rs
+++ b/src/test/mir-opt/const_prop/boxes.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 // ignore-emscripten compiled with panic=abort by default
 // ignore-wasm32
diff --git a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
index 5698a612fe2..e040a4b3a53 100644
--- a/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/cast.main.ConstProp.diff
@@ -19,7 +19,7 @@
           StorageLive(_2);                 // scope 1 at $DIR/cast.rs:+3:9: +3:10
 -         _2 = const 42_u32 as u8 (Misc);  // scope 1 at $DIR/cast.rs:+3:13: +3:24
 +         _2 = const 42_u8;                // scope 1 at $DIR/cast.rs:+3:13: +3:24
-          nop;                             // scope 0 at $DIR/cast.rs:+0:11: +4:2
+          _0 = const ();                   // scope 0 at $DIR/cast.rs:+0:11: +4:2
           StorageDead(_2);                 // scope 1 at $DIR/cast.rs:+4:1: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/cast.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/cast.rs:+4:2: +4:2
diff --git a/src/test/mir-opt/const_prop/cast.rs b/src/test/mir-opt/const_prop/cast.rs
index 680cab00740..984086eda48 100644
--- a/src/test/mir-opt/const_prop/cast.rs
+++ b/src/test/mir-opt/const_prop/cast.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // EMIT_MIR cast.main.ConstProp.diff
 
 fn main() {
diff --git a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
index 5e33d054207..96d0d25664a 100644
--- a/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/checked_add.main.ConstProp.diff
@@ -20,7 +20,7 @@
       bb1: {
 -         _1 = move (_2.0: u32);           // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
 +         _1 = const 2_u32;                // scope 0 at $DIR/checked_add.rs:+1:18: +1:23
-          nop;                             // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/checked_add.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/checked_add.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/checked_add.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/checked_add.rs b/src/test/mir-opt/const_prop/checked_add.rs
index 08d59b6fbc3..b9860da4c82 100644
--- a/src/test/mir-opt/const_prop/checked_add.rs
+++ b/src/test/mir-opt/const_prop/checked_add.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR checked_add.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
index c21b24591d8..2cb071deab1 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _3 = const FOO;                  // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:7:13: 7:16
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:13: 8:16
                                            // + literal: Const { ty: &i32, val: Unevaluated(FOO, [], None) }
           _2 = &raw const (*_3);           // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:16
           _1 = move _2 as usize (PointerExposeAddress); // scope 0 at $DIR/const_prop_fails_gracefully.rs:+2:13: +2:39
@@ -29,14 +29,14 @@
           _5 = _1;                         // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:10: +3:11
           _4 = read(move _5) -> bb1;       // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:5: +3:12
                                            // mir::Constant
-                                           // + span: $DIR/const_prop_fails_gracefully.rs:8:5: 8:9
+                                           // + span: $DIR/const_prop_fails_gracefully.rs:9:5: 9:9
                                            // + literal: Const { ty: fn(usize) {read}, val: Value(<ZST>) }
       }
   
       bb1: {
           StorageDead(_5);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:11: +3:12
           StorageDead(_4);                 // scope 1 at $DIR/const_prop_fails_gracefully.rs:+3:12: +3:13
-          nop;                             // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
+          _0 = const ();                   // scope 0 at $DIR/const_prop_fails_gracefully.rs:+0:11: +4:2
           StorageDead(_1);                 // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:1: +4:2
           return;                          // scope 0 at $DIR/const_prop_fails_gracefully.rs:+4:2: +4:2
       }
diff --git a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
index 8bd68527f37..0a3dcbd380f 100644
--- a/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ b/src/test/mir-opt/const_prop/const_prop_fails_gracefully.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 #[inline(never)]
 fn read(_: usize) { }
 
diff --git a/src/test/mir-opt/const_prop/control-flow-simplification.rs b/src/test/mir-opt/const_prop/control-flow-simplification.rs
index aa4ce19f620..7dbe8e7344b 100644
--- a/src/test/mir-opt/const_prop/control-flow-simplification.rs
+++ b/src/test/mir-opt/const_prop/control-flow-simplification.rs
@@ -1,10 +1,11 @@
+// unit-test: ConstProp
 // compile-flags: -Zmir-opt-level=1
 
-trait NeedsDrop:Sized{
-    const NEEDS:bool=std::mem::needs_drop::<Self>();
+trait NeedsDrop: Sized {
+    const NEEDS: bool = std::mem::needs_drop::<Self>();
 }
 
-impl<This> NeedsDrop for This{}
+impl<This> NeedsDrop for This {}
 
 // EMIT_MIR control_flow_simplification.hello.ConstProp.diff
 // EMIT_MIR control_flow_simplification.hello.PreCodegen.before.mir
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
index 5b4ecaa80f1..6b29bb59c40 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.32bit.diff
@@ -44,7 +44,7 @@
           _1 = Add(move _2, const 0_i32);  // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
           StorageDead(_2);                 // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
           StorageDead(_3);                 // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
-          nop;                             // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
index 5b4ecaa80f1..6b29bb59c40 100644
--- a/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
+++ b/src/test/mir-opt/const_prop/discriminant.main.ConstProp.64bit.diff
@@ -44,7 +44,7 @@
           _1 = Add(move _2, const 0_i32);  // scope 0 at $DIR/discriminant.rs:+1:13: +1:68
           StorageDead(_2);                 // scope 0 at $DIR/discriminant.rs:+1:67: +1:68
           StorageDead(_3);                 // scope 0 at $DIR/discriminant.rs:+1:68: +1:69
-          nop;                             // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/discriminant.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/discriminant.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/discriminant.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/discriminant.rs b/src/test/mir-opt/const_prop/discriminant.rs
index 67538b3c7a5..fdd67ca8ac4 100644
--- a/src/test/mir-opt/const_prop/discriminant.rs
+++ b/src/test/mir-opt/const_prop/discriminant.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -O
 
 // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with
diff --git a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
index 2e1e32545a2..948bb7f56fe 100644
--- a/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/indirect.main.ConstProp.diff
@@ -18,14 +18,14 @@
 -         assert(!move (_3.1: bool), "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
 +         _2 = const 2_u8;                 // scope 0 at $DIR/indirect.rs:+1:13: +1:25
 +         _3 = const (3_u8, false);        // scope 0 at $DIR/indirect.rs:+1:13: +1:29
-+         assert(!const false, "attempt to compute `{} + {}`, which would overflow", const 2_u8, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
++         assert(!const false, "attempt to compute `{} + {}`, which would overflow", move _2, const 1_u8) -> bb1; // scope 0 at $DIR/indirect.rs:+1:13: +1:29
       }
   
       bb1: {
 -         _1 = move (_3.0: u8);            // scope 0 at $DIR/indirect.rs:+1:13: +1:29
 +         _1 = const 3_u8;                 // scope 0 at $DIR/indirect.rs:+1:13: +1:29
           StorageDead(_2);                 // scope 0 at $DIR/indirect.rs:+1:28: +1:29
-          nop;                             // scope 0 at $DIR/indirect.rs:+0:11: +2:2
+          _0 = const ();                   // scope 0 at $DIR/indirect.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/indirect.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/indirect.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/const_prop/indirect.rs b/src/test/mir-opt/const_prop/indirect.rs
index 37217ca8134..44916cbfe74 100644
--- a/src/test/mir-opt/const_prop/indirect.rs
+++ b/src/test/mir-opt/const_prop/indirect.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR indirect.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/issue-66971.rs b/src/test/mir-opt/const_prop/issue-66971.rs
index 81eccae46b9..6ca03438ef3 100644
--- a/src/test/mir-opt/const_prop/issue-66971.rs
+++ b/src/test/mir-opt/const_prop/issue-66971.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
 // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected
diff --git a/src/test/mir-opt/const_prop/issue-67019.rs b/src/test/mir-opt/const_prop/issue-67019.rs
index c78b8b97178..ffc6fa1f290 100644
--- a/src/test/mir-opt/const_prop/issue-67019.rs
+++ b/src/test/mir-opt/const_prop/issue-67019.rs
@@ -1,3 +1,4 @@
+// unit-test: ConstProp
 // compile-flags: -Z mir-opt-level=3
 
 // This used to ICE in const-prop
diff --git a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
index b3d5980aa73..9d541dcabbb 100644
--- a/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_66971.main.ConstProp.diff
@@ -19,7 +19,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue-66971.rs:+1:21: +1:22
           _1 = encode(move _2) -> bb1;     // scope 0 at $DIR/issue-66971.rs:+1:5: +1:23
                                            // mir::Constant
-                                           // + span: $DIR/issue-66971.rs:16:5: 16:11
+                                           // + span: $DIR/issue-66971.rs:17:5: 17:11
                                            // + literal: Const { ty: fn(((), u8, u8)) {encode}, val: Value(<ZST>) }
       }
   
diff --git a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
index 8330b50529f..b79d814760d 100644
--- a/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/issue_67019.main.ConstProp.diff
@@ -20,7 +20,7 @@
           StorageDead(_3);                 // scope 0 at $DIR/issue-67019.rs:+1:18: +1:19
           _1 = test(move _2) -> bb1;       // scope 0 at $DIR/issue-67019.rs:+1:5: +1:20
                                            // mir::Constant
-                                           // + span: $DIR/issue-67019.rs:11:5: 11:9
+                                           // + span: $DIR/issue-67019.rs:12:5: 12:9
                                            // + literal: Const { ty: fn(((u8, u8),)) {test}, val: Value(<ZST>) }
       }
   
diff --git a/src/test/mir-opt/const_prop/mult_by_zero.rs b/src/test/mir-opt/const_prop/mult_by_zero.rs
index b0ecdf1818e..c839f92f2ce 100644
--- a/src/test/mir-opt/const_prop/mult_by_zero.rs
+++ b/src/test/mir-opt/const_prop/mult_by_zero.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O -Zmir-opt-level=4
 
 // EMIT_MIR mult_by_zero.test.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable.rs b/src/test/mir-opt/const_prop/mutable_variable.rs
index 801e7a9fcbb..cb01719dd77 100644
--- a/src/test/mir-opt/const_prop/mutable_variable.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
index e0b4b77bac4..d4ff8d89073 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
index 79ac497c783..9060f7e9bd3 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
index c678f7b0327..6eda503c1ee 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.main.ConstProp.diff
@@ -16,7 +16,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:9: +1:14
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_aggregate_partial_read.rs:+1:29: +1:34
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:5:29: 5:32
+                                           // + span: $DIR/mutable_variable_aggregate_partial_read.rs:6:29: 6:32
                                            // + literal: Const { ty: fn() -> (i32, i32) {foo}, val: Value(<ZST>) }
       }
   
diff --git a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
index 9bb62b8973c..cb59509ff10 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
index 4c2ba9a0998..eb3a7bc96d8 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.main.ConstProp.diff
@@ -25,7 +25,7 @@
           StorageLive(_4);                 // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
           _4 = const {alloc1: *mut u32};   // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_no_prop.rs:9:13: 9:19
+                                           // + span: $DIR/mutable_variable_no_prop.rs:10:13: 10:19
                                            // + literal: Const { ty: *mut u32, val: Value(Scalar(alloc1)) }
           _3 = (*_4);                      // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:13: +3:19
           _1 = move _3;                    // scope 2 at $DIR/mutable_variable_no_prop.rs:+3:9: +3:19
diff --git a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
index 4126fb3c68c..8c23c5fcf0f 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_no_prop.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 static mut STATIC: u32 = 42;
diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
index 5328792b323..4f205667be0 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.main.ConstProp.diff
@@ -25,7 +25,7 @@
           StorageLive(_1);                 // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:9: +1:10
           _1 = foo() -> bb1;               // scope 0 at $DIR/mutable_variable_unprop_assign.rs:+1:13: +1:18
                                            // mir::Constant
-                                           // + span: $DIR/mutable_variable_unprop_assign.rs:5:13: 5:16
+                                           // + span: $DIR/mutable_variable_unprop_assign.rs:6:13: 6:16
                                            // + literal: Const { ty: fn() -> i32 {foo}, val: Value(<ZST>) }
       }
   
diff --git a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
index 13f1b3f47f2..b077cfd3e0a 100644
--- a/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
+++ b/src/test/mir-opt/const_prop/mutable_variable_unprop_assign.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 // EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff
diff --git a/src/test/mir-opt/const_prop/optimizes_into_variable.rs b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
index 17265b7eb85..c0fbd2558cd 100644
--- a/src/test/mir-opt/const_prop/optimizes_into_variable.rs
+++ b/src/test/mir-opt/const_prop/optimizes_into_variable.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -C overflow-checks=on
 
 struct Point {
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
index 89f43d75138..b9c283a5482 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/read_immutable_static.main.ConstProp.diff
@@ -18,7 +18,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
           _3 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
                                            // mir::Constant
-                                           // + span: $DIR/read_immutable_static.rs:7:13: 7:16
+                                           // + span: $DIR/read_immutable_static.rs:8:13: 8:16
                                            // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _2 = (*_3);                      // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
 +         _2 = const 2_u8;                 // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:16
@@ -26,7 +26,7 @@
           StorageLive(_5);                 // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
           _5 = const {alloc1: &u8};        // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
                                            // mir::Constant
-                                           // + span: $DIR/read_immutable_static.rs:7:19: 7:22
+                                           // + span: $DIR/read_immutable_static.rs:8:19: 8:22
                                            // + literal: Const { ty: &u8, val: Value(Scalar(alloc1)) }
 -         _4 = (*_5);                      // scope 0 at $DIR/read_immutable_static.rs:+1:19: +1:22
 -         _1 = Add(move _2, move _4);      // scope 0 at $DIR/read_immutable_static.rs:+1:13: +1:22
diff --git a/src/test/mir-opt/const_prop/read_immutable_static.rs b/src/test/mir-opt/const_prop/read_immutable_static.rs
index 8a5f12c6f3d..4f7afe6cad4 100644
--- a/src/test/mir-opt/const_prop/read_immutable_static.rs
+++ b/src/test/mir-opt/const_prop/read_immutable_static.rs
@@ -1,3 +1,4 @@
+// unit-test
 // compile-flags: -O
 
 static FOO: u8 = 2;
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index f0c89caeac6..84ec5c8bb1d 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
@@ -13,7 +13,7 @@
           StorageLive(_2);                 // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
                                            // mir::Constant
-                                           // + span: $DIR/ref_deref_project.rs:5:6: 5:17
+                                           // + span: $DIR/ref_deref_project.rs:6:6: 6:17
                                            // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
           _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
index d2554028792..6f3a060a126 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
+++ b/src/test/mir-opt/const_prop/ref_deref_project.main.PromoteTemps.diff
@@ -16,7 +16,7 @@
 -         _2 = &(_3.1: i32);               // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
 +         _4 = const main::promoted[0];    // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
 +                                          // mir::Constant
-+                                          // + span: $DIR/ref_deref_project.rs:5:6: 5:17
++                                          // + span: $DIR/ref_deref_project.rs:6:6: 6:17
 +                                          // + literal: Const { ty: &(i32, i32), val: Unevaluated(main, [], Some(promoted[0])) }
 +         _2 = &((*_4).1: i32);            // scope 0 at $DIR/ref_deref_project.rs:+1:6: +1:17
           _1 = (*_2);                      // scope 0 at $DIR/ref_deref_project.rs:+1:5: +1:17
diff --git a/src/test/mir-opt/const_prop/ref_deref_project.rs b/src/test/mir-opt/const_prop/ref_deref_project.rs
index c7cc73651f6..659c11d9b0c 100644
--- a/src/test/mir-opt/const_prop/ref_deref_project.rs
+++ b/src/test/mir-opt/const_prop/ref_deref_project.rs
@@ -1,3 +1,4 @@
+// unit-test
 // EMIT_MIR ref_deref_project.main.PromoteTemps.diff
 // EMIT_MIR ref_deref_project.main.ConstProp.diff
 
diff --git a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
index 09765c7b997..0d10f9b5ffb 100644
--- a/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
+++ b/src/test/mir-opt/generator_drop_cleanup.main-{closure#0}.generator_drop.0.mir
@@ -17,14 +17,14 @@
 fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 10:17]) -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +0:17
     let mut _2: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +0:17
-    let _3: std::string::String;         // in scope 0 at $DIR/generator-drop-cleanup.rs:+1:13: +1:15
-    let _4: ();                          // in scope 0 at $DIR/generator-drop-cleanup.rs:+2:9: +2:14
-    let mut _5: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:+2:9: +2:14
-    let mut _6: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:18: +0:18
+    let _3: std::string::String;         // in scope 0 at $DIR/generator-drop-cleanup.rs:11:13: 11:15
+    let _4: ();                          // in scope 0 at $DIR/generator-drop-cleanup.rs:12:9: 12:14
+    let mut _5: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:12:9: 12:14
+    let mut _6: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:10:18: 10:18
     let mut _7: ();                      // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +0:17
     let mut _8: u32;                     // in scope 0 at $DIR/generator-drop-cleanup.rs:+0:15: +0:17
     scope 1 {
-        debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:+1:13: +1:15
+        debug _s => (((*_1) as variant#3).0: std::string::String); // in scope 1 at $DIR/generator-drop-cleanup.rs:11:13: 11:15
     }
 
     bb0: {
@@ -33,14 +33,14 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1
     }
 
     bb1: {
-        StorageDead(_5);                 // scope 1 at $DIR/generator-drop-cleanup.rs:+2:13: +2:14
-        StorageDead(_4);                 // scope 1 at $DIR/generator-drop-cleanup.rs:+2:14: +2:15
-        drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
+        StorageDead(_5);                 // scope 1 at $DIR/generator-drop-cleanup.rs:12:13: 12:14
+        StorageDead(_4);                 // scope 1 at $DIR/generator-drop-cleanup.rs:12:14: 12:15
+        drop((((*_1) as variant#3).0: std::string::String)) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
     }
 
     bb2: {
-        nop;                             // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
-        goto -> bb8;                     // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
+        nop;                             // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
+        goto -> bb8;                     // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
     }
 
     bb3: {
@@ -52,8 +52,8 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1
     }
 
     bb5 (cleanup): {
-        nop;                             // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
-        goto -> bb4;                     // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
+        nop;                             // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
+        goto -> bb4;                     // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
     }
 
     bb6: {
@@ -65,7 +65,7 @@ fn main::{closure#0}(_1: *mut [generator@$DIR/generator-drop-cleanup.rs:10:15: 1
     }
 
     bb8: {
-        goto -> bb3;                     // scope 0 at $DIR/generator-drop-cleanup.rs:+3:5: +3:6
+        goto -> bb3;                     // scope 0 at $DIR/generator-drop-cleanup.rs:13:5: 13:6
     }
 
     bb9: {
diff --git a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
index cb6ed33212e..5f677eafeb7 100644
--- a/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
+++ b/src/test/mir-opt/generator_storage_dead_unwind.main-{closure#0}.StateTransform.before.mir
@@ -3,66 +3,66 @@
 fn main::{closure#0}(_1: [generator@$DIR/generator-storage-dead-unwind.rs:22:16: 22:18], _2: ()) -> ()
 yields ()
  {
-    let mut _0: ();                      // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:19: +0:19
-    let _3: Foo;                         // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14
-    let _5: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
-    let mut _6: ();                      // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
-    let _7: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16
-    let mut _8: Foo;                     // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15
-    let _9: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16
-    let mut _10: Bar;                    // in scope 0 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15
+    let mut _0: ();                      // return place in scope 0 at $DIR/generator-storage-dead-unwind.rs:22:19: 22:19
+    let _3: Foo;                         // in scope 0 at $DIR/generator-storage-dead-unwind.rs:23:13: 23:14
+    let _5: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
+    let mut _6: ();                      // in scope 0 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
+    let _7: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
+    let mut _8: Foo;                     // in scope 0 at $DIR/generator-storage-dead-unwind.rs:26:14: 26:15
+    let _9: ();                          // in scope 0 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
+    let mut _10: Bar;                    // in scope 0 at $DIR/generator-storage-dead-unwind.rs:27:14: 27:15
     scope 1 {
-        debug a => _3;                   // in scope 1 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14
-        let _4: Bar;                     // in scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14
+        debug a => _3;                   // in scope 1 at $DIR/generator-storage-dead-unwind.rs:23:13: 23:14
+        let _4: Bar;                     // in scope 1 at $DIR/generator-storage-dead-unwind.rs:24:13: 24:14
         scope 2 {
-            debug b => _4;               // in scope 2 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14
+            debug b => _4;               // in scope 2 at $DIR/generator-storage-dead-unwind.rs:24:13: 24:14
         }
     }
 
     bb0: {
-        StorageLive(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:13: +1:14
-        Deinit(_3);                      // scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:17: +1:23
-        (_3.0: i32) = const 5_i32;       // scope 0 at $DIR/generator-storage-dead-unwind.rs:+1:17: +1:23
-        StorageLive(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:13: +2:14
-        Deinit(_4);                      // scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:17: +2:23
-        (_4.0: i32) = const 6_i32;       // scope 1 at $DIR/generator-storage-dead-unwind.rs:+2:17: +2:23
-        StorageLive(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
-        StorageLive(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
-        Deinit(_6);                      // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
-        _5 = yield(move _6) -> [resume: bb1, drop: bb5]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:9: +3:14
+        StorageLive(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:13: 23:14
+        Deinit(_3);                      // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:17: 23:23
+        (_3.0: i32) = const 5_i32;       // scope 0 at $DIR/generator-storage-dead-unwind.rs:23:17: 23:23
+        StorageLive(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:13: 24:14
+        Deinit(_4);                      // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:17: 24:23
+        (_4.0: i32) = const 6_i32;       // scope 1 at $DIR/generator-storage-dead-unwind.rs:24:17: 24:23
+        StorageLive(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
+        StorageLive(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
+        Deinit(_6);                      // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
+        _5 = yield(move _6) -> [resume: bb1, drop: bb5]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:9: 25:14
     }
 
     bb1: {
-        StorageDead(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:13: +3:14
-        StorageDead(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:14: +3:15
-        StorageLive(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16
-        StorageLive(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15
-        _8 = move _3;                    // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:14: +4:15
-        _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb9]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:9: +4:16
+        StorageDead(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:13: 25:14
+        StorageDead(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:14: 25:15
+        StorageLive(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
+        StorageLive(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:14: 26:15
+        _8 = move _3;                    // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:14: 26:15
+        _7 = take::<Foo>(move _8) -> [return: bb2, unwind: bb9]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:9: 26:16
                                          // mir::Constant
                                          // + span: $DIR/generator-storage-dead-unwind.rs:26:9: 26:13
                                          // + literal: Const { ty: fn(Foo) {take::<Foo>}, val: Value(<ZST>) }
     }
 
     bb2: {
-        StorageDead(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:15: +4:16
-        StorageDead(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:16: +4:17
-        StorageLive(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16
-        StorageLive(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15
-        _10 = move _4;                   // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:14: +5:15
-        _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb8]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:9: +5:16
+        StorageDead(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:15: 26:16
+        StorageDead(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:16: 26:17
+        StorageLive(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
+        StorageLive(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:14: 27:15
+        _10 = move _4;                   // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:14: 27:15
+        _9 = take::<Bar>(move _10) -> [return: bb3, unwind: bb8]; // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:9: 27:16
                                          // mir::Constant
                                          // + span: $DIR/generator-storage-dead-unwind.rs:27:9: 27:13
                                          // + literal: Const { ty: fn(Bar) {take::<Bar>}, val: Value(<ZST>) }
     }
 
     bb3: {
-        StorageDead(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:15: +5:16
-        StorageDead(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:16: +5:17
-        _0 = const ();                   // scope 0 at $DIR/generator-storage-dead-unwind.rs:+0:19: +6:6
-        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        drop(_1) -> [return: bb4, unwind: bb11]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
+        StorageDead(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:15: 27:16
+        StorageDead(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:16: 27:17
+        _0 = const ();                   // scope 0 at $DIR/generator-storage-dead-unwind.rs:22:19: 28:6
+        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        drop(_1) -> [return: bb4, unwind: bb11]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
     }
 
     bb4: {
@@ -70,15 +70,15 @@ yields ()
     }
 
     bb5: {
-        StorageDead(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:13: +3:14
-        StorageDead(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+3:14: +3:15
-        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        drop(_3) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
+        StorageDead(_6);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:13: 25:14
+        StorageDead(_5);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:25:14: 25:15
+        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        drop(_3) -> [return: bb6, unwind: bb12]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
     }
 
     bb6: {
-        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        drop(_1) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
+        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        drop(_1) -> [return: bb7, unwind: bb11]; // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
     }
 
     bb7: {
@@ -86,21 +86,21 @@ yields ()
     }
 
     bb8 (cleanup): {
-        StorageDead(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:15: +5:16
-        StorageDead(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+5:16: +5:17
+        StorageDead(_10);                // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:15: 27:16
+        StorageDead(_9);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:27:16: 27:17
         goto -> bb10;                    // scope 2 at no-location
     }
 
     bb9 (cleanup): {
-        StorageDead(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:15: +4:16
-        StorageDead(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:+4:16: +4:17
+        StorageDead(_8);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:15: 26:16
+        StorageDead(_7);                 // scope 2 at $DIR/generator-storage-dead-unwind.rs:26:16: 26:17
         goto -> bb10;                    // scope 2 at no-location
     }
 
     bb10 (cleanup): {
-        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        drop(_1) -> bb11;                // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
+        StorageDead(_4);                 // scope 1 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        drop(_1) -> bb11;                // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
     }
 
     bb11 (cleanup): {
@@ -108,7 +108,7 @@ yields ()
     }
 
     bb12 (cleanup): {
-        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
-        drop(_1) -> bb11;                // scope 0 at $DIR/generator-storage-dead-unwind.rs:+6:5: +6:6
+        StorageDead(_3);                 // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
+        drop(_1) -> bb11;                // scope 0 at $DIR/generator-storage-dead-unwind.rs:28:5: 28:6
     }
 }
diff --git a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
index 62e7d7b2da7..1917f757b6f 100644
--- a/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
+++ b/src/test/mir-opt/generator_tiny.main-{closure#0}.generator_resume.0.mir
@@ -17,17 +17,17 @@
 fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]>, _2: u8) -> GeneratorState<(), ()> {
     debug _x => _10;                     // in scope 0 at $DIR/generator-tiny.rs:+0:17: +0:19
     let mut _0: std::ops::GeneratorState<(), ()>; // return place in scope 0 at $DIR/generator-tiny.rs:+0:16: +0:24
-    let _3: HasDrop;                     // in scope 0 at $DIR/generator-tiny.rs:+1:13: +1:15
-    let mut _4: !;                       // in scope 0 at $DIR/generator-tiny.rs:+2:9: +5:10
+    let _3: HasDrop;                     // in scope 0 at $DIR/generator-tiny.rs:20:13: 20:15
+    let mut _4: !;                       // in scope 0 at $DIR/generator-tiny.rs:21:9: 24:10
     let mut _5: ();                      // in scope 0 at $DIR/generator-tiny.rs:+0:16: +0:24
-    let _6: u8;                          // in scope 0 at $DIR/generator-tiny.rs:+3:13: +3:18
-    let mut _7: ();                      // in scope 0 at $DIR/generator-tiny.rs:+3:13: +3:18
-    let _8: ();                          // in scope 0 at $DIR/generator-tiny.rs:+4:13: +4:21
-    let mut _9: ();                      // in scope 0 at $DIR/generator-tiny.rs:+0:25: +0:25
+    let _6: u8;                          // in scope 0 at $DIR/generator-tiny.rs:22:13: 22:18
+    let mut _7: ();                      // in scope 0 at $DIR/generator-tiny.rs:22:13: 22:18
+    let _8: ();                          // in scope 0 at $DIR/generator-tiny.rs:23:13: 23:21
+    let mut _9: ();                      // in scope 0 at $DIR/generator-tiny.rs:19:25: 19:25
     let _10: u8;                         // in scope 0 at $DIR/generator-tiny.rs:+0:17: +0:19
     let mut _11: u32;                    // in scope 0 at $DIR/generator-tiny.rs:+0:16: +0:24
     scope 1 {
-        debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:+1:13: +1:15
+        debug _d => (((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop); // in scope 1 at $DIR/generator-tiny.rs:20:13: 20:15
     }
 
     bb0: {
@@ -37,37 +37,37 @@ fn main::{closure#0}(_1: Pin<&mut [generator@$DIR/generator-tiny.rs:19:16: 19:24
 
     bb1: {
         _10 = move _2;                   // scope 0 at $DIR/generator-tiny.rs:+0:16: +0:24
-        nop;                             // scope 0 at $DIR/generator-tiny.rs:+1:13: +1:15
-        Deinit((((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop)); // scope 0 at $DIR/generator-tiny.rs:+1:18: +1:25
-        StorageLive(_4);                 // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10
-        goto -> bb2;                     // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10
+        nop;                             // scope 0 at $DIR/generator-tiny.rs:20:13: 20:15
+        Deinit((((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24])) as variant#3).0: HasDrop)); // scope 0 at $DIR/generator-tiny.rs:20:18: 20:25
+        StorageLive(_4);                 // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10
+        goto -> bb2;                     // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10
     }
 
     bb2: {
-        StorageLive(_6);                 // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        StorageLive(_7);                 // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        Deinit(_7);                      // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        Deinit(_0);                      // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        discriminant(_0) = 0;            // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
-        return;                          // scope 1 at $DIR/generator-tiny.rs:+3:13: +3:18
+        StorageLive(_6);                 // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        StorageLive(_7);                 // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        Deinit(_7);                      // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        Deinit(_0);                      // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        ((_0 as Yielded).0: ()) = move _7; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        discriminant(_0) = 0;            // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        discriminant((*(_1.0: &mut [generator@$DIR/generator-tiny.rs:19:16: 19:24]))) = 3; // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
+        return;                          // scope 1 at $DIR/generator-tiny.rs:22:13: 22:18
     }
 
     bb3: {
-        StorageDead(_7);                 // scope 1 at $DIR/generator-tiny.rs:+3:17: +3:18
-        StorageDead(_6);                 // scope 1 at $DIR/generator-tiny.rs:+3:18: +3:19
-        StorageLive(_8);                 // scope 1 at $DIR/generator-tiny.rs:+4:13: +4:21
-        _8 = callee() -> bb4;            // scope 1 at $DIR/generator-tiny.rs:+4:13: +4:21
+        StorageDead(_7);                 // scope 1 at $DIR/generator-tiny.rs:22:17: 22:18
+        StorageDead(_6);                 // scope 1 at $DIR/generator-tiny.rs:22:18: 22:19
+        StorageLive(_8);                 // scope 1 at $DIR/generator-tiny.rs:23:13: 23:21
+        _8 = callee() -> bb4;            // scope 1 at $DIR/generator-tiny.rs:23:13: 23:21
                                          // mir::Constant
                                          // + span: $DIR/generator-tiny.rs:23:13: 23:19
                                          // + literal: Const { ty: fn() {callee}, val: Value(<ZST>) }
     }
 
     bb4: {
-        StorageDead(_8);                 // scope 1 at $DIR/generator-tiny.rs:+4:21: +4:22
-        _5 = const ();                   // scope 1 at $DIR/generator-tiny.rs:+2:14: +5:10
-        goto -> bb2;                     // scope 1 at $DIR/generator-tiny.rs:+2:9: +5:10
+        StorageDead(_8);                 // scope 1 at $DIR/generator-tiny.rs:23:21: 23:22
+        _5 = const ();                   // scope 1 at $DIR/generator-tiny.rs:21:14: 24:10
+        goto -> bb2;                     // scope 1 at $DIR/generator-tiny.rs:21:9: 24:10
     }
 
     bb5: {
diff --git a/src/test/mir-opt/inline/cycle.g.Inline.diff b/src/test/mir-opt/inline/cycle.g.Inline.diff
index 59f34d379ec..5f3ee467c88 100644
--- a/src/test/mir-opt/inline/cycle.g.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.g.Inline.diff
@@ -6,10 +6,10 @@
       let _1: ();                          // in scope 0 at $DIR/cycle.rs:+1:5: +1:12
 +     let mut _2: fn() {main};             // in scope 0 at $DIR/cycle.rs:+1:5: +1:12
 +     scope 1 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
-+         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:+0:6: +0:7
-+         let _3: ();                      // in scope 1 at $DIR/cycle.rs:+0:5: +0:8
-+         let mut _4: &fn() {main};        // in scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:+0:5: +0:8
++         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:5:6: 5:7
++         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
++         let mut _4: &fn() {main};        // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         scope 2 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
 +         }
 +     }
@@ -25,10 +25,10 @@
 -                                          // mir::Constant
                                            // + span: $DIR/cycle.rs:12:7: 12:11
                                            // + literal: Const { ty: fn() {main}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:8
-+         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:8
++         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
++         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         _3 = move (*_4)() -> [return: bb4, unwind: bb2]; // scope 2 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
@@ -40,18 +40,18 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
-+         resume;                          // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
 +     }
 + 
 +     bb4: {
-+         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:+0:7: +0:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:+0:7: +0:8
-+         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:+0:8: +0:9
-+         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
++         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/cycle.main.Inline.diff b/src/test/mir-opt/inline/cycle.main.Inline.diff
index 6def7c3ee3e..8b4099b9d9f 100644
--- a/src/test/mir-opt/inline/cycle.main.Inline.diff
+++ b/src/test/mir-opt/inline/cycle.main.Inline.diff
@@ -6,17 +6,17 @@
       let _1: ();                          // in scope 0 at $DIR/cycle.rs:+1:5: +1:9
 +     let mut _2: fn() {g};                // in scope 0 at $DIR/cycle.rs:+1:5: +1:9
 +     scope 1 (inlined f::<fn() {g}>) {    // at $DIR/cycle.rs:17:5: 17:9
-+         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:+0:6: +0:7
-+         let _3: ();                      // in scope 1 at $DIR/cycle.rs:+0:5: +0:8
-+         let mut _4: &fn() {g};           // in scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:+0:5: +0:8
++         debug g => _2;                   // in scope 1 at $DIR/cycle.rs:5:6: 5:7
++         let _3: ();                      // in scope 1 at $DIR/cycle.rs:6:5: 6:8
++         let mut _4: &fn() {g};           // in scope 1 at $DIR/cycle.rs:6:5: 6:6
++         let mut _5: ();                  // in scope 1 at $DIR/cycle.rs:6:5: 6:8
 +         scope 2 (inlined <fn() {g} as Fn<()>>::call - shim(fn() {g})) { // at $DIR/cycle.rs:6:5: 6:8
 +             scope 3 (inlined g) {        // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+                 let mut _6: fn() {main}; // in scope 3 at $DIR/cycle.rs:+0:5: +0:12
++                 let mut _6: fn() {main}; // in scope 3 at $DIR/cycle.rs:12:5: 12:12
 +                 scope 4 (inlined f::<fn() {main}>) { // at $DIR/cycle.rs:12:5: 12:12
-+                     debug g => _6;       // in scope 4 at $DIR/cycle.rs:+0:6: +0:7
-+                     let _7: ();          // in scope 4 at $DIR/cycle.rs:+0:5: +0:8
-+                     let mut _8: &fn() {main}; // in scope 4 at $DIR/cycle.rs:+0:5: +0:6
++                     debug g => _6;       // in scope 4 at $DIR/cycle.rs:5:6: 5:7
++                     let _7: ();          // in scope 4 at $DIR/cycle.rs:6:5: 6:8
++                     let mut _8: &fn() {main}; // in scope 4 at $DIR/cycle.rs:6:5: 6:6
 +                     scope 5 (inlined <fn() {main} as Fn<()>>::call - shim(fn() {main})) { // at $DIR/cycle.rs:6:5: 6:8
 +                     }
 +                 }
@@ -35,14 +35,14 @@
 -                                          // mir::Constant
                                            // + span: $DIR/cycle.rs:17:7: 17:8
                                            // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:8
-+         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:+0:5: +0:6
-+         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:+0:5: +0:8
-+         StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:+0:5: +0:12
-+         StorageLive(_7);                 // scope 4 at $DIR/cycle.rs:+0:5: +0:8
-+         StorageLive(_8);                 // scope 4 at $DIR/cycle.rs:+0:5: +0:6
-+         _8 = &_6;                        // scope 4 at $DIR/cycle.rs:+0:5: +0:6
++         StorageLive(_3);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
++         StorageLive(_4);                 // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         _4 = &_2;                        // scope 1 at $DIR/cycle.rs:6:5: 6:6
++         StorageLive(_5);                 // scope 1 at $DIR/cycle.rs:6:5: 6:8
++         StorageLive(_6);                 // scope 3 at $DIR/cycle.rs:12:5: 12:12
++         StorageLive(_7);                 // scope 4 at $DIR/cycle.rs:6:5: 6:8
++         StorageLive(_8);                 // scope 4 at $DIR/cycle.rs:6:5: 6:6
++         _8 = &_6;                        // scope 4 at $DIR/cycle.rs:6:5: 6:6
 +         _7 = move (*_8)() -> [return: bb4, unwind: bb2]; // scope 5 at $SRC_DIR/core/src/ops/function.rs:LL:COL
       }
   
@@ -54,21 +54,21 @@
 +     }
 + 
 +     bb2 (cleanup): {
-+         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         drop(_2) -> bb3;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
 +     }
 + 
 +     bb3 (cleanup): {
-+         resume;                          // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         resume;                          // scope 1 at $DIR/cycle.rs:5:1: 7:2
 +     }
 + 
 +     bb4: {
-+         StorageDead(_8);                 // scope 4 at $DIR/cycle.rs:+0:7: +0:8
-+         StorageDead(_7);                 // scope 4 at $DIR/cycle.rs:+0:8: +0:9
-+         StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:+0:5: +0:12
-+         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:+0:7: +0:8
-+         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:+0:7: +0:8
-+         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:+0:8: +0:9
-+         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:+0:1: +0:2
++         StorageDead(_8);                 // scope 4 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_7);                 // scope 4 at $DIR/cycle.rs:6:8: 6:9
++         StorageDead(_6);                 // scope 3 at $DIR/cycle.rs:12:5: 12:12
++         StorageDead(_5);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_4);                 // scope 1 at $DIR/cycle.rs:6:7: 6:8
++         StorageDead(_3);                 // scope 1 at $DIR/cycle.rs:6:8: 6:9
++         drop(_2) -> bb1;                 // scope 1 at $DIR/cycle.rs:7:1: 7:2
       }
   }
   
diff --git a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
index 8eae04c4dd4..4b50ba9501c 100644
--- a/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
+++ b/src/test/mir-opt/inline/dyn_trait.get_query.Inline.diff
@@ -10,12 +10,12 @@
       scope 1 {
           debug c => _2;                   // in scope 1 at $DIR/dyn-trait.rs:+1:9: +1:10
 +         scope 2 (inlined try_execute_query::<<Q as Query>::C>) { // at $DIR/dyn-trait.rs:34:5: 34:25
-+             debug c => _4;               // in scope 2 at $DIR/dyn-trait.rs:+0:36: +0:37
-+             let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+             let mut _6: &<Q as Query>::C; // in scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
++             debug c => _4;               // in scope 2 at $DIR/dyn-trait.rs:26:36: 26:37
++             let mut _5: &dyn Cache<V = <Q as Query>::V>; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++             let mut _6: &<Q as Query>::C; // in scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
 +             scope 3 (inlined mk_cycle::<<Q as Query>::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16
-+                 debug c => _5;           // in scope 3 at $DIR/dyn-trait.rs:+0:27: +0:28
-+                 let mut _7: &dyn Cache<V = <Q as Query>::V>; // in scope 3 at $DIR/dyn-trait.rs:+0:5: +0:22
++                 debug c => _5;           // in scope 3 at $DIR/dyn-trait.rs:20:27: 20:28
++                 let mut _7: &dyn Cache<V = <Q as Query>::V>; // in scope 3 at $DIR/dyn-trait.rs:21:5: 21:22
 +             }
 +         }
       }
@@ -36,14 +36,14 @@
           StorageLive(_4);                 // scope 1 at $DIR/dyn-trait.rs:+2:23: +2:24
           _4 = &(*_2);                     // scope 1 at $DIR/dyn-trait.rs:+2:23: +2:24
 -         _0 = try_execute_query::<<Q as Query>::C>(move _4) -> bb2; // scope 1 at $DIR/dyn-trait.rs:+2:5: +2:25
-+         StorageLive(_5);                 // scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+         StorageLive(_6);                 // scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+         _6 = _4;                         // scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+         _5 = move _6 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+         StorageDead(_6);                 // scope 2 at $DIR/dyn-trait.rs:+0:14: +0:15
-+         StorageLive(_7);                 // scope 3 at $DIR/dyn-trait.rs:+0:5: +0:22
-+         _7 = _5;                         // scope 3 at $DIR/dyn-trait.rs:+0:5: +0:22
-+         _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:+0:5: +0:22
++         StorageLive(_5);                 // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++         StorageLive(_6);                 // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++         _6 = _4;                         // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++         _5 = move _6 as &dyn Cache<V = <Q as Query>::V> (Pointer(Unsize)); // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++         StorageDead(_6);                 // scope 2 at $DIR/dyn-trait.rs:27:14: 27:15
++         StorageLive(_7);                 // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22
++         _7 = _5;                         // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22
++         _0 = <dyn Cache<V = <Q as Query>::V> as Cache>::store_nocache(move _7) -> bb2; // scope 3 at $DIR/dyn-trait.rs:21:5: 21:22
                                            // mir::Constant
 -                                          // + span: $DIR/dyn-trait.rs:34:5: 34:22
 -                                          // + literal: Const { ty: for<'r> fn(&'r <Q as Query>::C) {try_execute_query::<<Q as Query>::C>}, val: Value(<ZST>) }
@@ -52,8 +52,8 @@
       }
   
       bb2: {
-+         StorageDead(_7);                 // scope 3 at $DIR/dyn-trait.rs:+0:21: +0:22
-+         StorageDead(_5);                 // scope 2 at $DIR/dyn-trait.rs:+0:15: +0:16
++         StorageDead(_7);                 // scope 3 at $DIR/dyn-trait.rs:21:21: 21:22
++         StorageDead(_5);                 // scope 2 at $DIR/dyn-trait.rs:27:15: 27:16
           StorageDead(_4);                 // scope 1 at $DIR/dyn-trait.rs:+2:24: +2:25
           StorageDead(_2);                 // scope 0 at $DIR/dyn-trait.rs:+3:1: +3:2
           return;                          // scope 0 at $DIR/dyn-trait.rs:+3:2: +3:2
diff --git a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
index e7c5972f429..58c05b9f564 100644
--- a/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
+++ b/src/test/mir-opt/inline/dyn_trait.try_execute_query.Inline.diff
@@ -7,8 +7,8 @@
       let mut _2: &dyn Cache<V = <C as Cache>::V>; // in scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15
       let mut _3: &C;                      // in scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15
 +     scope 1 (inlined mk_cycle::<<C as Cache>::V>) { // at $DIR/dyn-trait.rs:27:5: 27:16
-+         debug c => _2;                   // in scope 1 at $DIR/dyn-trait.rs:+0:27: +0:28
-+         let mut _4: &dyn Cache<V = <C as Cache>::V>; // in scope 1 at $DIR/dyn-trait.rs:+0:5: +0:22
++         debug c => _2;                   // in scope 1 at $DIR/dyn-trait.rs:20:27: 20:28
++         let mut _4: &dyn Cache<V = <C as Cache>::V>; // in scope 1 at $DIR/dyn-trait.rs:21:5: 21:22
 +     }
   
       bb0: {
@@ -18,9 +18,9 @@
           _2 = move _3 as &dyn Cache<V = <C as Cache>::V> (Pointer(Unsize)); // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15
           StorageDead(_3);                 // scope 0 at $DIR/dyn-trait.rs:+1:14: +1:15
 -         _0 = mk_cycle::<<C as Cache>::V>(move _2) -> bb1; // scope 0 at $DIR/dyn-trait.rs:+1:5: +1:16
-+         StorageLive(_4);                 // scope 1 at $DIR/dyn-trait.rs:+0:5: +0:22
-+         _4 = _2;                         // scope 1 at $DIR/dyn-trait.rs:+0:5: +0:22
-+         _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:+0:5: +0:22
++         StorageLive(_4);                 // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22
++         _4 = _2;                         // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22
++         _0 = <dyn Cache<V = <C as Cache>::V> as Cache>::store_nocache(move _4) -> bb1; // scope 1 at $DIR/dyn-trait.rs:21:5: 21:22
                                            // mir::Constant
 -                                          // + span: $DIR/dyn-trait.rs:27:5: 27:13
 -                                          // + literal: Const { ty: for<'r> fn(&'r (dyn Cache<V = <C as Cache>::V> + 'r)) {mk_cycle::<<C as Cache>::V>}, val: Value(<ZST>) }
@@ -29,7 +29,7 @@
       }
   
       bb1: {
-+         StorageDead(_4);                 // scope 1 at $DIR/dyn-trait.rs:+0:21: +0:22
++         StorageDead(_4);                 // scope 1 at $DIR/dyn-trait.rs:21:21: 21:22
           StorageDead(_2);                 // scope 0 at $DIR/dyn-trait.rs:+1:15: +1:16
           return;                          // scope 0 at $DIR/dyn-trait.rs:+2:2: +2:2
       }
diff --git a/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
index 63022525818..b27425fb18c 100644
--- a/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_any_operand.bar.Inline.after.mir
@@ -9,10 +9,10 @@ fn bar() -> bool {
     scope 1 {
         debug f => _1;                   // in scope 1 at $DIR/inline-any-operand.rs:+1:9: +1:10
         scope 2 (inlined foo) {          // at $DIR/inline-any-operand.rs:12:5: 12:13
-            debug x => _3;               // in scope 2 at $DIR/inline-any-operand.rs:+6:8: +6:9
-            debug y => _4;               // in scope 2 at $DIR/inline-any-operand.rs:+6:16: +6:17
-            let mut _5: i32;             // in scope 2 at $DIR/inline-any-operand.rs:+7:5: +7:6
-            let mut _6: i32;             // in scope 2 at $DIR/inline-any-operand.rs:+7:10: +7:11
+            debug x => _3;               // in scope 2 at $DIR/inline-any-operand.rs:16:8: 16:9
+            debug y => _4;               // in scope 2 at $DIR/inline-any-operand.rs:16:16: 16:17
+            let mut _5: i32;             // in scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
+            let mut _6: i32;             // in scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
         }
     }
 
@@ -28,13 +28,13 @@ fn bar() -> bool {
         _3 = const 1_i32;                // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13
         StorageLive(_4);                 // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13
         _4 = const -1_i32;               // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13
-        StorageLive(_5);                 // scope 2 at $DIR/inline-any-operand.rs:+7:5: +7:6
-        _5 = _3;                         // scope 2 at $DIR/inline-any-operand.rs:+7:5: +7:6
-        StorageLive(_6);                 // scope 2 at $DIR/inline-any-operand.rs:+7:10: +7:11
-        _6 = _4;                         // scope 2 at $DIR/inline-any-operand.rs:+7:10: +7:11
-        _0 = Eq(move _5, move _6);       // scope 2 at $DIR/inline-any-operand.rs:+7:5: +7:11
-        StorageDead(_6);                 // scope 2 at $DIR/inline-any-operand.rs:+7:10: +7:11
-        StorageDead(_5);                 // scope 2 at $DIR/inline-any-operand.rs:+7:10: +7:11
+        StorageLive(_5);                 // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
+        _5 = _3;                         // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:6
+        StorageLive(_6);                 // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
+        _6 = _4;                         // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
+        _0 = Eq(move _5, move _6);       // scope 2 at $DIR/inline-any-operand.rs:17:5: 17:11
+        StorageDead(_6);                 // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
+        StorageDead(_5);                 // scope 2 at $DIR/inline-any-operand.rs:17:10: 17:11
         StorageDead(_4);                 // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13
         StorageDead(_3);                 // scope 1 at $DIR/inline-any-operand.rs:+2:5: +2:13
         StorageDead(_2);                 // scope 1 at $DIR/inline-any-operand.rs:+2:12: +2:13
diff --git a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
index b1c476362de..a4d706de0ba 100644
--- a/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.one.Inline.diff
@@ -14,7 +14,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:24
-+         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline-cycle.rs:+23:9: +23:28
++         _1 = <C as Call>::call() -> bb1; // scope 3 at $DIR/inline-cycle.rs:36:9: 36:28
                                            // mir::Constant
 -                                          // + span: $DIR/inline-cycle.rs:14:5: 14:22
 +                                          // + span: $DIR/inline-cycle.rs:36:9: 36:26
diff --git a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
index dc890a36511..b1a5b62ef1d 100644
--- a/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle.two.Inline.diff
@@ -6,13 +6,13 @@
       let _1: ();                          // in scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12
 +     let mut _2: fn() {f};                // in scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12
 +     scope 1 (inlined call::<fn() {f}>) { // at $DIR/inline-cycle.rs:49:5: 49:12
-+         debug f => _2;                   // in scope 1 at $DIR/inline-cycle.rs:+5:22: +5:23
-+         let _3: ();                      // in scope 1 at $DIR/inline-cycle.rs:+6:5: +6:8
-+         let mut _4: fn() {f};            // in scope 1 at $DIR/inline-cycle.rs:+6:5: +6:6
-+         let mut _5: ();                  // in scope 1 at $DIR/inline-cycle.rs:+6:5: +6:8
++         debug f => _2;                   // in scope 1 at $DIR/inline-cycle.rs:53:22: 53:23
++         let _3: ();                      // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:8
++         let mut _4: fn() {f};            // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:6
++         let mut _5: ();                  // in scope 1 at $DIR/inline-cycle.rs:54:5: 54:8
 +         scope 2 (inlined <fn() {f} as FnOnce<()>>::call_once - shim(fn() {f})) { // at $DIR/inline-cycle.rs:54:5: 54:8
 +             scope 3 (inlined f) {        // at $SRC_DIR/core/src/ops/function.rs:LL:COL
-+                 let _6: ();              // in scope 3 at $DIR/inline-cycle.rs:+11:5: +11:12
++                 let _6: ();              // in scope 3 at $DIR/inline-cycle.rs:59:5: 59:12
 +             }
 +         }
 +     }
@@ -26,12 +26,12 @@
 -                                          // + span: $DIR/inline-cycle.rs:49:5: 49:9
 +                                          // + span: $DIR/inline-cycle.rs:49:10: 49:11
 +                                          // + literal: Const { ty: fn() {f}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 1 at $DIR/inline-cycle.rs:+6:5: +6:8
-+         StorageLive(_4);                 // scope 1 at $DIR/inline-cycle.rs:+6:5: +6:6
-+         _4 = move _2;                    // scope 1 at $DIR/inline-cycle.rs:+6:5: +6:6
-+         StorageLive(_5);                 // scope 1 at $DIR/inline-cycle.rs:+6:5: +6:8
-+         StorageLive(_6);                 // scope 3 at $DIR/inline-cycle.rs:+11:5: +11:12
-+         _6 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline-cycle.rs:+11:5: +11:12
++         StorageLive(_3);                 // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8
++         StorageLive(_4);                 // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6
++         _4 = move _2;                    // scope 1 at $DIR/inline-cycle.rs:54:5: 54:6
++         StorageLive(_5);                 // scope 1 at $DIR/inline-cycle.rs:54:5: 54:8
++         StorageLive(_6);                 // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12
++         _6 = call::<fn() {f}>(f) -> bb1; // scope 3 at $DIR/inline-cycle.rs:59:5: 59:12
 +                                          // mir::Constant
 +                                          // + span: $DIR/inline-cycle.rs:59:5: 59:9
                                            // + literal: Const { ty: fn(fn() {f}) {call::<fn() {f}>}, val: Value(<ZST>) }
@@ -42,10 +42,10 @@
       }
   
       bb1: {
-+         StorageDead(_6);                 // scope 3 at $DIR/inline-cycle.rs:+11:12: +11:13
-+         StorageDead(_5);                 // scope 1 at $DIR/inline-cycle.rs:+6:7: +6:8
-+         StorageDead(_4);                 // scope 1 at $DIR/inline-cycle.rs:+6:7: +6:8
-+         StorageDead(_3);                 // scope 1 at $DIR/inline-cycle.rs:+6:8: +6:9
++         StorageDead(_6);                 // scope 3 at $DIR/inline-cycle.rs:59:12: 59:13
++         StorageDead(_5);                 // scope 1 at $DIR/inline-cycle.rs:54:7: 54:8
++         StorageDead(_4);                 // scope 1 at $DIR/inline-cycle.rs:54:7: 54:8
++         StorageDead(_3);                 // scope 1 at $DIR/inline-cycle.rs:54:8: 54:9
 +         StorageDead(_2);                 // scope 0 at $DIR/inline-cycle.rs:+1:5: +1:12
           StorageDead(_1);                 // scope 0 at $DIR/inline-cycle.rs:+1:12: +1:13
           _0 = const ();                   // scope 0 at $DIR/inline-cycle.rs:+0:10: +2:2
diff --git a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
index 082f57e59a0..fc5d57ce8bf 100644
--- a/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_cycle_generic.main.Inline.diff
@@ -16,7 +16,7 @@
       bb0: {
           StorageLive(_1);                 // scope 0 at $DIR/inline-cycle-generic.rs:+1:5: +1:24
 -         _1 = <C as Call>::call() -> bb1; // scope 0 at $DIR/inline-cycle-generic.rs:+1:5: +1:24
-+         _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline-cycle-generic.rs:+23:9: +23:28
++         _1 = <C as Call>::call() -> bb1; // scope 4 at $DIR/inline-cycle-generic.rs:31:9: 31:28
                                            // mir::Constant
 -                                          // + span: $DIR/inline-cycle-generic.rs:9:5: 9:22
 +                                          // + span: $DIR/inline-cycle-generic.rs:31:9: 31:26
diff --git a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
index 6b24b3e1697..cef4cfc67ab 100644
--- a/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.f.Inline.diff
@@ -18,7 +18,7 @@
 +     }
 + 
 +     bb1: {
-+         goto -> bb1;                     // scope 1 at $DIR/inline-diverging.rs:+32:5: +32:12
++         goto -> bb1;                     // scope 1 at $DIR/inline-diverging.rs:39:5: 39:12
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
index 8759f3d02fc..6569ab24c38 100644
--- a/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
+++ b/src/test/mir-opt/inline/inline_diverging.h.Inline.diff
@@ -6,19 +6,19 @@
       let _1: (!, !);                      // in scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22
 +     let mut _2: fn() -> ! {sleep};       // in scope 0 at $DIR/inline-diverging.rs:+1:5: +1:22
 +     scope 1 (inlined call_twice::<!, fn() -> ! {sleep}>) { // at $DIR/inline-diverging.rs:22:5: 22:22
-+         debug f => _2;                   // in scope 1 at $DIR/inline-diverging.rs:+5:36: +5:37
-+         let _3: !;                       // in scope 1 at $DIR/inline-diverging.rs:+6:9: +6:10
-+         let mut _4: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:+6:13: +6:14
-+         let mut _5: ();                  // in scope 1 at $DIR/inline-diverging.rs:+6:13: +6:16
-+         let mut _7: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:+7:13: +7:14
-+         let mut _8: ();                  // in scope 1 at $DIR/inline-diverging.rs:+7:13: +7:16
-+         let mut _9: !;                   // in scope 1 at $DIR/inline-diverging.rs:+8:6: +8:7
-+         let mut _10: !;                  // in scope 1 at $DIR/inline-diverging.rs:+8:9: +8:10
++         debug f => _2;                   // in scope 1 at $DIR/inline-diverging.rs:26:36: 26:37
++         let _3: !;                       // in scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         let mut _4: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         let mut _5: ();                  // in scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         let mut _7: &fn() -> ! {sleep};  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:14
++         let mut _8: ();                  // in scope 1 at $DIR/inline-diverging.rs:28:13: 28:16
++         let mut _9: !;                   // in scope 1 at $DIR/inline-diverging.rs:29:6: 29:7
++         let mut _10: !;                  // in scope 1 at $DIR/inline-diverging.rs:29:9: 29:10
 +         scope 2 {
-+             debug a => _3;               // in scope 2 at $DIR/inline-diverging.rs:+6:9: +6:10
-+             let _6: !;                   // in scope 2 at $DIR/inline-diverging.rs:+7:9: +7:10
++             debug a => _3;               // in scope 2 at $DIR/inline-diverging.rs:27:9: 27:10
++             let _6: !;                   // in scope 2 at $DIR/inline-diverging.rs:28:9: 28:10
 +             scope 3 {
-+                 debug b => _6;           // in scope 3 at $DIR/inline-diverging.rs:+7:9: +7:10
++                 debug b => _6;           // in scope 3 at $DIR/inline-diverging.rs:28:9: 28:10
 +             }
 +             scope 6 (inlined <fn() -> ! {sleep} as Fn<()>>::call - shim(fn() -> ! {sleep})) { // at $DIR/inline-diverging.rs:28:13: 28:16
 +                 scope 7 (inlined sleep) { // at $SRC_DIR/core/src/ops/function.rs:LL:COL
@@ -42,15 +42,15 @@
 -                                          // mir::Constant
                                            // + span: $DIR/inline-diverging.rs:22:16: 22:21
                                            // + literal: Const { ty: fn() -> ! {sleep}, val: Value(<ZST>) }
-+         StorageLive(_3);                 // scope 1 at $DIR/inline-diverging.rs:+6:9: +6:10
-+         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:+6:13: +6:14
-+         _4 = &_2;                        // scope 1 at $DIR/inline-diverging.rs:+6:13: +6:14
-+         StorageLive(_5);                 // scope 1 at $DIR/inline-diverging.rs:+6:13: +6:16
-+         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:+18:5: +18:12
++         StorageLive(_3);                 // scope 1 at $DIR/inline-diverging.rs:27:9: 27:10
++         StorageLive(_4);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         _4 = &_2;                        // scope 1 at $DIR/inline-diverging.rs:27:13: 27:14
++         StorageLive(_5);                 // scope 1 at $DIR/inline-diverging.rs:27:13: 27:16
++         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
 +     }
 + 
 +     bb1: {
-+         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:+18:5: +18:12
++         goto -> bb1;                     // scope 5 at $DIR/inline-diverging.rs:39:5: 39:12
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_generator.main.Inline.diff b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
index c7c2759cc65..fd97d8bf333 100644
--- a/src/test/mir-opt/inline/inline_generator.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_generator.main.Inline.diff
@@ -24,15 +24,15 @@
 +         }
 +     }
 +     scope 6 (inlined g::{closure#0}) {   // at $DIR/inline-generator.rs:9:14: 9:46
-+         debug a => _11;                  // in scope 6 at $DIR/inline-generator.rs:+7:6: +7:7
-+         let mut _8: i32;                 // in scope 6 at $DIR/inline-generator.rs:+7:17: +7:39
-+         let mut _9: bool;                // in scope 6 at $DIR/inline-generator.rs:+7:20: +7:21
-+         let mut _10: bool;               // in scope 6 at $DIR/inline-generator.rs:+7:9: +7:9
-+         let _11: bool;                   // in scope 6 at $DIR/inline-generator.rs:+7:6: +7:7
-+         let mut _12: u32;                // in scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         let mut _13: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         let mut _14: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         let mut _15: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
++         debug a => _11;                  // in scope 6 at $DIR/inline-generator.rs:15:6: 15:7
++         let mut _8: i32;                 // in scope 6 at $DIR/inline-generator.rs:15:17: 15:39
++         let mut _9: bool;                // in scope 6 at $DIR/inline-generator.rs:15:20: 15:21
++         let mut _10: bool;               // in scope 6 at $DIR/inline-generator.rs:15:9: 15:9
++         let _11: bool;                   // in scope 6 at $DIR/inline-generator.rs:15:6: 15:7
++         let mut _12: u32;                // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         let mut _13: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         let mut _14: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         let mut _15: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]; // in scope 6 at $DIR/inline-generator.rs:15:5: 15:8
 +     }
   
       bb0: {
@@ -47,8 +47,8 @@
 -     }
 - 
 -     bb1: {
-+         Deinit(_4);                      // scope 2 at $DIR/inline-generator.rs:+7:5: +7:41
-+         discriminant(_4) = 0;            // scope 2 at $DIR/inline-generator.rs:+7:5: +7:41
++         Deinit(_4);                      // scope 2 at $DIR/inline-generator.rs:15:5: 15:41
++         discriminant(_4) = 0;            // scope 2 at $DIR/inline-generator.rs:15:5: 15:41
           _3 = &mut _4;                    // scope 0 at $DIR/inline-generator.rs:+1:23: +1:31
 -         _2 = Pin::<&mut [generator@$DIR/inline-generator.rs:15:5: 15:8]>::new(move _3) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/inline-generator.rs:+1:14: +1:32
 -                                          // mir::Constant
@@ -76,11 +76,11 @@
 +         StorageLive(_10);                // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46
 +         StorageLive(_11);                // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46
 +         StorageLive(_12);                // scope 0 at $DIR/inline-generator.rs:+1:14: +1:46
-+         StorageLive(_13);                // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         _13 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         _12 = discriminant((*_13));      // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         StorageDead(_13);                // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
++         StorageLive(_13);                // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         _13 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         _12 = discriminant((*_13));      // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         StorageDead(_13);                // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         switchInt(move _12) -> [0_u32: bb3, 1_u32: bb8, 3_u32: bb7, otherwise: bb9]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
       }
   
 -     bb3: {
@@ -102,55 +102,55 @@
 +     }
 + 
 +     bb3: {
-+         _11 = move _7;                   // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         StorageLive(_8);                 // scope 6 at $DIR/inline-generator.rs:+7:17: +7:39
-+         StorageLive(_9);                 // scope 6 at $DIR/inline-generator.rs:+7:20: +7:21
-+         _9 = _11;                        // scope 6 at $DIR/inline-generator.rs:+7:20: +7:21
-+         switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:+7:20: +7:21
++         _11 = move _7;                   // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         StorageLive(_8);                 // scope 6 at $DIR/inline-generator.rs:15:17: 15:39
++         StorageLive(_9);                 // scope 6 at $DIR/inline-generator.rs:15:20: 15:21
++         _9 = _11;                        // scope 6 at $DIR/inline-generator.rs:15:20: 15:21
++         switchInt(move _9) -> [false: bb5, otherwise: bb4]; // scope 6 at $DIR/inline-generator.rs:15:20: 15:21
 +     }
 + 
 +     bb4: {
-+         _8 = const 7_i32;                // scope 6 at $DIR/inline-generator.rs:+7:24: +7:25
-+         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:+7:17: +7:39
++         _8 = const 7_i32;                // scope 6 at $DIR/inline-generator.rs:15:24: 15:25
++         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:15:17: 15:39
 +     }
 + 
 +     bb5: {
-+         _8 = const 13_i32;               // scope 6 at $DIR/inline-generator.rs:+7:35: +7:37
-+         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:+7:17: +7:39
++         _8 = const 13_i32;               // scope 6 at $DIR/inline-generator.rs:15:35: 15:37
++         goto -> bb6;                     // scope 6 at $DIR/inline-generator.rs:15:17: 15:39
 +     }
 + 
 +     bb6: {
-+         StorageDead(_9);                 // scope 6 at $DIR/inline-generator.rs:+7:38: +7:39
-+         Deinit(_1);                      // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         discriminant(_1) = 0;            // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         StorageLive(_14);                // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         _14 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         discriminant((*_14)) = 3;        // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         StorageDead(_14);                // scope 6 at $DIR/inline-generator.rs:+7:11: +7:39
-+         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:+7:11: +7:39
++         StorageDead(_9);                 // scope 6 at $DIR/inline-generator.rs:15:38: 15:39
++         Deinit(_1);                      // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         ((_1 as Yielded).0: i32) = move _8; // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         discriminant(_1) = 0;            // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         StorageLive(_14);                // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         _14 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         discriminant((*_14)) = 3;        // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         StorageDead(_14);                // scope 6 at $DIR/inline-generator.rs:15:11: 15:39
++         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:15:11: 15:39
 +     }
 + 
 +     bb7: {
-+         StorageLive(_8);                 // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         _10 = move _7;                   // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
-+         StorageDead(_8);                 // scope 6 at $DIR/inline-generator.rs:+7:38: +7:39
-+         Deinit(_1);                      // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         discriminant(_1) = 1;            // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         StorageLive(_15);                // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         _15 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         discriminant((*_15)) = 1;        // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         StorageDead(_15);                // scope 6 at $DIR/inline-generator.rs:+7:8: +7:8
-+         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:+7:8: +7:8
++         StorageLive(_8);                 // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         _10 = move _7;                   // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
++         StorageDead(_8);                 // scope 6 at $DIR/inline-generator.rs:15:38: 15:39
++         Deinit(_1);                      // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         ((_1 as Complete).0: bool) = move _10; // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         discriminant(_1) = 1;            // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         StorageLive(_15);                // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         _15 = deref_copy (_2.0: &mut [generator@$DIR/inline-generator.rs:15:5: 15:8]); // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         discriminant((*_15)) = 1;        // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         StorageDead(_15);                // scope 6 at $DIR/inline-generator.rs:15:8: 15:8
++         goto -> bb1;                     // scope 0 at $DIR/inline-generator.rs:15:8: 15:8
 +     }
 + 
 +     bb8: {
-+         assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
++         assert(const false, "generator resumed after completion") -> [success: bb8, unwind: bb2]; // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
 +     }
 + 
 +     bb9: {
-+         unreachable;                     // scope 6 at $DIR/inline-generator.rs:+7:5: +7:8
++         unreachable;                     // scope 6 at $DIR/inline-generator.rs:15:5: 15:8
       }
   }
   
diff --git a/src/test/mir-opt/inline/inline_options.main.Inline.after.mir b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir
index 275493066ee..361b0271526 100644
--- a/src/test/mir-opt/inline/inline_options.main.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_options.main.Inline.after.mir
@@ -5,9 +5,9 @@ fn main() -> () {
     let _1: ();                          // in scope 0 at $DIR/inline-options.rs:+1:5: +1:18
     let _2: ();                          // in scope 0 at $DIR/inline-options.rs:+2:5: +2:21
     scope 1 (inlined inlined::<u32>) {   // at $DIR/inline-options.rs:10:5: 10:21
-        let _3: ();                      // in scope 1 at $DIR/inline-options.rs:+8:23: +8:26
-        let _4: ();                      // in scope 1 at $DIR/inline-options.rs:+8:28: +8:31
-        let _5: ();                      // in scope 1 at $DIR/inline-options.rs:+8:33: +8:36
+        let _3: ();                      // in scope 1 at $DIR/inline-options.rs:16:23: 16:26
+        let _4: ();                      // in scope 1 at $DIR/inline-options.rs:16:28: 16:31
+        let _5: ();                      // in scope 1 at $DIR/inline-options.rs:16:33: 16:36
     }
 
     bb0: {
@@ -21,33 +21,33 @@ fn main() -> () {
     bb1: {
         StorageDead(_1);                 // scope 0 at $DIR/inline-options.rs:+1:18: +1:19
         StorageLive(_2);                 // scope 0 at $DIR/inline-options.rs:+2:5: +2:21
-        StorageLive(_3);                 // scope 1 at $DIR/inline-options.rs:+8:23: +8:26
-        _3 = g() -> bb2;                 // scope 1 at $DIR/inline-options.rs:+8:23: +8:26
+        StorageLive(_3);                 // scope 1 at $DIR/inline-options.rs:16:23: 16:26
+        _3 = g() -> bb2;                 // scope 1 at $DIR/inline-options.rs:16:23: 16:26
                                          // mir::Constant
                                          // + span: $DIR/inline-options.rs:16:23: 16:24
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 
     bb2: {
-        StorageDead(_3);                 // scope 1 at $DIR/inline-options.rs:+8:26: +8:27
-        StorageLive(_4);                 // scope 1 at $DIR/inline-options.rs:+8:28: +8:31
-        _4 = g() -> bb3;                 // scope 1 at $DIR/inline-options.rs:+8:28: +8:31
+        StorageDead(_3);                 // scope 1 at $DIR/inline-options.rs:16:26: 16:27
+        StorageLive(_4);                 // scope 1 at $DIR/inline-options.rs:16:28: 16:31
+        _4 = g() -> bb3;                 // scope 1 at $DIR/inline-options.rs:16:28: 16:31
                                          // mir::Constant
                                          // + span: $DIR/inline-options.rs:16:28: 16:29
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 
     bb3: {
-        StorageDead(_4);                 // scope 1 at $DIR/inline-options.rs:+8:31: +8:32
-        StorageLive(_5);                 // scope 1 at $DIR/inline-options.rs:+8:33: +8:36
-        _5 = g() -> bb4;                 // scope 1 at $DIR/inline-options.rs:+8:33: +8:36
+        StorageDead(_4);                 // scope 1 at $DIR/inline-options.rs:16:31: 16:32
+        StorageLive(_5);                 // scope 1 at $DIR/inline-options.rs:16:33: 16:36
+        _5 = g() -> bb4;                 // scope 1 at $DIR/inline-options.rs:16:33: 16:36
                                          // mir::Constant
                                          // + span: $DIR/inline-options.rs:16:33: 16:34
                                          // + literal: Const { ty: fn() {g}, val: Value(<ZST>) }
     }
 
     bb4: {
-        StorageDead(_5);                 // scope 1 at $DIR/inline-options.rs:+8:36: +8:37
+        StorageDead(_5);                 // scope 1 at $DIR/inline-options.rs:16:36: 16:37
         StorageDead(_2);                 // scope 0 at $DIR/inline-options.rs:+2:21: +2:22
         _0 = const ();                   // scope 0 at $DIR/inline-options.rs:+0:11: +3:2
         return;                          // scope 0 at $DIR/inline-options.rs:+3:2: +3:2
diff --git a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
index 768608564d6..989fe278586 100644
--- a/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_retag.bar.Inline.after.mir
@@ -15,10 +15,10 @@ fn bar() -> bool {
         let mut _9: &i32;                // in scope 1 at $DIR/inline-retag.rs:+2:11: +2:14
         let mut _10: &i32;               // in scope 1 at $DIR/inline-retag.rs:+2:7: +2:9
         scope 2 (inlined foo) {          // at $DIR/inline-retag.rs:12:5: 12:15
-            debug x => _3;               // in scope 2 at $DIR/inline-retag.rs:+6:8: +6:9
-            debug y => _6;               // in scope 2 at $DIR/inline-retag.rs:+6:17: +6:18
-            let mut _11: i32;            // in scope 2 at $DIR/inline-retag.rs:+7:5: +7:7
-            let mut _12: i32;            // in scope 2 at $DIR/inline-retag.rs:+7:11: +7:13
+            debug x => _3;               // in scope 2 at $DIR/inline-retag.rs:16:8: 16:9
+            debug y => _6;               // in scope 2 at $DIR/inline-retag.rs:16:17: 16:18
+            let mut _11: i32;            // in scope 2 at $DIR/inline-retag.rs:17:5: 17:7
+            let mut _12: i32;            // in scope 2 at $DIR/inline-retag.rs:17:11: 17:13
         }
     }
 
@@ -52,15 +52,15 @@ fn bar() -> bool {
         Retag(_7);                       // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14
         _6 = &(*_7);                     // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14
         Retag(_6);                       // scope 1 at $DIR/inline-retag.rs:+2:11: +2:14
-        Retag(_3);                       // scope 2 at $DIR/inline-retag.rs:+6:1: +8:2
-        Retag(_6);                       // scope 2 at $DIR/inline-retag.rs:+6:1: +8:2
-        StorageLive(_11);                // scope 2 at $DIR/inline-retag.rs:+7:5: +7:7
-        _11 = (*_3);                     // scope 2 at $DIR/inline-retag.rs:+7:5: +7:7
-        StorageLive(_12);                // scope 2 at $DIR/inline-retag.rs:+7:11: +7:13
-        _12 = (*_6);                     // scope 2 at $DIR/inline-retag.rs:+7:11: +7:13
-        _0 = Eq(move _11, move _12);     // scope 2 at $DIR/inline-retag.rs:+7:5: +7:13
-        StorageDead(_12);                // scope 2 at $DIR/inline-retag.rs:+7:12: +7:13
-        StorageDead(_11);                // scope 2 at $DIR/inline-retag.rs:+7:12: +7:13
+        Retag(_3);                       // scope 2 at $DIR/inline-retag.rs:16:1: 18:2
+        Retag(_6);                       // scope 2 at $DIR/inline-retag.rs:16:1: 18:2
+        StorageLive(_11);                // scope 2 at $DIR/inline-retag.rs:17:5: 17:7
+        _11 = (*_3);                     // scope 2 at $DIR/inline-retag.rs:17:5: 17:7
+        StorageLive(_12);                // scope 2 at $DIR/inline-retag.rs:17:11: 17:13
+        _12 = (*_6);                     // scope 2 at $DIR/inline-retag.rs:17:11: 17:13
+        _0 = Eq(move _11, move _12);     // scope 2 at $DIR/inline-retag.rs:17:5: 17:13
+        StorageDead(_12);                // scope 2 at $DIR/inline-retag.rs:17:12: 17:13
+        StorageDead(_11);                // scope 2 at $DIR/inline-retag.rs:17:12: 17:13
         StorageDead(_6);                 // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15
         StorageDead(_3);                 // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15
         StorageDead(_2);                 // scope 1 at $DIR/inline-retag.rs:+2:14: +2:15
diff --git a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff
index 106291b36e3..fdf2a1e1ff9 100644
--- a/src/test/mir-opt/inline/inline_specialization.main.Inline.diff
+++ b/src/test/mir-opt/inline/inline_specialization.main.Inline.diff
@@ -19,7 +19,7 @@
 -     }
 - 
 -     bb1: {
-+         _1 = const 123_u32;              // scope 2 at $DIR/inline-specialization.rs:+10:31: +10:34
++         _1 = const 123_u32;              // scope 2 at $DIR/inline-specialization.rs:14:31: 14:34
           _0 = const ();                   // scope 0 at $DIR/inline-specialization.rs:+0:11: +2:2
           StorageDead(_1);                 // scope 0 at $DIR/inline-specialization.rs:+2:1: +2:2
           return;                          // scope 0 at $DIR/inline-specialization.rs:+2:2: +2:2
diff --git a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
index 116ae4e361b..b8896430d22 100644
--- a/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
+++ b/src/test/mir-opt/inline/inline_trait_method_2.test2.Inline.after.mir
@@ -6,8 +6,8 @@ fn test2(_1: &dyn X) -> bool {
     let mut _2: &dyn X;                  // in scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11
     let mut _3: &dyn X;                  // in scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11
     scope 1 (inlined test) {             // at $DIR/inline-trait-method_2.rs:5:5: 5:12
-        debug x => _2;                   // in scope 1 at $DIR/inline-trait-method_2.rs:+5:9: +5:10
-        let mut _4: &dyn X;              // in scope 1 at $DIR/inline-trait-method_2.rs:+6:5: +6:10
+        debug x => _2;                   // in scope 1 at $DIR/inline-trait-method_2.rs:9:9: 9:10
+        let mut _4: &dyn X;              // in scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
     }
 
     bb0: {
@@ -16,16 +16,16 @@ fn test2(_1: &dyn X) -> bool {
         _3 = &(*_1);                     // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11
         _2 = move _3 as &dyn X (Pointer(Unsize)); // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11
         StorageDead(_3);                 // scope 0 at $DIR/inline-trait-method_2.rs:+1:10: +1:11
-        StorageLive(_4);                 // scope 1 at $DIR/inline-trait-method_2.rs:+6:5: +6:10
-        _4 = _2;                         // scope 1 at $DIR/inline-trait-method_2.rs:+6:5: +6:10
-        _0 = <dyn X as X>::y(move _4) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:+6:5: +6:10
+        StorageLive(_4);                 // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
+        _4 = _2;                         // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
+        _0 = <dyn X as X>::y(move _4) -> bb1; // scope 1 at $DIR/inline-trait-method_2.rs:10:5: 10:10
                                          // mir::Constant
                                          // + span: $DIR/inline-trait-method_2.rs:10:7: 10:8
                                          // + literal: Const { ty: for<'r> fn(&'r dyn X) -> bool {<dyn X as X>::y}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_4);                 // scope 1 at $DIR/inline-trait-method_2.rs:+6:9: +6:10
+        StorageDead(_4);                 // scope 1 at $DIR/inline-trait-method_2.rs:10:9: 10:10
         StorageDead(_2);                 // scope 0 at $DIR/inline-trait-method_2.rs:+1:11: +1:12
         return;                          // scope 0 at $DIR/inline-trait-method_2.rs:+2:2: +2:2
     }
diff --git a/src/test/mir-opt/inline/polymorphic-recursion.rs b/src/test/mir-opt/inline/polymorphic-recursion.rs
new file mode 100644
index 00000000000..7388722b776
--- /dev/null
+++ b/src/test/mir-opt/inline/polymorphic-recursion.rs
@@ -0,0 +1,25 @@
+// Make sure that the MIR inliner does not loop indefinitely on polymorphic recursion.
+// compile-flags: --crate-type lib
+
+// Randomize `def_path_hash` by defining them under a module with different names
+macro_rules! emit {
+    ($($m:ident)*) => {$(
+        pub mod $m {
+            pub trait Tr { type Next: Tr; }
+
+            pub fn hoge<const N: usize, T: Tr>() {
+                inner::<N, T>();
+            }
+
+            #[inline(always)]
+            fn inner<const N: usize, T: Tr>()
+            {
+                inner::<N, T::Next>();
+                inner::<N, T::Next>();
+            }
+        }
+    )*};
+}
+
+// Increase the chance of triggering the bug
+emit!(m00 m01 m02 m03 m04 m05 m06 m07 m08 m09 m10 m11 m12 m13 m14 m15 m16 m17 m18 m19);
diff --git a/src/test/mir-opt/issue-91633.rs b/src/test/mir-opt/issue-91633.rs
new file mode 100644
index 00000000000..8f66019857f
--- /dev/null
+++ b/src/test/mir-opt/issue-91633.rs
@@ -0,0 +1,31 @@
+// compile-flags: -Z mir-opt-level=0
+// EMIT_MIR issue_91633.hey.mir_map.0.mir
+fn hey<T> (it: &[T])
+ where
+     [T] : std::ops::Index<usize>,
+ {
+     let _ = &it[0];
+ }
+
+// EMIT_MIR issue_91633.bar.mir_map.0.mir
+fn bar<T> (it: Box<[T]>)
+ where
+     [T] : std::ops::Index<usize>,
+ {
+     let _ = it[0];
+ }
+
+// EMIT_MIR issue_91633.fun.mir_map.0.mir
+fn fun<T> (it: &[T]) -> &T
+ {
+     let f = &it[0];
+     f
+ }
+
+// EMIT_MIR issue_91633.foo.mir_map.0.mir
+fn foo<T: Clone> (it: Box<[T]>) -> T
+ {
+     let f = it[0].clone();
+     f
+ }
+ fn main(){}
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
index 50948180fc4..ac7fe31f3b3 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.32bit.diff
@@ -55,7 +55,7 @@
           ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
           discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
           _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30
+          goto -> bb3;                     // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30
       }
   
       bb1: {
@@ -66,6 +66,10 @@
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
+      }
+  
+      bb3: {
           StorageLive(_4);                 // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
           _4 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
           _1 = _4;                         // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
@@ -108,10 +112,10 @@
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _15) -> [false: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_20);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           discriminant(_20) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -141,7 +145,7 @@
                                            // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
       }
   
-      bb4: {
+      bb5: {
           nop;                             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
index 50948180fc4..ac7fe31f3b3 100644
--- a/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
+++ b/src/test/mir-opt/issue_73223.main.SimplifyArmIdentity.64bit.diff
@@ -55,7 +55,7 @@
           ((_2 as Some).0: i32) = const 1_i32; // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
           discriminant(_2) = 1;            // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
           _3 = const 1_isize;              // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
-          goto -> bb2;                     // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30
+          goto -> bb3;                     // scope 0 at $DIR/issue-73223.rs:+1:17: +1:30
       }
   
       bb1: {
@@ -66,6 +66,10 @@
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/issue-73223.rs:+1:23: +1:30
+      }
+  
+      bb3: {
           StorageLive(_4);                 // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
           _4 = ((_2 as Some).0: i32);      // scope 0 at $DIR/issue-73223.rs:+2:14: +2:15
           _1 = _4;                         // scope 2 at $DIR/issue-73223.rs:+2:20: +2:21
@@ -108,10 +112,10 @@
           StorageDead(_17);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           _15 = Not(move _16);             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_16);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
-          switchInt(move _15) -> [false: bb4, otherwise: bb3]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
+          switchInt(move _15) -> [false: bb5, otherwise: bb4]; // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_20);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           Deinit(_20);                     // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           discriminant(_20) = 0;           // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
@@ -141,7 +145,7 @@
                                            // + literal: Const { ty: core::panicking::AssertKind, val: Value(Scalar(0x00)) }
       }
   
-      bb4: {
+      bb5: {
           nop;                             // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_15);                // scope 4 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
           StorageDead(_14);                // scope 3 at $SRC_DIR/core/src/macros/mod.rs:LL:COL
diff --git a/src/test/mir-opt/issue_91633.bar.mir_map.0.mir b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir
new file mode 100644
index 00000000000..f5092d2ac92
--- /dev/null
+++ b/src/test/mir-opt/issue_91633.bar.mir_map.0.mir
@@ -0,0 +1,39 @@
+// MIR for `bar` 0 mir_map
+
+fn bar(_1: Box<[T]>) -> () {
+    debug it => _1;                      // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2
+    let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
+    let mut _3: &[T];                    // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
+        StorageLive(_3);                 // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
+        _3 = &(*_1);                     // scope 0 at $DIR/issue-91633.rs:+4:14: +4:16
+        _2 = <[T] as Index<usize>>::index(move _3, const 0_usize) -> [return: bb1, unwind: bb3]; // scope 0 at $DIR/issue-91633.rs:+4:14: +4:19
+                                         // mir::Constant
+                                         // + span: $DIR/issue-91633.rs:15:14: 15:19
+                                         // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageDead(_3);                 // scope 0 at $DIR/issue-91633.rs:+4:18: +4:19
+        StorageDead(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20
+        _0 = const ();                   // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3
+        drop(_1) -> [return: bb2, unwind: bb4]; // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
+    }
+
+    bb2: {
+        return;                          // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3
+    }
+
+    bb3 (cleanup): {
+        drop(_1) -> bb4;                 // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
+    }
+
+    bb4 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3
+    }
+}
diff --git a/src/test/mir-opt/issue_91633.foo.mir_map.0.mir b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir
new file mode 100644
index 00000000000..2e8b0feedd3
--- /dev/null
+++ b/src/test/mir-opt/issue_91633.foo.mir_map.0.mir
@@ -0,0 +1,57 @@
+// MIR for `foo` 0 mir_map
+
+fn foo(_1: Box<[T]>) -> T {
+    debug it => _1;                      // in scope 0 at $DIR/issue-91633.rs:+0:19: +0:21
+    let mut _0: T;                       // return place in scope 0 at $DIR/issue-91633.rs:+0:36: +0:37
+    let _2: T;                           // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+    let mut _3: &T;                      // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
+    let _4: usize;                       // in scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
+    let mut _5: usize;                   // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
+    let mut _6: bool;                    // in scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
+    scope 1 {
+        debug f => _2;                   // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+        StorageLive(_3);                 // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
+        StorageLive(_4);                 // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
+        _4 = const 0_usize;              // scope 0 at $DIR/issue-91633.rs:+2:17: +2:18
+        _5 = Len((*_1));                 // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
+        _6 = Lt(_4, _5);                 // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
+        assert(move _6, "index out of bounds: the length is {} but the index is {}", move _5, _4) -> [success: bb1, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:19
+    }
+
+    bb1: {
+        _3 = &(*_1)[_4];                 // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
+        _2 = <T as Clone>::clone(move _3) -> [return: bb2, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+2:14: +2:27
+                                         // mir::Constant
+                                         // + span: $DIR/issue-91633.rs:28:20: 28:25
+                                         // + literal: Const { ty: for<'r> fn(&'r T) -> T {<T as Clone>::clone}, val: Value(<ZST>) }
+    }
+
+    bb2: {
+        StorageDead(_3);                 // scope 0 at $DIR/issue-91633.rs:+2:26: +2:27
+        FakeRead(ForLet(None), _2);      // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+        StorageDead(_4);                 // scope 0 at $DIR/issue-91633.rs:+2:27: +2:28
+        _0 = move _2;                    // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7
+        drop(_2) -> [return: bb3, unwind: bb5]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+    }
+
+    bb3: {
+        StorageDead(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+        drop(_1) -> [return: bb4, unwind: bb6]; // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+    }
+
+    bb4: {
+        return;                          // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3
+    }
+
+    bb5 (cleanup): {
+        drop(_1) -> bb6;                 // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+    }
+
+    bb6 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3
+    }
+}
diff --git a/src/test/mir-opt/issue_91633.fun.mir_map.0.mir b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir
new file mode 100644
index 00000000000..ded9a4cf7e3
--- /dev/null
+++ b/src/test/mir-opt/issue_91633.fun.mir_map.0.mir
@@ -0,0 +1,35 @@
+// MIR for `fun` 0 mir_map
+
+fn fun(_1: &[T]) -> &T {
+    debug it => _1;                      // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
+    let mut _0: &T;                      // return place in scope 0 at $DIR/issue-91633.rs:+0:25: +0:27
+    let _2: &T;                          // in scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+    let _3: usize;                       // in scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
+    let mut _4: usize;                   // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
+    let mut _5: bool;                    // in scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
+    scope 1 {
+        debug f => _2;                   // in scope 1 at $DIR/issue-91633.rs:+2:10: +2:11
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+        StorageLive(_3);                 // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
+        _3 = const 0_usize;              // scope 0 at $DIR/issue-91633.rs:+2:18: +2:19
+        _4 = Len((*_1));                 // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
+        _5 = Lt(_3, _4);                 // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
+        assert(move _5, "index out of bounds: the length is {} but the index is {}", move _4, _3) -> [success: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+2:15: +2:20
+    }
+
+    bb1: {
+        _2 = &(*_1)[_3];                 // scope 0 at $DIR/issue-91633.rs:+2:14: +2:20
+        FakeRead(ForLet(None), _2);      // scope 0 at $DIR/issue-91633.rs:+2:10: +2:11
+        _0 = &(*_2);                     // scope 1 at $DIR/issue-91633.rs:+3:6: +3:7
+        StorageDead(_3);                 // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+        StorageDead(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:2: +4:3
+        return;                          // scope 0 at $DIR/issue-91633.rs:+4:3: +4:3
+    }
+
+    bb2 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-91633.rs:+0:1: +4:3
+    }
+}
diff --git a/src/test/mir-opt/issue_91633.hey.mir_map.0.mir b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir
new file mode 100644
index 00000000000..74f4a5a9761
--- /dev/null
+++ b/src/test/mir-opt/issue_91633.hey.mir_map.0.mir
@@ -0,0 +1,35 @@
+// MIR for `hey` 0 mir_map
+
+fn hey(_1: &[T]) -> () {
+    debug it => _1;                      // in scope 0 at $DIR/issue-91633.rs:+0:12: +0:14
+    let mut _0: ();                      // return place in scope 0 at $DIR/issue-91633.rs:+1:2: +1:2
+    let mut _2: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
+    let _3: &<[T] as std::ops::Index<usize>>::Output; // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
+    let mut _4: &[T];                    // in scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
+    scope 1 {
+    }
+
+    bb0: {
+        StorageLive(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
+        StorageLive(_3);                 // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
+        StorageLive(_4);                 // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
+        _4 = &(*_1);                     // scope 0 at $DIR/issue-91633.rs:+4:15: +4:17
+        _3 = <[T] as Index<usize>>::index(move _4, const 0_usize) -> [return: bb1, unwind: bb2]; // scope 0 at $DIR/issue-91633.rs:+4:15: +4:20
+                                         // mir::Constant
+                                         // + span: $DIR/issue-91633.rs:7:15: 7:20
+                                         // + literal: Const { ty: for<'r> fn(&'r [T], usize) -> &'r <[T] as Index<usize>>::Output {<[T] as Index<usize>>::index}, val: Value(<ZST>) }
+    }
+
+    bb1: {
+        StorageDead(_4);                 // scope 0 at $DIR/issue-91633.rs:+4:19: +4:20
+        _2 = &(*_3);                     // scope 0 at $DIR/issue-91633.rs:+4:14: +4:20
+        StorageDead(_2);                 // scope 0 at $DIR/issue-91633.rs:+4:20: +4:21
+        _0 = const ();                   // scope 0 at $DIR/issue-91633.rs:+3:2: +5:3
+        StorageDead(_3);                 // scope 0 at $DIR/issue-91633.rs:+5:2: +5:3
+        return;                          // scope 0 at $DIR/issue-91633.rs:+5:3: +5:3
+    }
+
+    bb2 (cleanup): {
+        resume;                          // scope 0 at $DIR/issue-91633.rs:+0:1: +5:3
+    }
+}
diff --git a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
index 9e4de2ac068..2a9a099a38d 100644
--- a/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
+++ b/src/test/mir-opt/lower_intrinsics.f_u64.PreCodegen.before.mir
@@ -4,9 +4,9 @@ fn f_u64() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:16: +0:16
     let mut _1: u64;                     // in scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
     scope 1 (inlined f_dispatch::<u64>) { // at $DIR/lower_intrinsics.rs:40:5: 40:21
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+5:22: +5:23
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:+9:9: +9:21
-        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:+9:19: +9:20
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
+        let mut _3: u64;                 // in scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
         scope 2 (inlined std::mem::size_of::<u64>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
         }
     }
@@ -14,18 +14,18 @@ fn f_u64() -> () {
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
         _1 = const 0_u64;                // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+9:9: +9:21
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+9:19: +9:20
-        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:+9:19: +9:20
-        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+9:9: +9:21
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
+        _3 = move _1;                    // scope 1 at $DIR/lower_intrinsics.rs:48:19: 48:20
+        _2 = f_non_zst::<u64>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:48:9: 48:21
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics.rs:48:9: 48:18
                                          // + literal: Const { ty: fn(u64) {f_non_zst::<u64>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+9:20: +9:21
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+9:21: +9:22
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:48:20: 48:21
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:48:21: 48:22
         StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:5: +1:21
         return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
     }
diff --git a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
index 9a6c0457f92..5783822f6b5 100644
--- a/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
+++ b/src/test/mir-opt/lower_intrinsics.f_unit.PreCodegen.before.mir
@@ -4,26 +4,26 @@ fn f_unit() -> () {
     let mut _0: ();                      // return place in scope 0 at $DIR/lower_intrinsics.rs:+0:17: +0:17
     let mut _1: ();                      // in scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
     scope 1 (inlined f_dispatch::<()>) { // at $DIR/lower_intrinsics.rs:34:5: 34:19
-        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:+11:22: +11:23
-        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:+13:9: +13:17
-        let mut _3: ();                  // in scope 1 at $DIR/lower_intrinsics.rs:+13:15: +13:16
+        debug t => _1;                   // in scope 1 at $DIR/lower_intrinsics.rs:44:22: 44:23
+        let _2: ();                      // in scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
+        let mut _3: ();                  // in scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
         scope 2 (inlined std::mem::size_of::<()>) { // at $DIR/lower_intrinsics.rs:45:8: 45:32
         }
     }
 
     bb0: {
         StorageLive(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:16: +1:18
-        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+13:9: +13:17
-        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+13:15: +13:16
-        _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:+13:9: +13:17
+        StorageLive(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
+        StorageLive(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:46:15: 46:16
+        _2 = f_zst::<()>(move _3) -> bb1; // scope 1 at $DIR/lower_intrinsics.rs:46:9: 46:17
                                          // mir::Constant
                                          // + span: $DIR/lower_intrinsics.rs:46:9: 46:14
                                          // + literal: Const { ty: fn(()) {f_zst::<()>}, val: Value(<ZST>) }
     }
 
     bb1: {
-        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:+13:16: +13:17
-        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:+13:17: +13:18
+        StorageDead(_3);                 // scope 1 at $DIR/lower_intrinsics.rs:46:16: 46:17
+        StorageDead(_2);                 // scope 1 at $DIR/lower_intrinsics.rs:46:17: 46:18
         StorageDead(_1);                 // scope 0 at $DIR/lower_intrinsics.rs:+1:18: +1:19
         return;                          // scope 0 at $DIR/lower_intrinsics.rs:+2:2: +2:2
     }
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
index c42657b3855..1b4dddc1d43 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.32bit.diff
@@ -8,20 +8,24 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
           _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
       }
   
       bb2: {
-          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          unreachable;                     // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
       }
   
       bb3: {
+          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+      }
+  
+      bb4: {
           return;                          // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
index c42657b3855..1b4dddc1d43 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match.MatchBranchSimplification.64bit.diff
@@ -8,20 +8,24 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
           _0 = const 1_u8;                 // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
       }
   
       bb2: {
-          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          unreachable;                     // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
       }
   
       bb3: {
+          _0 = const 0_u8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+      }
+  
+      bb4: {
           return;                          // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
index a4ff2e437db..6e734852e1a 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.32bit.diff
@@ -8,20 +8,24 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
           _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
       }
   
       bb2: {
-          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          unreachable;                     // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
       }
   
       bb3: {
+          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+      }
+  
+      bb4: {
           return;                          // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
index a4ff2e437db..6e734852e1a 100644
--- a/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
+++ b/src/test/mir-opt/matches_u8.exhaustive_match_i8.MatchBranchSimplification.64bit.diff
@@ -8,20 +8,24 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/matches_u8.rs:+1:5: +1:12
       }
   
       bb1: {
           _0 = const 1_i8;                 // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+3:17: +3:18
       }
   
       bb2: {
-          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
-          goto -> bb3;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          unreachable;                     // scope 0 at $DIR/matches_u8.rs:+1:11: +1:12
       }
   
       bb3: {
+          _0 = const 0_i8;                 // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+          goto -> bb4;                     // scope 0 at $DIR/matches_u8.rs:+2:17: +2:18
+      }
+  
+      bb4: {
           return;                          // scope 0 at $DIR/matches_u8.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
index 60c0f336e74..faaacc67ea8 100644
--- a/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
+++ b/src/test/mir-opt/retag.main-{closure#0}.SimplifyCfg-elaborate-drops.after.mir
@@ -3,20 +3,20 @@
 fn main::{closure#0}(_1: &[closure@main::{closure#0}], _2: &i32) -> &i32 {
     debug x => _2;                       // in scope 0 at $DIR/retag.rs:+0:32: +0:33
     let mut _0: &i32;                    // return place in scope 0 at $DIR/retag.rs:+0:44: +0:48
-    let _3: &i32;                        // in scope 0 at $DIR/retag.rs:+1:13: +1:15
+    let _3: &i32;                        // in scope 0 at $DIR/retag.rs:42:13: 42:15
     scope 1 {
-        debug _y => _3;                  // in scope 1 at $DIR/retag.rs:+1:13: +1:15
+        debug _y => _3;                  // in scope 1 at $DIR/retag.rs:42:13: 42:15
     }
 
     bb0: {
         Retag([fn entry] _1);            // scope 0 at $DIR/retag.rs:+0:31: +0:48
         Retag([fn entry] _2);            // scope 0 at $DIR/retag.rs:+0:31: +0:48
-        StorageLive(_3);                 // scope 0 at $DIR/retag.rs:+1:13: +1:15
-        _3 = _2;                         // scope 0 at $DIR/retag.rs:+1:18: +1:19
-        Retag(_3);                       // scope 0 at $DIR/retag.rs:+1:18: +1:19
-        _0 = _2;                         // scope 1 at $DIR/retag.rs:+2:9: +2:10
-        Retag(_0);                       // scope 1 at $DIR/retag.rs:+2:9: +2:10
-        StorageDead(_3);                 // scope 0 at $DIR/retag.rs:+3:5: +3:6
+        StorageLive(_3);                 // scope 0 at $DIR/retag.rs:42:13: 42:15
+        _3 = _2;                         // scope 0 at $DIR/retag.rs:42:18: 42:19
+        Retag(_3);                       // scope 0 at $DIR/retag.rs:42:18: 42:19
+        _0 = _2;                         // scope 1 at $DIR/retag.rs:43:9: 43:10
+        Retag(_0);                       // scope 1 at $DIR/retag.rs:43:9: 43:10
+        StorageDead(_3);                 // scope 0 at $DIR/retag.rs:44:5: 44:6
         return;                          // scope 0 at $DIR/retag.rs:+0:48: +0:48
     }
 }
diff --git a/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff b/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
index 3a11e45cacd..ca90489f8ae 100644
--- a/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
+++ b/src/test/mir-opt/separate_const_switch.identity.ConstProp.diff
@@ -57,7 +57,7 @@
           _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           _10 = discriminant(_4);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-          switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+          switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
       bb1: {
@@ -74,6 +74,10 @@
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+      }
+  
+      bb3: {
           StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
           _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
           StorageLive(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
@@ -97,7 +101,7 @@
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_13);                // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           _13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_14);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
@@ -115,16 +119,16 @@
           StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
--         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+-         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 +         _5 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(const 1_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(const 1_isize) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
-      bb4: {
+      bb5: {
           unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
-      bb5: {
+      bb6: {
           StorageLive(_11);                // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           _11 = move ((_4 as Ok).0: i32);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
@@ -137,9 +141,9 @@
           StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
--         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+-         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 +         _5 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(const 0_isize) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(const 0_isize) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   }
   
diff --git a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
index 8453d534150..6816f8f9c1e 100644
--- a/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.identity.SeparateConstSwitch.diff
@@ -57,15 +57,15 @@
           _4 = _1;                         // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:9
           StorageLive(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
           _10 = discriminant(_4);          // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
--         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
-+         switchInt(move _10) -> [0_isize: bb5, 1_isize: bb3, otherwise: bb4]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
+-         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
++         switchInt(move _10) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
       bb1: {
 -         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 -         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 -         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
--         switchInt(move _5) -> [0_isize: bb2, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+-         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 -     }
 - 
 -     bb2: {
@@ -83,6 +83,11 @@
   
 -     bb3: {
 +     bb2: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
+      }
+  
+-     bb4: {
++     bb3: {
           StorageLive(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
           _6 = ((_3 as Break).0: std::result::Result<std::convert::Infallible, i32>); // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
           StorageLive(_8);                 // scope 2 at $DIR/separate_const_switch.rs:+1:9: +1:10
@@ -106,8 +111,8 @@
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+2:2: +2:2
       }
   
--     bb4: {
-+     bb3: {
+-     bb5: {
++     bb4: {
           StorageLive(_13);                // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           _13 = move ((_4 as Err).0: i32); // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_14);                // scope 7 at $SRC_DIR/core/src/result.rs:LL:COL
@@ -126,16 +131,16 @@
 +         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   
--     bb5: {
-+     bb4: {
+-     bb6: {
++     bb5: {
           unreachable;                     // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
       }
   
--     bb6: {
-+     bb5: {
+-     bb7: {
++     bb6: {
           StorageLive(_11);                // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           _11 = move ((_4 as Ok).0: i32);  // scope 5 at $SRC_DIR/core/src/result.rs:LL:COL
           StorageLive(_12);                // scope 6 at $SRC_DIR/core/src/result.rs:LL:COL
@@ -149,7 +154,7 @@
 +         StorageDead(_10);                // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
 +         StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+1:9: +1:10
 +         _5 = discriminant(_3);           // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
-+         switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
++         switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+1:8: +1:10
       }
   }
   
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff b/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff
index de9f45c3d46..28269165e1c 100644
--- a/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff
+++ b/src/test/mir-opt/separate_const_switch.too_complex.ConstProp.diff
@@ -30,7 +30,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
           _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
-          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
       }
   
       bb1: {
@@ -44,12 +44,16 @@
           StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 -         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
--         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+-         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
 +         _8 = const 1_isize;              // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+         switchInt(const 1_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(const 1_isize) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
+      }
+  
+      bb3: {
           StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
           _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
           StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
@@ -60,21 +64,25 @@
           StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
 -         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
--         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+-         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
 +         _8 = const 0_isize;              // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+         switchInt(const 0_isize) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(const 0_isize) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_11);                // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
           _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
           Deinit(_0);                      // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
           discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
           StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+          goto -> bb7;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
       }
   
-      bb4: {
+      bb5: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
+      }
+  
+      bb6: {
           StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
           _9 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
           StorageLive(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
@@ -84,10 +92,10 @@
           discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
           StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
           StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-          goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+          goto -> bb7;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
       }
   
-      bb5: {
+      bb7: {
           StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
       }
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir
index 1009225b733..0ee070619e7 100644
--- a/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir
+++ b/src/test/mir-opt/separate_const_switch.too_complex.PreCodegen.after.mir
@@ -27,7 +27,7 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
     bb0: {
         StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
         _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
-        switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+        switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
     }
 
     bb1: {
@@ -37,10 +37,14 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
         Deinit(_0);                      // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
         discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
         StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+        goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
     }
 
     bb2: {
+        unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
+    }
+
+    bb3: {
         StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
         _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
         StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
@@ -59,10 +63,10 @@ fn too_complex(_1: Result<i32, usize>) -> Option<i32> {
         discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
         StorageDead(_8);                 // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
         StorageDead(_7);                 // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-        goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+        goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
     }
 
-    bb3: {
+    bb4: {
         StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
         return;                          // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
     }
diff --git a/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff b/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
index 3ab1c572aa1..43797908136 100644
--- a/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
+++ b/src/test/mir-opt/separate_const_switch.too_complex.SeparateConstSwitch.diff
@@ -30,7 +30,7 @@
       bb0: {
           StorageLive(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
           _3 = discriminant(_1);           // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
-          switchInt(move _3) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
+          switchInt(move _3) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/separate_const_switch.rs:+6:9: +6:16
       }
   
       bb1: {
@@ -43,12 +43,16 @@
           discriminant(_2) = 1;            // scope 2 at $DIR/separate_const_switch.rs:+8:23: +8:44
           StorageDead(_7);                 // scope 2 at $DIR/separate_const_switch.rs:+8:43: +8:44
           StorageDead(_6);                 // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
--         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
+-         goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+8:43: +8:44
 +         _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
-+         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+6:15: +6:16
+      }
+  
+      bb3: {
           StorageLive(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
           _4 = ((_1 as Ok).0: i32);        // scope 0 at $DIR/separate_const_switch.rs:+7:16: +7:17
           StorageLive(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:44: +7:45
@@ -58,28 +62,33 @@
           discriminant(_2) = 0;            // scope 1 at $DIR/separate_const_switch.rs:+7:22: +7:46
           StorageDead(_5);                 // scope 1 at $DIR/separate_const_switch.rs:+7:45: +7:46
           StorageDead(_4);                 // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
--         goto -> bb3;                     // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
+-         goto -> bb4;                     // scope 0 at $DIR/separate_const_switch.rs:+7:45: +7:46
 -     }
 - 
--     bb3: {
+-     bb4: {
           _8 = discriminant(_2);           // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
--         switchInt(move _8) -> [0_isize: bb5, otherwise: bb4]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
-+         switchInt(move _8) -> [0_isize: bb4, otherwise: bb3]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
+-         switchInt(move _8) -> [0_isize: bb7, 1_isize: bb5, otherwise: bb6]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
++         switchInt(move _8) -> [0_isize: bb6, 1_isize: bb4, otherwise: bb5]; // scope 0 at $DIR/separate_const_switch.rs:+5:5: +10:6
       }
   
--     bb4: {
-+     bb3: {
+-     bb5: {
++     bb4: {
           StorageLive(_11);                // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
           _11 = ((_2 as Break).0: usize);  // scope 0 at $DIR/separate_const_switch.rs:+12:28: +12:29
           Deinit(_0);                      // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
           discriminant(_0) = 0;            // scope 4 at $DIR/separate_const_switch.rs:+12:34: +12:38
           StorageDead(_11);                // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
--         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
-+         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
+-         goto -> bb8;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
++         goto -> bb7;                     // scope 0 at $DIR/separate_const_switch.rs:+12:37: +12:38
       }
   
--     bb5: {
-+     bb4: {
+-     bb6: {
++     bb5: {
+          unreachable;                     // scope 0 at $DIR/separate_const_switch.rs:+5:11: +10:6
+      }
+  
+-     bb7: {
++     bb6: {
           StorageLive(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
           _9 = ((_2 as Continue).0: i32);  // scope 0 at $DIR/separate_const_switch.rs:+11:31: +11:32
           StorageLive(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:42: +11:43
@@ -89,12 +98,12 @@
           discriminant(_0) = 1;            // scope 3 at $DIR/separate_const_switch.rs:+11:37: +11:44
           StorageDead(_10);                // scope 3 at $DIR/separate_const_switch.rs:+11:43: +11:44
           StorageDead(_9);                 // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
--         goto -> bb6;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
-+         goto -> bb5;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
+-         goto -> bb8;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
++         goto -> bb7;                     // scope 0 at $DIR/separate_const_switch.rs:+11:43: +11:44
       }
   
--     bb6: {
-+     bb5: {
+-     bb8: {
++     bb7: {
           StorageDead(_2);                 // scope 0 at $DIR/separate_const_switch.rs:+14:1: +14:2
           return;                          // scope 0 at $DIR/separate_const_switch.rs:+14:2: +14:2
       }
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
index 452cc8a9c26..cff9afc38f0 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyArmIdentity.diff
@@ -23,14 +23,14 @@
               debug t => _9;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           }
           scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
-              debug e => _8;               // in scope 6 at $DIR/simplify-arm.rs:+0:21: +0:22
+              debug e => _8;               // in scope 6 at $DIR/simplify-arm.rs:27:21: 27:22
           }
       }
       scope 3 {
           debug v => _10;                  // in scope 3 at $DIR/simplify-arm.rs:+3:12: +3:13
       }
       scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
-          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:+0:22: +0:23
+          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:23:22: 23:23
       }
   
       bb0: {
@@ -38,7 +38,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+1:19: +1:33
           StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:+1:31: +1:32
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:+1:31: +1:32
-          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:+0:5: +0:6
+          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:24:5: 24:6
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:+1:32: +1:33
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:+1:19: +1:33
           switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:13: +1:33
@@ -72,9 +72,9 @@
           _9 = _6;                         // scope 2 at $DIR/simplify-arm.rs:+2:48: +2:49
           _8 = move _9;                    // scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           StorageDead(_9);                 // scope 2 at $DIR/simplify-arm.rs:+2:49: +2:50
-          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify-arm.rs:+0:9: +0:10
-          Deinit(_0);                      // scope 6 at $DIR/simplify-arm.rs:+0:5: +0:11
-          discriminant(_0) = 1;            // scope 6 at $DIR/simplify-arm.rs:+0:5: +0:11
+          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify-arm.rs:28:9: 28:10
+          Deinit(_0);                      // scope 6 at $DIR/simplify-arm.rs:28:5: 28:11
+          discriminant(_0) = 1;            // scope 6 at $DIR/simplify-arm.rs:28:5: 28:11
           StorageDead(_8);                 // scope 2 at $DIR/simplify-arm.rs:+2:50: +2:51
           StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:+2:50: +2:51
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+4:6: +4:7
diff --git a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
index 5d7d4ba7c3d..9d38b93508c 100644
--- a/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
+++ b/src/test/mir-opt/simplify_arm.id_try.SimplifyBranchSame.diff
@@ -23,14 +23,14 @@
               debug t => _9;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           }
           scope 6 (inlined from_error::<u8, i32>) { // at $DIR/simplify-arm.rs:37:26: 37:51
-              debug e => _8;               // in scope 6 at $DIR/simplify-arm.rs:+0:21: +0:22
+              debug e => _8;               // in scope 6 at $DIR/simplify-arm.rs:27:21: 27:22
           }
       }
       scope 3 {
           debug v => _10;                  // in scope 3 at $DIR/simplify-arm.rs:+3:12: +3:13
       }
       scope 4 (inlined into_result::<u8, i32>) { // at $DIR/simplify-arm.rs:36:19: 36:33
-          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:+0:22: +0:23
+          debug r => _4;                   // in scope 4 at $DIR/simplify-arm.rs:23:22: 23:23
       }
   
       bb0: {
@@ -38,7 +38,7 @@
           StorageLive(_3);                 // scope 0 at $DIR/simplify-arm.rs:+1:19: +1:33
           StorageLive(_4);                 // scope 0 at $DIR/simplify-arm.rs:+1:31: +1:32
           _4 = _1;                         // scope 0 at $DIR/simplify-arm.rs:+1:31: +1:32
-          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:+0:5: +0:6
+          _3 = move _4;                    // scope 4 at $DIR/simplify-arm.rs:24:5: 24:6
           StorageDead(_4);                 // scope 0 at $DIR/simplify-arm.rs:+1:32: +1:33
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify-arm.rs:+1:19: +1:33
           switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify-arm.rs:+1:13: +1:33
@@ -72,9 +72,9 @@
           _9 = _6;                         // scope 2 at $DIR/simplify-arm.rs:+2:48: +2:49
           _8 = move _9;                    // scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           StorageDead(_9);                 // scope 2 at $DIR/simplify-arm.rs:+2:49: +2:50
-          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify-arm.rs:+0:9: +0:10
-          Deinit(_0);                      // scope 6 at $DIR/simplify-arm.rs:+0:5: +0:11
-          discriminant(_0) = 1;            // scope 6 at $DIR/simplify-arm.rs:+0:5: +0:11
+          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify-arm.rs:28:9: 28:10
+          Deinit(_0);                      // scope 6 at $DIR/simplify-arm.rs:28:5: 28:11
+          discriminant(_0) = 1;            // scope 6 at $DIR/simplify-arm.rs:28:5: 28:11
           StorageDead(_8);                 // scope 2 at $DIR/simplify-arm.rs:+2:50: +2:51
           StorageDead(_6);                 // scope 0 at $DIR/simplify-arm.rs:+2:50: +2:51
           StorageDead(_3);                 // scope 0 at $DIR/simplify-arm.rs:+4:6: +4:7
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
index c6895fa41bf..d8e0657c6eb 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.32bit.diff
@@ -16,23 +16,27 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
       }
   
       bb1: {
           ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
           Deinit(_0);                      // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
           discriminant(_0) = 1;            // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+          goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+      }
+  
+      bb3: {
           Deinit(_0);                      // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
           discriminant(_0) = 0;            // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
+          goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
       }
   
-      bb3: {
+      bb4: {
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
index c6895fa41bf..d8e0657c6eb 100644
--- a/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
+++ b/src/test/mir-opt/simplify_locals_removes_unused_discriminant_reads.map.SimplifyLocals.64bit.diff
@@ -16,23 +16,27 @@
   
       bb0: {
           _2 = discriminant(_1);           // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
-          switchInt(move _2) -> [0_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
+          switchInt(move _2) -> [0_isize: bb3, 1_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:5: +1:12
       }
   
       bb1: {
           ((_0 as Some).0: std::boxed::Box<()>) = move ((_1 as Some).0: std::boxed::Box<()>); // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:14: +3:15
           Deinit(_0);                      // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
           discriminant(_0) = 1;            // scope 1 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:20: +3:27
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
+          goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+3:26: +3:27
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+1:11: +1:12
+      }
+  
+      bb3: {
           Deinit(_0);                      // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
           discriminant(_0) = 0;            // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
-          goto -> bb3;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
+          goto -> bb4;                     // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+2:17: +2:21
       }
   
-      bb3: {
+      bb4: {
           return;                          // scope 0 at $DIR/simplify-locals-removes-unused-discriminant-reads.rs:+5:2: +5:2
       }
   }
diff --git a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
index d81d23c1c4c..83b91309be3 100644
--- a/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.DestinationPropagation.diff
@@ -24,7 +24,7 @@
               debug t => _9;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           }
           scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
-              debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:+0:21: +0:22
+              debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:12:21: 12:22
           }
       }
       scope 3 {
@@ -32,8 +32,8 @@
 +         debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:+3:12: +3:13
       }
       scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
--         debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:+0:22: +0:23
-+         debug r => _3;                   // in scope 4 at $DIR/simplify_try.rs:+0:22: +0:23
+-         debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:8:22: 8:23
++         debug r => _3;                   // in scope 4 at $DIR/simplify_try.rs:8:22: 8:23
       }
   
       bb0: {
@@ -41,16 +41,16 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
 -         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
 -         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
--         _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:+0:5: +0:6
+-         _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:9:5: 9:6
 -         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:32: +1:33
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:+1:9: +1:10
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
 +         _3 = _1;                         // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
-+         nop;                             // scope 4 at $DIR/simplify_try.rs:+0:5: +0:6
++         nop;                             // scope 4 at $DIR/simplify_try.rs:9:5: 9:6
 +         nop;                             // scope 0 at $DIR/simplify_try.rs:+1:32: +1:33
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
+          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
       }
   
       bb1: {
@@ -80,6 +80,10 @@
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
+      }
+  
+      bb3: {
           StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
           nop;                             // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
           StorageLive(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:37: +2:50
@@ -87,9 +91,9 @@
           nop;                             // scope 2 at $DIR/simplify_try.rs:+2:48: +2:49
           nop;                             // scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           StorageDead(_9);                 // scope 2 at $DIR/simplify_try.rs:+2:49: +2:50
-          nop;                             // scope 6 at $DIR/simplify_try.rs:+0:9: +0:10
-          Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
-          discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
+          nop;                             // scope 6 at $DIR/simplify_try.rs:13:9: 13:10
+          Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
+          discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
           StorageDead(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:50: +2:51
           StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:50: +2:51
 -         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:+4:6: +4:7
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
index 853b95cc669..e025ae7c551 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyArmIdentity.diff
@@ -23,14 +23,14 @@
               debug t => _9;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           }
           scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
-              debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:+0:21: +0:22
+              debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:12:21: 12:22
           }
       }
       scope 3 {
           debug v => _10;                  // in scope 3 at $DIR/simplify_try.rs:+3:12: +3:13
       }
       scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
-          debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:+0:22: +0:23
+          debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:8:22: 8:23
       }
   
       bb0: {
@@ -38,10 +38,10 @@
           StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
           StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
           _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
-          _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:+0:5: +0:6
+          _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:9:5: 9:6
           StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:32: +1:33
           _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
-          switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
+          switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
       }
   
       bb1: {
@@ -61,6 +61,10 @@
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
+      }
+  
+      bb3: {
           StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
           _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
           StorageLive(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:37: +2:50
@@ -68,9 +72,9 @@
           _9 = _6;                         // scope 2 at $DIR/simplify_try.rs:+2:48: +2:49
           _8 = move _9;                    // scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
           StorageDead(_9);                 // scope 2 at $DIR/simplify_try.rs:+2:49: +2:50
-          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify_try.rs:+0:9: +0:10
-          Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
-          discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
+          ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify_try.rs:13:9: 13:10
+          Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
+          discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
           StorageDead(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:50: +2:51
           StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:50: +2:51
           StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:+4:6: +4:7
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
index 10799cd92dd..eb5af2227ec 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyBranchSame.after.mir
@@ -22,14 +22,14 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
             debug t => _9;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
         }
         scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
-            debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:+0:21: +0:22
+            debug e => _8;               // in scope 6 at $DIR/simplify_try.rs:12:21: 12:22
         }
     }
     scope 3 {
         debug v => _10;                  // in scope 3 at $DIR/simplify_try.rs:+3:12: +3:13
     }
     scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
-        debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:+0:22: +0:23
+        debug r => _4;                   // in scope 4 at $DIR/simplify_try.rs:8:22: 8:23
     }
 
     bb0: {
@@ -37,10 +37,10 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
         StorageLive(_3);                 // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
         _4 = _1;                         // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
-        _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:+0:5: +0:6
+        _3 = move _4;                    // scope 4 at $DIR/simplify_try.rs:9:5: 9:6
         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:+1:32: +1:33
         _5 = discriminant(_3);           // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
-        switchInt(move _5) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
+        switchInt(move _5) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
     }
 
     bb1: {
@@ -60,6 +60,10 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
     }
 
     bb2: {
+        unreachable;                     // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
+    }
+
+    bb3: {
         StorageLive(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
         _6 = ((_3 as Err).0: i32);       // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
         StorageLive(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:37: +2:50
@@ -67,9 +71,9 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
         _9 = _6;                         // scope 2 at $DIR/simplify_try.rs:+2:48: +2:49
         _8 = move _9;                    // scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
         StorageDead(_9);                 // scope 2 at $DIR/simplify_try.rs:+2:49: +2:50
-        ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify_try.rs:+0:9: +0:10
-        Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
-        discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
+        ((_0 as Err).0: i32) = move _8;  // scope 6 at $DIR/simplify_try.rs:13:9: 13:10
+        Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
+        discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
         StorageDead(_8);                 // scope 2 at $DIR/simplify_try.rs:+2:50: +2:51
         StorageDead(_6);                 // scope 0 at $DIR/simplify_try.rs:+2:50: +2:51
         StorageDead(_3);                 // scope 0 at $DIR/simplify_try.rs:+4:6: +4:7
diff --git a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
index f8c9034f77c..1efa8a67e5c 100644
--- a/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/simplify_try.try_identity.SimplifyLocals.after.mir
@@ -17,20 +17,20 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
             debug t => _6;               // in scope 5 at $SRC_DIR/core/src/convert/mod.rs:LL:COL
         }
         scope 6 (inlined from_error::<u32, i32>) { // at $DIR/simplify_try.rs:22:26: 22:51
-            debug e => _5;               // in scope 6 at $DIR/simplify_try.rs:+0:21: +0:22
+            debug e => _5;               // in scope 6 at $DIR/simplify_try.rs:12:21: 12:22
         }
     }
     scope 3 {
         debug v => ((_0 as Ok).0: u32);  // in scope 3 at $DIR/simplify_try.rs:+3:12: +3:13
     }
     scope 4 (inlined into_result::<u32, i32>) { // at $DIR/simplify_try.rs:21:19: 21:33
-        debug r => _2;                   // in scope 4 at $DIR/simplify_try.rs:+0:22: +0:23
+        debug r => _2;                   // in scope 4 at $DIR/simplify_try.rs:8:22: 8:23
     }
 
     bb0: {
         _2 = _1;                         // scope 0 at $DIR/simplify_try.rs:+1:31: +1:32
         _3 = discriminant(_2);           // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
-        switchInt(move _3) -> [0_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
+        switchInt(move _3) -> [0_isize: bb1, 1_isize: bb3, otherwise: bb2]; // scope 0 at $DIR/simplify_try.rs:+1:13: +1:33
     }
 
     bb1: {
@@ -41,12 +41,16 @@ fn try_identity(_1: Result<u32, i32>) -> Result<u32, i32> {
     }
 
     bb2: {
+        unreachable;                     // scope 0 at $DIR/simplify_try.rs:+1:19: +1:33
+    }
+
+    bb3: {
         StorageLive(_4);                 // scope 0 at $DIR/simplify_try.rs:+2:13: +2:14
         StorageLive(_5);                 // scope 2 at $DIR/simplify_try.rs:+2:37: +2:50
         StorageLive(_6);                 // scope 2 at $DIR/simplify_try.rs:+2:48: +2:49
         StorageDead(_6);                 // scope 2 at $DIR/simplify_try.rs:+2:49: +2:50
-        Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
-        discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:+0:5: +0:11
+        Deinit(_0);                      // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
+        discriminant(_0) = 1;            // scope 6 at $DIR/simplify_try.rs:13:5: 13:11
         StorageDead(_5);                 // scope 2 at $DIR/simplify_try.rs:+2:50: +2:51
         StorageDead(_4);                 // scope 0 at $DIR/simplify_try.rs:+2:50: +2:51
         return;                          // scope 0 at $DIR/simplify_try.rs:+6:2: +6:2
diff --git a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir
index bc9e9142071..4127a0c9555 100644
--- a/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir
+++ b/src/test/mir-opt/storage_live_dead_in_statics.XXX.mir_map.0.mir
@@ -198,6 +198,6 @@ static XXX: &Foo = {
         _0 = &(*_1);                     // scope 0 at $DIR/storage_live_dead_in_statics.rs:+0:28: +18:2
         StorageDead(_5);                 // scope 0 at $DIR/storage_live_dead_in_statics.rs:+18:1: +18:2
         StorageDead(_1);                 // scope 0 at $DIR/storage_live_dead_in_statics.rs:+18:1: +18:2
-        return;                          // scope 0 at $DIR/storage_live_dead_in_statics.rs:+0:1: +0:25
+        return;                          // scope 0 at $DIR/storage_live_dead_in_statics.rs:+0:1: +18:2
     }
 }
diff --git a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
index 34c38d24c54..6ed53643f4b 100644
--- a/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
+++ b/src/test/mir-opt/uninhabited_enum.process_never.SimplifyLocals.after.mir
@@ -11,8 +11,6 @@ fn process_never(_1: *const !) -> () {
     }
 
     bb0: {
-        StorageLive(_2);                 // scope 0 at $DIR/uninhabited-enum.rs:+1:8: +1:14
-        StorageDead(_2);                 // scope 0 at $DIR/uninhabited-enum.rs:+2:1: +2:2
         unreachable;                     // scope 0 at $DIR/uninhabited-enum.rs:+0:39: +2:2
     }
 }
diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index 3d860dac361..4aa5ba007f1 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -18,6 +18,10 @@ fn main() -> () {
         Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
         _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+        switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+    }
+
+    bb1: {
         StorageLive(_5);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:21: +4:24
         _5 = const "C";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:21: +4:24
                                          // mir::Constant
@@ -32,10 +36,14 @@ fn main() -> () {
         Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
         _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-        switchInt(move _8) -> [4_isize: bb2, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+        switchInt(move _8) -> [4_isize: bb5, 5_isize: bb3, otherwise: bb4]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
     }
 
-    bb1: {
+    bb2: {
+        unreachable;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+    }
+
+    bb3: {
         StorageLive(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
         _9 = const "E";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
                                          // mir::Constant
@@ -43,18 +51,22 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
         _6 = &(*_9);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
         StorageDead(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
-        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
+        goto -> bb6;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
     }
 
-    bb2: {
+    bb4: {
+        unreachable;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+    }
+
+    bb5: {
         _6 = const "D";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
                                          // mir::Constant
                                          // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
-        goto -> bb3;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
+        goto -> bb6;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
     }
 
-    bb3: {
+    bb6: {
         StorageDead(_7);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+10:6: +10:7
         StorageDead(_6);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+10:6: +10:7
         _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching.rs:+0:11: +11:2
diff --git a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
index 023f6ae32b0..c3d356aedb2 100644
--- a/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_enum_branching.main.UninhabitedEnumBranching.diff
@@ -19,8 +19,8 @@
           Deinit(_2);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           discriminant(_2) = 2;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
           _3 = discriminant(_2);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
--         switchInt(move _3) -> [0_isize: bb2, 1_isize: bb3, otherwise: bb1]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
-+         switchInt(move _3) -> bb1;       // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
+-         switchInt(move _3) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
++         switchInt(move _3) -> [2_isize: bb1, otherwise: bb2]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:5: +1:19
       }
   
       bb1: {
@@ -31,18 +31,22 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _1 = &(*_5);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:21: +4:24
           StorageDead(_5);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:23: +4:24
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:23: +4:24
+          goto -> bb5;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+4:23: +4:24
       }
   
       bb2: {
+          unreachable;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+1:11: +1:19
+      }
+  
+      bb3: {
           _1 = const "A(Empty)";           // scope 0 at $DIR/uninhabited_enum_branching.rs:+2:24: +2:34
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching.rs:21:24: 21:34
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+2:24: +2:34
+          goto -> bb5;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+2:24: +2:34
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_4);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:24: +3:34
           _4 = const "B(Empty)";           // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:24: +3:34
                                            // mir::Constant
@@ -50,10 +54,10 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _1 = &(*_4);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:24: +3:34
           StorageDead(_4);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:33: +3:34
-          goto -> bb4;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:33: +3:34
+          goto -> bb5;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+3:33: +3:34
       }
   
-      bb4: {
+      bb5: {
           StorageDead(_2);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
           StorageDead(_1);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+5:6: +5:7
           StorageLive(_6);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +10:6
@@ -61,10 +65,10 @@
           Deinit(_7);                      // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           discriminant(_7) = 0;            // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
           _8 = discriminant(_7);           // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
-          switchInt(move _8) -> [4_isize: bb6, otherwise: bb5]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
+          switchInt(move _8) -> [4_isize: bb8, 5_isize: bb6, otherwise: bb7]; // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:5: +7:19
       }
   
-      bb5: {
+      bb6: {
           StorageLive(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
           _9 = const "E";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
                                            // mir::Constant
@@ -72,18 +76,22 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _6 = &(*_9);                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:21: +9:24
           StorageDead(_9);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
-          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
+          goto -> bb9;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+9:23: +9:24
       }
   
-      bb6: {
+      bb7: {
+          unreachable;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+7:11: +7:19
+      }
+  
+      bb8: {
           _6 = const "D";                  // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching.rs:27:21: 27:24
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
-          goto -> bb7;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
+          goto -> bb9;                     // scope 0 at $DIR/uninhabited_enum_branching.rs:+8:21: +8:24
       }
   
-      bb7: {
+      bb9: {
           StorageDead(_7);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+10:6: +10:7
           StorageDead(_6);                 // scope 0 at $DIR/uninhabited_enum_branching.rs:+10:6: +10:7
           _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching.rs:+0:11: +11:2
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
index a5e7f526928..ec5612ad767 100644
--- a/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
+++ b/src/test/mir-opt/uninhabited_enum_branching2.main.SimplifyCfg-after-uninhabited-enum-branching.after.mir
@@ -32,7 +32,7 @@ fn main() -> () {
         StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
         _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
-        switchInt(move _5) -> [2_isize: bb2, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+        switchInt(move _5) -> [2_isize: bb3, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
     }
 
     bb1: {
@@ -43,10 +43,14 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
         _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:21: +7:24
         StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
-        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
+        goto -> bb4;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
     }
 
     bb2: {
+        unreachable;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
+    }
+
+    bb3: {
         StorageLive(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
         _7 = const "C";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
                                          // mir::Constant
@@ -54,18 +58,18 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
         _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
         StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
-        goto -> bb3;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
+        goto -> bb4;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
     }
 
-    bb3: {
+    bb4: {
         StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
         StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
         StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
         _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
-        switchInt(move _10) -> [2_isize: bb5, otherwise: bb4]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+        switchInt(move _10) -> [2_isize: bb7, 3_isize: bb5, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
     }
 
-    bb4: {
+    bb5: {
         StorageLive(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
         _13 = const "D";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
                                          // mir::Constant
@@ -73,10 +77,14 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
         _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
         StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
-        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
+        goto -> bb8;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
     }
 
-    bb5: {
+    bb6: {
+        unreachable;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
+    }
+
+    bb7: {
         StorageLive(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
         _12 = const "C";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
                                          // mir::Constant
@@ -84,10 +92,10 @@ fn main() -> () {
                                          // + literal: Const { ty: &str, val: Value(Slice(..)) }
         _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
         StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
-        goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
+        goto -> bb8;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
     }
 
-    bb6: {
+    bb8: {
         StorageDead(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+15:6: +15:7
         _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching2.rs:+0:11: +16:2
         StorageDead(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:+16:1: +16:2
diff --git a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
index 157518491f1..77b358a4801 100644
--- a/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
+++ b/src/test/mir-opt/uninhabited_enum_branching2.main.UninhabitedEnumBranching.diff
@@ -33,8 +33,8 @@
           StorageLive(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _4 = &(_1.1: Test1);             // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
           _5 = discriminant((*_4));        // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
--         switchInt(move _5) -> [0_isize: bb2, 1_isize: bb3, 2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
-+         switchInt(move _5) -> [2_isize: bb4, otherwise: bb1]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
+-         switchInt(move _5) -> [0_isize: bb3, 1_isize: bb4, 2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
++         switchInt(move _5) -> [2_isize: bb5, 3_isize: bb1, otherwise: bb2]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:5: +3:22
       }
   
       bb1: {
@@ -45,18 +45,22 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _3 = &(*_8);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:21: +7:24
           StorageDead(_8);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
+          goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+7:23: +7:24
       }
   
       bb2: {
+          unreachable;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+3:11: +3:22
+      }
+  
+      bb3: {
           _3 = const "A(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:+4:24: +4:34
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching2.rs:22:24: 22:34
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+4:24: +4:34
+          goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+4:24: +4:34
       }
   
-      bb3: {
+      bb4: {
           StorageLive(_6);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:24: +5:34
           _6 = const "B(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:24: +5:34
                                            // mir::Constant
@@ -64,10 +68,10 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _3 = &(*_6);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:24: +5:34
           StorageDead(_6);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:33: +5:34
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:33: +5:34
+          goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+5:33: +5:34
       }
   
-      bb4: {
+      bb5: {
           StorageLive(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
           _7 = const "C";                  // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
                                            // mir::Constant
@@ -75,19 +79,19 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _3 = &(*_7);                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:21: +6:24
           StorageDead(_7);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
-          goto -> bb5;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
+          goto -> bb6;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+6:23: +6:24
       }
   
-      bb5: {
+      bb6: {
           StorageDead(_4);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
           StorageDead(_3);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+8:6: +8:7
           StorageLive(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +15:6
           _10 = discriminant((_1.1: Test1)); // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
--         switchInt(move _10) -> [0_isize: bb7, 1_isize: bb8, 2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
-+         switchInt(move _10) -> [2_isize: bb9, otherwise: bb6]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
+-         switchInt(move _10) -> [0_isize: bb9, 1_isize: bb10, 2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
++         switchInt(move _10) -> [2_isize: bb11, 3_isize: bb7, otherwise: bb8]; // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:5: +10:21
       }
   
-      bb6: {
+      bb7: {
           StorageLive(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
           _13 = const "D";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
                                            // mir::Constant
@@ -95,18 +99,22 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _9 = &(*_13);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:21: +14:24
           StorageDead(_13);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
+          goto -> bb12;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+14:23: +14:24
       }
   
-      bb7: {
+      bb8: {
+          unreachable;                     // scope 1 at $DIR/uninhabited_enum_branching2.rs:+10:11: +10:21
+      }
+  
+      bb9: {
           _9 = const "A(Empty)";           // scope 1 at $DIR/uninhabited_enum_branching2.rs:+11:24: +11:34
                                            // mir::Constant
                                            // + span: $DIR/uninhabited_enum_branching2.rs:29:24: 29:34
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+11:24: +11:34
+          goto -> bb12;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+11:24: +11:34
       }
   
-      bb8: {
+      bb10: {
           StorageLive(_11);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:24: +12:34
           _11 = const "B(Empty)";          // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:24: +12:34
                                            // mir::Constant
@@ -114,10 +122,10 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _9 = &(*_11);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:24: +12:34
           StorageDead(_11);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:33: +12:34
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:33: +12:34
+          goto -> bb12;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+12:33: +12:34
       }
   
-      bb9: {
+      bb11: {
           StorageLive(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
           _12 = const "C";                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
                                            // mir::Constant
@@ -125,10 +133,10 @@
                                            // + literal: Const { ty: &str, val: Value(Slice(..)) }
           _9 = &(*_12);                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:21: +13:24
           StorageDead(_12);                // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
-          goto -> bb10;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
+          goto -> bb12;                    // scope 1 at $DIR/uninhabited_enum_branching2.rs:+13:23: +13:24
       }
   
-      bb10: {
+      bb12: {
           StorageDead(_9);                 // scope 1 at $DIR/uninhabited_enum_branching2.rs:+15:6: +15:7
           _0 = const ();                   // scope 0 at $DIR/uninhabited_enum_branching2.rs:+0:11: +16:2
           StorageDead(_1);                 // scope 0 at $DIR/uninhabited_enum_branching2.rs:+16:1: +16:2
diff --git a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
index 52d9543e978..9cd4b8ccf33 100644
--- a/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable.main.UnreachablePropagation.diff
@@ -28,7 +28,7 @@
       bb1: {
           _2 = discriminant(_1);           // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
 -         switchInt(move _2) -> [1_isize: bb2, otherwise: bb6]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
-+         goto -> bb2;                     // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
++         switchInt(move _2) -> [1_isize: bb2, otherwise: bb3]; // scope 1 at $DIR/unreachable.rs:+1:12: +1:20
       }
   
       bb2: {
@@ -39,9 +39,10 @@
 -         StorageLive(_6);                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 -         _6 = const true;                 // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
 -         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
--     }
-- 
--     bb3: {
++         unreachable;                     // scope 2 at $DIR/unreachable.rs:+4:12: +4:16
+      }
+  
+      bb3: {
 -         _4 = const 21_i32;               // scope 2 at $DIR/unreachable.rs:+5:13: +5:20
 -         _5 = const ();                   // scope 2 at $DIR/unreachable.rs:+4:17: +6:10
 -         goto -> bb5;                     // scope 2 at $DIR/unreachable.rs:+4:9: +8:10
diff --git a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
index 3d31553c44a..afd6b00aac3 100644
--- a/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
+++ b/src/test/mir-opt/unreachable_diverging.main.UnreachablePropagation.diff
@@ -29,8 +29,7 @@
   
       bb1: {
           _3 = discriminant(_2);           // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
--         switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
-+         switchInt(move _3) -> [1_isize: bb2, otherwise: bb5]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
+          switchInt(move _3) -> [1_isize: bb2, otherwise: bb6]; // scope 2 at $DIR/unreachable_diverging.rs:+2:12: +2:22
       }
   
       bb2: {
@@ -39,13 +38,11 @@
           StorageLive(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
           StorageLive(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
           _6 = _1;                         // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
--         switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
-+         goto -> bb3;                     // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
+          switchInt(move _6) -> [false: bb4, otherwise: bb3]; // scope 2 at $DIR/unreachable_diverging.rs:+3:12: +3:13
       }
   
       bb3: {
--         _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27
-+         _5 = loop_forever() -> bb4;      // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27
+          _5 = loop_forever() -> bb5;      // scope 2 at $DIR/unreachable_diverging.rs:+4:13: +4:27
                                            // mir::Constant
                                            // + span: $DIR/unreachable_diverging.rs:16:13: 16:25
                                            // + literal: Const { ty: fn() {loop_forever}, val: Value(<ZST>) }
@@ -54,17 +51,17 @@
       bb4: {
 -         _5 = const ();                   // scope 2 at $DIR/unreachable_diverging.rs:+5:10: +5:10
 -         goto -> bb5;                     // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
--     }
-- 
--     bb5: {
-          StorageDead(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:+5:9: +5:10
-          StorageDead(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:+5:9: +5:10
-          StorageLive(_7);                 // scope 2 at $DIR/unreachable_diverging.rs:+6:9: +6:22
++         unreachable;                     // scope 2 at $DIR/unreachable_diverging.rs:+3:9: +5:10
+      }
+  
+      bb5: {
+-         StorageDead(_6);                 // scope 2 at $DIR/unreachable_diverging.rs:+5:9: +5:10
+-         StorageDead(_5);                 // scope 2 at $DIR/unreachable_diverging.rs:+5:9: +5:10
+-         StorageLive(_7);                 // scope 2 at $DIR/unreachable_diverging.rs:+6:9: +6:22
           unreachable;                     // scope 2 at $DIR/unreachable_diverging.rs:+6:15: +6:19
       }
   
--     bb6: {
-+     bb5: {
+      bb6: {
           _0 = const ();                   // scope 1 at $DIR/unreachable_diverging.rs:+7:6: +7:6
           StorageDead(_1);                 // scope 0 at $DIR/unreachable_diverging.rs:+8:1: +8:2
           StorageDead(_2);                 // scope 0 at $DIR/unreachable_diverging.rs:+8:1: +8:2
diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir
index f7bc8d58f48..e2633f61b5f 100644
--- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir
+++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.32bit.mir
@@ -5,6 +5,6 @@ const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 =
 
     bb0: {
         _0 = const 2_i32;                // scope 0 at $DIR/unusual-item-types.rs:+0:38: +0:39
-        return;                          // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:35
+        return;                          // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:39
     }
 }
diff --git a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir
index f7bc8d58f48..e2633f61b5f 100644
--- a/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir
+++ b/src/test/mir-opt/unusual_item_types.{impl#0}-ASSOCIATED_CONSTANT.mir_map.0.64bit.mir
@@ -5,6 +5,6 @@ const <impl at $DIR/unusual-item-types.rs:9:1: 9:7>::ASSOCIATED_CONSTANT: i32 =
 
     bb0: {
         _0 = const 2_i32;                // scope 0 at $DIR/unusual-item-types.rs:+0:38: +0:39
-        return;                          // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:35
+        return;                          // scope 0 at $DIR/unusual-item-types.rs:+0:5: +0:39
     }
 }
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
index 7ae0e978808..732de652627 100644
--- a/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.doctest.txt
@@ -23,12 +23,6 @@
    22|      1|//! ```
    23|      2|//! #[derive(Debug, PartialEq)]
                        ^1
-  ------------------
-  | Unexecuted instantiation: <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::ne
-  ------------------
-  | <rust_out::main::_doctest_main____coverage_doctest_rs_22_0::SomeError as core::cmp::PartialEq>::eq:
-  |   23|      2|//! #[derive(Debug, PartialEq)]
-  ------------------
    24|      1|//! struct SomeError {
    25|      1|//!     msg: String,
    26|      1|//! }
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
index de32c88b725..25c74ab2e70 100644
--- a/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-83601.txt
@@ -2,12 +2,6 @@
     2|       |
     3|      3|#[derive(Debug, PartialEq, Eq)]
                               ^2
-  ------------------
-  | <issue_83601::Foo as core::cmp::PartialEq>::eq:
-  |    3|      2|#[derive(Debug, PartialEq, Eq)]
-  ------------------
-  | Unexecuted instantiation: <issue_83601::Foo as core::cmp::PartialEq>::ne
-  ------------------
     4|       |struct Foo(u32);
     5|       |
     6|      1|fn main() {
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
index f24f7c69404..4a60432c14c 100644
--- a/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.issue-84561.txt
@@ -2,12 +2,6 @@
     2|       |
     3|       |// expect-exit-status-101
     4|     21|#[derive(PartialEq, Eq)]
-  ------------------
-  | <issue_84561::Foo as core::cmp::PartialEq>::eq:
-  |    4|     21|#[derive(PartialEq, Eq)]
-  ------------------
-  | Unexecuted instantiation: <issue_84561::Foo as core::cmp::PartialEq>::ne
-  ------------------
     5|       |struct Foo(u32);
     6|      1|fn test3() {
     7|      1|    let is_true = std::env::args().len() == 1;
diff --git a/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
index fc266653349..a77175af663 100644
--- a/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
+++ b/src/test/run-make/coverage-reports/expected_show_coverage.partial_eq.txt
@@ -3,11 +3,6 @@
     3|       |
     4|      2|#[derive(Clone, Debug, PartialEq, Eq, PartialOrd, Ord)]
                        ^0            ^0      ^0     ^1       ^1 ^0^0
-  ------------------
-  | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::ne
-  ------------------
-  | Unexecuted instantiation: <partial_eq::Version as core::cmp::PartialEq>::eq
-  ------------------
     5|       |pub struct Version {
     6|       |    major: usize,
     7|       |    minor: usize,
diff --git a/src/test/rustdoc-gui/pocket-menu.goml b/src/test/rustdoc-gui/pocket-menu.goml
index 782526e29f4..71d514648ba 100644
--- a/src/test/rustdoc-gui/pocket-menu.goml
+++ b/src/test/rustdoc-gui/pocket-menu.goml
@@ -56,7 +56,7 @@ reload:
 click: "#help-button"
 assert-css: (
     "#help-button .popover",
-    {"display": "block", "border-color": "rgb(210, 210, 210)"},
+    {"display": "block", "border-color": "rgb(224, 224, 224)"},
 )
 compare-elements-css: ("#help-button .popover", "#help-button .top", ["border-color"])
 compare-elements-css: ("#help-button .popover", "#help-button .bottom", ["border-color"])
diff --git a/src/test/rustdoc-gui/search-filter.goml b/src/test/rustdoc-gui/search-filter.goml
index b12eddfd12a..35d7ca480ca 100644
--- a/src/test/rustdoc-gui/search-filter.goml
+++ b/src/test/rustdoc-gui/search-filter.goml
@@ -69,7 +69,7 @@ click: "#settings-menu"
 wait-for: "#settings"
 click: "#theme-dark"
 wait-for-css: ("#crate-search", {
-    "border": "1px solid rgb(210, 210, 210)",
+    "border": "1px solid rgb(224, 224, 224)",
     "color": "rgb(221, 221, 221)",
     "background-color": "rgb(53, 53, 53)",
 })
diff --git a/src/test/rustdoc-gui/search-form-elements.goml b/src/test/rustdoc-gui/search-form-elements.goml
new file mode 100644
index 00000000000..c35a86ccd1c
--- /dev/null
+++ b/src/test/rustdoc-gui/search-form-elements.goml
@@ -0,0 +1,243 @@
+// This test ensures that the elements in ".search-form" have the expected display.
+goto: file://|DOC_PATH|/test_docs/index.html
+show-text: true
+
+// Ayu theme
+local-storage: {
+    "rustdoc-theme": "ayu",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(92, 103, 115)",
+        "background-color": "rgb(20, 25, 32)",
+        "color": "rgb(255, 255, 255)",
+    },
+)
+focus: ".search-input"
+// Nothing should change.
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(92, 103, 115)",
+        "background-color": "rgb(20, 25, 32)",
+        "color": "rgb(255, 255, 255)",
+    },
+)
+
+assert-css: (
+    "#help-button",
+    {"border-color": "rgb(197, 197, 197)"},
+)
+assert-css: (
+    "#help-button > button",
+    {
+        "color": "rgb(255, 255, 255)",
+        "border-color": "rgb(92, 103, 115)",
+        "background-color": "rgb(20, 25, 32)",
+    },
+)
+move-cursor-to: "#help-button"
+assert-css: (
+    "#help-button:hover",
+    {"border-color": "rgb(197, 197, 197)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#help-button:hover > button",
+    {
+        "color": "rgb(255, 255, 255)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(20, 25, 32)",
+    },
+)
+
+assert-css: (
+    "#settings-menu",
+    {"border-color": "rgb(197, 197, 197)"},
+)
+assert-css: (
+    "#settings-menu > a",
+    {
+        "color": "rgb(255, 255, 255)",
+        "border-color": "rgb(92, 103, 115)",
+        "background-color": "rgb(20, 25, 32)",
+    },
+)
+move-cursor-to: "#settings-menu"
+assert-css: (
+    "#settings-menu:hover",
+    {"border-color": "rgb(197, 197, 197)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#settings-menu:hover > a",
+    {
+        "color": "rgb(255, 255, 255)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(20, 25, 32)",
+    },
+)
+
+// Dark theme
+local-storage: {
+    "rustdoc-theme": "dark",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(240, 240, 240)",
+        "background-color": "rgb(240, 240, 240)",
+        "color": "rgb(17, 17, 17)",
+    },
+)
+focus: ".search-input"
+// Only "border-color" should change.
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(0, 141, 253)",
+        "background-color": "rgb(240, 240, 240)",
+        "color": "rgb(17, 17, 17)",
+    },
+)
+
+assert-css: (
+    "#help-button",
+    {"border-color": "rgb(221, 221, 221)"},
+)
+assert-css: (
+    "#help-button > button",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(240, 240, 240)",
+    },
+)
+move-cursor-to: "#help-button"
+assert-css: (
+    "#help-button:hover",
+    {"border-color": "rgb(221, 221, 221)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#help-button:hover > button",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(255, 185, 0)",
+        "background-color": "rgb(240, 240, 240)",
+    },
+)
+
+assert-css: (
+    "#settings-menu",
+    {"border-color": "rgb(221, 221, 221)"},
+)
+assert-css: (
+    "#settings-menu > a",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(240, 240, 240)",
+    },
+)
+move-cursor-to: "#settings-menu"
+assert-css: (
+    "#settings-menu:hover",
+    {"border-color": "rgb(221, 221, 221)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#settings-menu:hover > a",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(255, 185, 0)",
+        "background-color": "rgb(240, 240, 240)",
+    },
+)
+
+// Light theme
+local-storage: {
+    "rustdoc-theme": "light",
+    "rustdoc-use-system-theme": "false",
+}
+reload:
+
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(255, 255, 255)",
+        "color": "rgb(0, 0, 0)",
+    },
+)
+focus: ".search-input"
+// Nothing should change.
+assert-css: (
+    ".search-input",
+    {
+        "border-color": "rgb(102, 175, 233)",
+        "background-color": "rgb(255, 255, 255)",
+        "color": "rgb(0, 0, 0)",
+    },
+)
+
+assert-css: (
+    "#help-button",
+    {"border-color": "rgb(0, 0, 0)"},
+)
+assert-css: (
+    "#help-button > button",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(255, 255, 255)",
+    },
+)
+move-cursor-to: "#help-button"
+assert-css: (
+    "#help-button:hover",
+    {"border-color": "rgb(0, 0, 0)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#help-button:hover > button",
+    {
+        "color": "rgb(0, 0, 0)",
+        "border-color": "rgb(113, 113, 113)",
+        "background-color": "rgb(255, 255, 255)",
+    },
+)
+
+assert-css: (
+    "#settings-menu",
+    {"border-color": "rgb(0, 0, 0)"},
+)
+assert-css: (
+    "#settings-menu > a",
+    {
+        "color": "rgb(56, 115, 173)",
+        "border-color": "rgb(224, 224, 224)",
+        "background-color": "rgb(255, 255, 255)",
+    },
+)
+move-cursor-to: "#settings-menu"
+assert-css: (
+    "#settings-menu:hover",
+    {"border-color": "rgb(0, 0, 0)"},
+)
+// Only "border-color" should change.
+assert-css: (
+    "#settings-menu:hover > a",
+    {
+        "color": "rgb(56, 115, 173)",
+        "border-color": "rgb(113, 113, 113)",
+        "background-color": "rgb(255, 255, 255)",
+    },
+)
diff --git a/src/test/rustdoc-gui/search-input.goml b/src/test/rustdoc-gui/search-input.goml
index 44123b702df..6903e1a1bf5 100644
--- a/src/test/rustdoc-gui/search-input.goml
+++ b/src/test/rustdoc-gui/search-input.goml
@@ -3,9 +3,8 @@ goto: file://|DOC_PATH|/test_docs/index.html
 local-storage: {"rustdoc-use-system-theme": "false", "rustdoc-theme": "dark"}
 reload:
 
-assert-css: (".search-input", {"border-color": "rgb(224, 224, 224)"})
+assert-css: (".search-input", {"border-color": "rgb(240, 240, 240)"})
 click: ".search-input"
-focus: ".search-input"
 assert-css: (".search-input", {"border-color": "rgb(0, 141, 253)"})
 
 local-storage: {"rustdoc-theme": "light"}
@@ -18,6 +17,6 @@ assert-css: (".search-input", {"border-color": "rgb(102, 175, 233)"})
 local-storage: {"rustdoc-theme": "ayu"}
 reload:
 
-assert-css: (".search-input", {"border-color": "rgb(66, 76, 87)"})
+assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
 click: ".search-input"
-assert-css: (".search-input", {"border-color": "rgb(66, 76, 87)"})
+assert-css: (".search-input", {"border-color": "rgb(92, 103, 115)"})
diff --git a/src/test/rustdoc/issue-100679-sidebar-links-deref.rs b/src/test/rustdoc/issue-100679-sidebar-links-deref.rs
new file mode 100644
index 00000000000..f09d2320609
--- /dev/null
+++ b/src/test/rustdoc/issue-100679-sidebar-links-deref.rs
@@ -0,0 +1,30 @@
+#![crate_name="foo"]
+
+pub struct Vec;
+
+pub struct Slice;
+
+impl std::ops::Deref for Vec {
+    type Target = Slice;
+    fn deref(&self) -> &Slice {
+        &Slice
+    }
+}
+
+// @has foo/struct.Vec.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty"]' \
+//          "is_empty"
+impl Vec {
+    pub fn is_empty(&self) -> bool {
+        true
+    }
+}
+
+// @has foo/struct.Vec.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty-1"]' \
+//          "is_empty"
+// @has foo/struct.Slice.html '//*[@class="sidebar-elems"]//section//li/a[@href="#method.is_empty"]' \
+//          "is_empty"
+impl Slice {
+    pub fn is_empty(&self) -> bool {
+        true
+    }
+}
diff --git a/src/test/rustdoc/issue-32374.rs b/src/test/rustdoc/issue-32374.rs
index 9c585497d35..8d2c27cf3d7 100644
--- a/src/test/rustdoc/issue-32374.rs
+++ b/src/test/rustdoc/issue-32374.rs
@@ -8,20 +8,24 @@
 //      'Experimental'
 // @matches issue_32374/index.html '//*[@class="item-right docblock-short"]/text()' 'Docs'
 
-// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]' \
-//      '👎 Deprecated since 1.0.0: text'
+// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' '👎'
+// @has issue_32374/struct.T.html '//*[@class="stab deprecated"]/span' \
+//      'Deprecated since 1.0.0: text'
 // @hasraw - '<code>test</code>&nbsp;<a href="https://issue_url/32374">#32374</a>'
+// @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' '🔬'
 // @matches issue_32374/struct.T.html '//*[@class="stab unstable"]' \
-//      '🔬 This is a nightly-only experimental API. \(test\s#32374\)$'
+//     'This is a nightly-only experimental API. \(test\s#32374\)$'
 /// Docs
 #[deprecated(since = "1.0.0", note = "text")]
 #[unstable(feature = "test", issue = "32374")]
 pub struct T;
 
+// @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' '👎'
 // @has issue_32374/struct.U.html '//*[@class="stab deprecated"]' \
-//      '👎 Deprecated since 1.0.0: deprecated'
+//     'Deprecated since 1.0.0: deprecated'
+// @has issue_32374/struct.U.html '//*[@class="stab unstable"]' '🔬'
 // @has issue_32374/struct.U.html '//*[@class="stab unstable"]' \
-//      '🔬 This is a nightly-only experimental API. (test #32374)'
+//     'This is a nightly-only experimental API. (test #32374)'
 #[deprecated(since = "1.0.0", note = "deprecated")]
 #[unstable(feature = "test", issue = "32374", reason = "unstable")]
 pub struct U;
diff --git a/src/test/rustdoc/issue-41783.codeblock.html b/src/test/rustdoc/issue-41783.codeblock.html
index b919935e4b4..89987491d1b 100644
--- a/src/test/rustdoc/issue-41783.codeblock.html
+++ b/src/test/rustdoc/issue-41783.codeblock.html
@@ -1,5 +1,5 @@
 <code># single
 ## double
 ### triple
-<span class="attribute">#[outer]</span>
-<span class="attribute">#![inner]</span></code>
\ No newline at end of file
+<span class="attribute">#[outer]
+#![inner]</span></code>
diff --git a/src/test/rustdoc/issue-41783.rs b/src/test/rustdoc/issue-41783.rs
index d6771602879..87267a750c6 100644
--- a/src/test/rustdoc/issue-41783.rs
+++ b/src/test/rustdoc/issue-41783.rs
@@ -1,8 +1,10 @@
 // @has issue_41783/struct.Foo.html
 // @!hasraw - 'space'
 // @!hasraw - 'comment'
-// @hasraw - '<span class="attribute">#[outer]</span>'
-// @hasraw - '<span class="attribute">#![inner]</span>'
+// @hasraw - '<span class="attribute">#[outer]'
+// @!hasraw - '<span class="attribute">#[outer]</span>'
+// @hasraw - '#![inner]</span>'
+// @!hasraw - '<span class="attribute">#![inner]</span>'
 // @snapshot 'codeblock' - '//*[@class="rustdoc-toggle top-doc"]/*[@class="docblock"]//pre/code'
 
 /// ```no_run
diff --git a/src/test/ui-fulldeps/internal-lints/diagnostics.rs b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
index d6f63d44ba6..33192433bbf 100644
--- a/src/test/ui-fulldeps/internal-lints/diagnostics.rs
+++ b/src/test/ui-fulldeps/internal-lints/diagnostics.rs
@@ -16,7 +16,7 @@ use rustc_session::{parse::ParseSess, SessionDiagnostic};
 use rustc_span::Span;
 
 #[derive(SessionDiagnostic)]
-#[error(parser::expect_path)]
+#[diag(parser::expect_path)]
 struct DeriveSessionDiagnostic {
     #[primary_span]
     span: Span,
diff --git a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
index 0d9c9350efc..117b798710c 100644
--- a/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/src/test/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -30,7 +30,6 @@ use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
-use rustc_data_structures::thin_vec::ThinVec;
 use rustc_parse::new_parser_from_source_str;
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::FilePathMapping;
@@ -47,7 +46,7 @@ fn parse_expr(ps: &ParseSess, src: &str) -> Option<P<Expr>> {
 
 // Helper functions for building exprs
 fn expr(kind: ExprKind) -> P<Expr> {
-    P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: ThinVec::new(), tokens: None })
+    P(Expr { id: DUMMY_NODE_ID, kind, span: DUMMY_SP, attrs: AttrVec::new(), tokens: None })
 }
 
 fn make_x() -> P<Expr> {
@@ -196,7 +195,7 @@ impl MutVisitor for AddParens {
                 id: DUMMY_NODE_ID,
                 kind: ExprKind::Paren(e),
                 span: DUMMY_SP,
-                attrs: ThinVec::new(),
+                attrs: AttrVec::new(),
                 tokens: None,
             })
         });
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
index 0a210cbdc94..aaa8caa64f3 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.rs
@@ -28,15 +28,15 @@ use rustc_errors::{Applicability, MultiSpan};
 extern crate rustc_session;
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Hello {}
 
 #[derive(SessionDiagnostic)]
-#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct HelloWarn {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[derive(SessionDiagnostic)]` can only be used on structs
 enum SessionDiagnosticOnEnum {
     Foo,
@@ -44,54 +44,54 @@ enum SessionDiagnosticOnEnum {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[error = "E0123"]
-//~^ ERROR `#[error = ...]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag = "E0123"]
+//~^ ERROR `#[diag = ...]` is not a valid attribute
 struct WrongStructAttrStyle {}
 
 #[derive(SessionDiagnostic)]
 #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
 //~^ ERROR `#[nonsense(...)]` is not a valid attribute
-//~^^ ERROR diagnostic kind not specified
+//~^^ ERROR diagnostic slug not specified
 //~^^^ ERROR cannot find attribute `nonsense` in this scope
 struct InvalidStructAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error("E0123")]
-//~^ ERROR `#[error("...")]` is not a valid attribute
+#[diag("E0123")]
+//~^ ERROR `#[diag("...")]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidLitNestedAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense, code = "E0123")]
+#[diag(nonsense, code = "E0123")]
 //~^ ERROR cannot find value `nonsense` in module `rustc_errors::fluent`
 struct InvalidNestedStructAttr {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense("foo"), code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense(...))]` is not a valid attribute
+#[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense(...))]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr1 {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense = "...", code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+#[diag(nonsense = "...", code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr2 {}
 
 #[derive(SessionDiagnostic)]
-#[error(nonsense = 4, code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(nonsense = ...)]` is not a valid attribute
+#[diag(nonsense = 4, code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(nonsense = ...)]` is not a valid attribute
 //~^^ ERROR diagnostic slug not specified
 struct InvalidNestedStructAttr3 {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
-//~^ ERROR `#[error(slug = ...)]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+//~^ ERROR `#[diag(slug = ...)]` is not a valid attribute
 struct InvalidNestedStructAttr4 {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongPlaceField {
     #[suggestion = "bar"]
     //~^ ERROR `#[suggestion = ...]` is not a valid attribute
@@ -99,45 +99,36 @@ struct WrongPlaceField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
 //~^ ERROR specified multiple times
 //~^^ ERROR specified multiple times
-//~^^^ ERROR specified multiple times
-struct ErrorSpecifiedTwice {}
+struct DiagSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-#[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-//~^ ERROR specified multiple times
-//~^^ ERROR specified multiple times
-//~^^^ ERROR specified multiple times
-struct WarnSpecifiedAfterError {}
-
-#[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
 //~^ ERROR specified multiple times
 struct CodeSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-//~^ ERROR `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+#[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+//~^ ERROR `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
 struct SlugSpecifiedTwice {}
 
 #[derive(SessionDiagnostic)]
-struct KindNotProvided {} //~ ERROR diagnostic kind not specified
+struct KindNotProvided {} //~ ERROR diagnostic slug not specified
 
 #[derive(SessionDiagnostic)]
-#[error(code = "E0456")]
+#[diag(code = "E0456")]
 //~^ ERROR diagnostic slug not specified
 struct SlugNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct CodeNotProvided {}
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct MessageWrongType {
     #[primary_span]
     //~^ ERROR `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -145,7 +136,7 @@ struct MessageWrongType {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidPathFieldAttr {
     #[nonsense]
     //~^ ERROR `#[nonsense]` is not a valid attribute
@@ -154,7 +145,7 @@ struct InvalidPathFieldAttr {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithField {
     name: String,
     #[label(typeck::label)]
@@ -162,7 +153,7 @@ struct ErrorWithField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithMessageAppliedToField {
     #[label(typeck::label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -170,7 +161,7 @@ struct ErrorWithMessageAppliedToField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNonexistentField {
     #[suggestion(typeck::suggestion, code = "{name}")]
     //~^ ERROR `name` doesn't refer to a field on this type
@@ -179,7 +170,7 @@ struct ErrorWithNonexistentField {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: expected `'}'`
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingClosingBrace {
     #[suggestion(typeck::suggestion, code = "{name")]
     suggestion: (Span, Applicability),
@@ -189,7 +180,7 @@ struct ErrorMissingClosingBrace {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR invalid format string: unmatched `}`
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorMissingOpeningBrace {
     #[suggestion(typeck::suggestion, code = "name}")]
     suggestion: (Span, Applicability),
@@ -198,14 +189,14 @@ struct ErrorMissingOpeningBrace {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnSpan {
     #[label(typeck::label)]
     sp: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelOnNonSpan {
     #[label(typeck::label)]
     //~^ ERROR the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
@@ -213,7 +204,7 @@ struct LabelOnNonSpan {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct Suggest {
     #[suggestion(typeck::suggestion, code = "This is the suggested code")]
     #[suggestion_short(typeck::suggestion, code = "This is the suggested code")]
@@ -223,14 +214,14 @@ struct Suggest {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutCode {
     #[suggestion(typeck::suggestion)]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithBadKey {
     #[suggestion(nonsense = "bar")]
     //~^ ERROR `#[suggestion(nonsense = ...)]` is not a valid attribute
@@ -238,7 +229,7 @@ struct SuggestWithBadKey {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithShorthandMsg {
     #[suggestion(msg = "bar")]
     //~^ ERROR `#[suggestion(msg = ...)]` is not a valid attribute
@@ -246,21 +237,21 @@ struct SuggestWithShorthandMsg {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithoutMsg {
     #[suggestion(code = "bar")]
     suggestion: (Span, Applicability),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithTypesSwapped {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: (Applicability, Span),
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithWrongTypeApplicabilityOnly {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR wrong field type for suggestion
@@ -268,14 +259,14 @@ struct SuggestWithWrongTypeApplicabilityOnly {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithSpanOnly {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateSpanAndApplicability {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one `Span`
@@ -283,7 +274,7 @@ struct SuggestWithDuplicateSpanAndApplicability {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct SuggestWithDuplicateApplicabilityAndSpan {
     #[suggestion(typeck::suggestion, code = "This is suggested code")]
     //~^ ERROR type of field annotated with `#[suggestion(...)]` contains more than one
@@ -291,7 +282,7 @@ struct SuggestWithDuplicateApplicabilityAndSpan {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct WrongKindOfAnnotation {
     #[label = "bar"]
     //~^ ERROR `#[label = ...]` is not a valid attribute
@@ -299,7 +290,7 @@ struct WrongKindOfAnnotation {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptionsInErrors {
     #[label(typeck::label)]
     label: Option<Span>,
@@ -308,7 +299,7 @@ struct OptionsInErrors {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
 struct MoveOutOfBorrowError<'tcx> {
     name: Ident,
     ty: Ty<'tcx>,
@@ -322,7 +313,7 @@ struct MoveOutOfBorrowError<'tcx> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithLifetime<'a> {
     #[label(typeck::label)]
     span: Span,
@@ -330,7 +321,7 @@ struct ErrorWithLifetime<'a> {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithDefaultLabelAttr<'a> {
     #[label]
     span: Span,
@@ -339,7 +330,7 @@ struct ErrorWithDefaultLabelAttr<'a> {
 
 #[derive(SessionDiagnostic)]
 //~^ ERROR the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithoutSkip {
     #[primary_span]
     span: Span,
@@ -347,7 +338,7 @@ struct ArgFieldWithoutSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ArgFieldWithSkip {
     #[primary_span]
     span: Span,
@@ -358,56 +349,56 @@ struct ArgFieldWithSkip {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNote {
     #[note]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedNoteCustom {
     #[note(typeck::note)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[note]
 struct ErrorWithNote {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[note(typeck::note)]
 struct ErrorWithNoteCustom {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelp {
     #[help]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithSpannedHelpCustom {
     #[help(typeck::help)]
     span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[help]
 struct ErrorWithHelp {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[help(typeck::help)]
 struct ErrorWithHelpCustom {
     val: String,
@@ -415,34 +406,34 @@ struct ErrorWithHelpCustom {
 
 #[derive(SessionDiagnostic)]
 #[help]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[help(typeck::help)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithHelpCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[note]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
 #[note(typeck::note)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithNoteCustomWrongOrder {
     val: String,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ApplicabilityInBoth {
     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     //~^ ERROR applicability cannot be set in both the field and attribute
@@ -450,7 +441,7 @@ struct ApplicabilityInBoth {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct InvalidApplicability {
     #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
     //~^ ERROR invalid applicability
@@ -458,14 +449,14 @@ struct InvalidApplicability {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ValidApplicability {
     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
     suggestion: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct NoApplicability {
     #[suggestion(typeck::suggestion, code = "...")]
     suggestion: Span,
@@ -476,14 +467,14 @@ struct NoApplicability {
 struct Note;
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct Subdiagnostic {
     #[subdiagnostic]
     note: Note,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct VecField {
     #[primary_span]
     #[label]
@@ -491,7 +482,7 @@ struct VecField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct UnitField {
     #[primary_span]
     spans: Span,
@@ -502,7 +493,7 @@ struct UnitField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct OptUnitField {
     #[primary_span]
     spans: Span,
@@ -513,7 +504,7 @@ struct OptUnitField {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingPath {
     #[label(typeck::label, foo)]
     //~^ ERROR `#[label(...)]` is not a valid attribute
@@ -521,7 +512,7 @@ struct LabelWithTrailingPath {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingNameValue {
     #[label(typeck::label, foo = "...")]
     //~^ ERROR `#[label(...)]` is not a valid attribute
@@ -529,40 +520,64 @@ struct LabelWithTrailingNameValue {
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct LabelWithTrailingList {
     #[label(typeck::label, foo("..."))]
     //~^ ERROR `#[label(...)]` is not a valid attribute
     span: Span,
 }
 
-#[derive(SessionDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound)]
-//~^ ERROR only `#[error(..)]` and `#[warning(..)]` are supported
-struct LintsBad {
-}
-
 #[derive(LintDiagnostic)]
-#[lint(typeck::ambiguous_lifetime_bound)]
+#[diag(typeck::ambiguous_lifetime_bound)]
 struct LintsGood {
 }
 
 #[derive(LintDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound)]
-//~^ ERROR only `#[lint(..)]` is supported
-struct ErrorsBad {
+#[diag(typeck::ambiguous_lifetime_bound)]
+struct PrimarySpanOnLint {
+    #[primary_span]
+    //~^ ERROR `#[primary_span]` is not a valid attribute
+    span: Span,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 struct ErrorWithMultiSpan {
     #[primary_span]
     span: MultiSpan,
 }
 
 #[derive(SessionDiagnostic)]
-#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+#[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 #[warn_]
 struct ErrorWithWarn {
     val: String,
 }
+
+#[derive(SessionDiagnostic)]
+#[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[error(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `error` in this scope
+struct ErrorAttribute {}
+
+#[derive(SessionDiagnostic)]
+#[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[warning(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `warning` in this scope
+struct WarningAttribute {}
+
+#[derive(SessionDiagnostic)]
+#[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[lint(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `lint` in this scope
+struct LintAttributeOnSessionDiag {}
+
+#[derive(LintDiagnostic)]
+#[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+//~^ ERROR `#[lint(...)]` is not a valid attribute
+//~| ERROR diagnostic slug not specified
+//~| ERROR cannot find attribute `lint` in this scope
+struct LintAttributeOnLintDiag {}
diff --git a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
index c1080aa2452..866b1a1de99 100644
--- a/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
+++ b/src/test/ui-fulldeps/session-diagnostic/diagnostic-derive.stderr
@@ -1,7 +1,7 @@
 error: `#[derive(SessionDiagnostic)]` can only be used on structs
   --> $DIR/diagnostic-derive.rs:39:1
    |
-LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | / #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
 LL | | enum SessionDiagnosticOnEnum {
 LL | |     Foo,
@@ -9,11 +9,11 @@ LL | |     Bar,
 LL | | }
    | |_^
 
-error: `#[error = ...]` is not a valid attribute
+error: `#[diag = ...]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:48:1
    |
-LL | #[error = "E0123"]
-   | ^^^^^^^^^^^^^^^^^^
+LL | #[diag = "E0123"]
+   | ^^^^^^^^^^^^^^^^^
 
 error: `#[nonsense(...)]` is not a valid attribute
   --> $DIR/diagnostic-derive.rs:53:1
@@ -21,9 +21,9 @@ error: `#[nonsense(...)]` is not a valid attribute
 LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: only `error`, `warning`, `help`, `note` and `warn_` are valid attributes
+   = help: only `diag`, `help`, `note` and `warn_` are valid attributes
 
-error: diagnostic kind not specified
+error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:53:1
    |
 LL | / #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
@@ -33,89 +33,89 @@ LL | |
 LL | | struct InvalidStructAttr {}
    | |___________________________^
    |
-   = help: use the `#[error(...)]` attribute to create an error
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error("...")]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:60:9
+error: `#[diag("...")]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:60:8
    |
-LL | #[error("E0123")]
-   |         ^^^^^^^
+LL | #[diag("E0123")]
+   |        ^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:60:1
    |
-LL | / #[error("E0123")]
+LL | / #[diag("E0123")]
 LL | |
 LL | |
 LL | | struct InvalidLitNestedAttr {}
    | |______________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense(...))]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:71:9
+error: `#[diag(nonsense(...))]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:71:8
    |
-LL | #[error(nonsense("foo"), code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^^^^
+LL | #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:71:1
    |
-LL | / #[error(nonsense("foo"), code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense("foo"), code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr1 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:77:9
+error: `#[diag(nonsense = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:77:8
    |
-LL | #[error(nonsense = "...", code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^^^^^
+LL | #[diag(nonsense = "...", code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:77:1
    |
-LL | / #[error(nonsense = "...", code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = "...", code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr2 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:83:9
+error: `#[diag(nonsense = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:83:8
    |
-LL | #[error(nonsense = 4, code = "E0123", slug = "foo")]
-   |         ^^^^^^^^^^^^
+LL | #[diag(nonsense = 4, code = "E0123", slug = "foo")]
+   |        ^^^^^^^^^^^^
    |
    = help: first argument of the attribute should be the diagnostic slug
 
 error: diagnostic slug not specified
   --> $DIR/diagnostic-derive.rs:83:1
    |
-LL | / #[error(nonsense = 4, code = "E0123", slug = "foo")]
+LL | / #[diag(nonsense = 4, code = "E0123", slug = "foo")]
 LL | |
 LL | |
 LL | | struct InvalidNestedStructAttr3 {}
    | |__________________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
-error: `#[error(slug = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:89:59
+error: `#[diag(slug = ...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:89:58
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
-   |                                                           ^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123", slug = "foo")]
+   |                                                          ^^^^^^^^^^^^
    |
    = help: only `code` is a valid nested attributes following the slug
 
@@ -128,119 +128,71 @@ LL |     #[suggestion = "bar"]
 error: specified multiple times
   --> $DIR/diagnostic-derive.rs:103:1
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: previously specified here
   --> $DIR/diagnostic-derive.rs:102:1
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:103:1
+  --> $DIR/diagnostic-derive.rs:103:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                                 ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:102:1
+  --> $DIR/diagnostic-derive.rs:102:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |                                                 ^^^^^^^
 
 error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:103:50
+  --> $DIR/diagnostic-derive.rs:109:65
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                                 ^^^^^^^
    |
 note: previously specified here
-  --> $DIR/diagnostic-derive.rs:102:50
+  --> $DIR/diagnostic-derive.rs:109:49
    |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
+   |                                                 ^^^^^^^
 
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:1
+error: `#[diag(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:114:42
    |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:1
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | #[diag(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
+   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:1
-   |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:1
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:111:52
-   |
-LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0293")]
-   |                                                    ^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:110:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
-   |                                                  ^^^^^^^
-
-error: specified multiple times
-  --> $DIR/diagnostic-derive.rs:118:66
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                                  ^^^^^^^
-   |
-note: previously specified here
-  --> $DIR/diagnostic-derive.rs:118:50
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0456", code = "E0457")]
-   |                                                  ^^^^^^^
-
-error: `#[error(typeck::ambiguous_lifetime_bound)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:123:43
-   |
-LL | #[error(typeck::ambiguous_lifetime_bound, typeck::ambiguous_lifetime_bound, code = "E0456")]
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: diagnostic kind not specified
-  --> $DIR/diagnostic-derive.rs:128:1
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:119:1
    |
 LL | struct KindNotProvided {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: use the `#[error(...)]` attribute to create an error
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
 error: diagnostic slug not specified
-  --> $DIR/diagnostic-derive.rs:131:1
+  --> $DIR/diagnostic-derive.rs:122:1
    |
-LL | / #[error(code = "E0456")]
+LL | / #[diag(code = "E0456")]
 LL | |
 LL | | struct SlugNotProvided {}
    | |_________________________^
    |
-   = help: specify the slug as the first argument to the attribute, such as `#[error(typeck::example_error)]`
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
 
 error: the `#[primary_span]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:142:5
+  --> $DIR/diagnostic-derive.rs:133:5
    |
 LL |     #[primary_span]
    |     ^^^^^^^^^^^^^^^
 
 error: `#[nonsense]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:150:5
+  --> $DIR/diagnostic-derive.rs:141:5
    |
 LL |     #[nonsense]
    |     ^^^^^^^^^^^
@@ -248,19 +200,19 @@ LL |     #[nonsense]
    = help: only `skip_arg`, `primary_span`, `label`, `note`, `help` and `subdiagnostic` are valid field attributes
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:167:5
+  --> $DIR/diagnostic-derive.rs:158:5
    |
 LL |     #[label(typeck::label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `name` doesn't refer to a field on this type
-  --> $DIR/diagnostic-derive.rs:175:45
+  --> $DIR/diagnostic-derive.rs:166:45
    |
 LL |     #[suggestion(typeck::suggestion, code = "{name}")]
    |                                             ^^^^^^^^
 
 error: invalid format string: expected `'}'` but string was terminated
-  --> $DIR/diagnostic-derive.rs:180:16
+  --> $DIR/diagnostic-derive.rs:171:16
    |
 LL | #[derive(SessionDiagnostic)]
    |           -    ^ expected `'}'` in format string
@@ -271,7 +223,7 @@ LL | #[derive(SessionDiagnostic)]
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: invalid format string: unmatched `}` found
-  --> $DIR/diagnostic-derive.rs:190:15
+  --> $DIR/diagnostic-derive.rs:181:15
    |
 LL | #[derive(SessionDiagnostic)]
    |               ^ unmatched `}` in format string
@@ -280,13 +232,13 @@ LL | #[derive(SessionDiagnostic)]
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: the `#[label(...)]` attribute can only be applied to fields of type `Span` or `MultiSpan`
-  --> $DIR/diagnostic-derive.rs:210:5
+  --> $DIR/diagnostic-derive.rs:201:5
    |
 LL |     #[label(typeck::label)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[suggestion(nonsense = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:235:18
+  --> $DIR/diagnostic-derive.rs:226:18
    |
 LL |     #[suggestion(nonsense = "bar")]
    |                  ^^^^^^^^^^^^^^^^
@@ -294,7 +246,7 @@ LL |     #[suggestion(nonsense = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: `#[suggestion(msg = ...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:243:18
+  --> $DIR/diagnostic-derive.rs:234:18
    |
 LL |     #[suggestion(msg = "bar")]
    |                  ^^^^^^^^^^^
@@ -302,7 +254,7 @@ LL |     #[suggestion(msg = "bar")]
    = help: only `message`, `code` and `applicability` are valid field attributes
 
 error: wrong field type for suggestion
-  --> $DIR/diagnostic-derive.rs:265:5
+  --> $DIR/diagnostic-derive.rs:256:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -312,7 +264,7 @@ LL | |     suggestion: Applicability,
    = help: `#[suggestion(...)]` should be applied to fields of type `Span` or `(Span, Applicability)`
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one `Span`
-  --> $DIR/diagnostic-derive.rs:280:5
+  --> $DIR/diagnostic-derive.rs:271:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -320,7 +272,7 @@ LL | |     suggestion: (Span, Span, Applicability),
    | |___________________________________________^
 
 error: type of field annotated with `#[suggestion(...)]` contains more than one Applicability
-  --> $DIR/diagnostic-derive.rs:288:5
+  --> $DIR/diagnostic-derive.rs:279:5
    |
 LL | /     #[suggestion(typeck::suggestion, code = "This is suggested code")]
 LL | |
@@ -328,62 +280,128 @@ LL | |     suggestion: (Applicability, Applicability, Span),
    | |____________________________________________________^
 
 error: `#[label = ...]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:296:5
+  --> $DIR/diagnostic-derive.rs:287:5
    |
 LL |     #[label = "bar"]
    |     ^^^^^^^^^^^^^^^^
 
 error: applicability cannot be set in both the field and attribute
-  --> $DIR/diagnostic-derive.rs:447:52
+  --> $DIR/diagnostic-derive.rs:438:52
    |
 LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "maybe-incorrect")]
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: invalid applicability
-  --> $DIR/diagnostic-derive.rs:455:52
+  --> $DIR/diagnostic-derive.rs:446:52
    |
 LL |     #[suggestion(typeck::suggestion, code = "...", applicability = "batman")]
    |                                                    ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:518:5
+  --> $DIR/diagnostic-derive.rs:509:5
    |
 LL |     #[label(typeck::label, foo)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:526:5
+  --> $DIR/diagnostic-derive.rs:517:5
    |
 LL |     #[label(typeck::label, foo = "...")]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: `#[label(...)]` is not a valid attribute
-  --> $DIR/diagnostic-derive.rs:534:5
+  --> $DIR/diagnostic-derive.rs:525:5
    |
 LL |     #[label(typeck::label, foo("..."))]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: only `#[error(..)]` and `#[warning(..)]` are supported
-  --> $DIR/diagnostic-derive.rs:540:1
+error: `#[primary_span]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:538:5
    |
-LL | / #[lint(typeck::ambiguous_lifetime_bound)]
+LL |     #[primary_span]
+   |     ^^^^^^^^^^^^^^^
+   |
+   = help: the `primary_span` field attribute is not valid for lint diagnostics
+
+error: `#[error(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:558:1
+   |
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:558:1
+   |
+LL | / #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
-LL | | struct LintsBad {
-LL | | }
-   | |_^
+LL | |
+LL | |
+LL | | struct ErrorAttribute {}
+   | |________________________^
+   |
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[warning(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:565:1
    |
-   = help: use the `#[error(...)]` attribute to create a error
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
 
-error: only `#[lint(..)]` is supported
-  --> $DIR/diagnostic-derive.rs:551:1
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:565:1
    |
-LL | / #[error(typeck::ambiguous_lifetime_bound)]
+LL | / #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
 LL | |
-LL | | struct ErrorsBad {
-LL | | }
-   | |_^
+LL | |
+LL | |
+LL | | struct WarningAttribute {}
+   | |__________________________^
+   |
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[lint(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:572:1
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:572:1
+   |
+LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct LintAttributeOnSessionDiag {}
+   | |____________________________________^
+   |
+   = help: specify the slug as the first argument to the `#[diag(...)]` attribute, such as `#[diag(typeck::example_error)]`
+
+error: `#[lint(...)]` is not a valid attribute
+  --> $DIR/diagnostic-derive.rs:579:1
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: `error`, `warning` and `lint` have been replaced by `diag`
+
+error: diagnostic slug not specified
+  --> $DIR/diagnostic-derive.rs:579:1
+   |
+LL | / #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+LL | |
+LL | |
+LL | |
+LL | | struct LintAttributeOnLintDiag {}
+   | |_________________________________^
    |
-   = help: use the `#[lint(...)]` attribute to create a lint
+   = help: specify the slug as the first argument to the attribute, such as `#[diag(typeck::example_error)]`
 
 error: cannot find attribute `nonsense` in this scope
   --> $DIR/diagnostic-derive.rs:53:3
@@ -392,32 +410,56 @@ LL | #[nonsense(typeck::ambiguous_lifetime_bound, code = "E0123")]
    |   ^^^^^^^^
 
 error: cannot find attribute `nonsense` in this scope
-  --> $DIR/diagnostic-derive.rs:150:7
+  --> $DIR/diagnostic-derive.rs:141:7
    |
 LL |     #[nonsense]
    |       ^^^^^^^^
 
+error: cannot find attribute `error` in this scope
+  --> $DIR/diagnostic-derive.rs:558:3
+   |
+LL | #[error(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^^
+
+error: cannot find attribute `warning` in this scope
+  --> $DIR/diagnostic-derive.rs:565:3
+   |
+LL | #[warning(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^^^^
+
+error: cannot find attribute `lint` in this scope
+  --> $DIR/diagnostic-derive.rs:572:3
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^ help: a built-in attribute with a similar name exists: `link`
+
+error: cannot find attribute `lint` in this scope
+  --> $DIR/diagnostic-derive.rs:579:3
+   |
+LL | #[lint(typeck::ambiguous_lifetime_bound, code = "E0123")]
+   |   ^^^^ help: a built-in attribute with a similar name exists: `link`
+
 error[E0425]: cannot find value `nonsense` in module `rustc_errors::fluent`
-  --> $DIR/diagnostic-derive.rs:66:9
+  --> $DIR/diagnostic-derive.rs:66:8
    |
-LL | #[error(nonsense, code = "E0123")]
-   |         ^^^^^^^^ not found in `rustc_errors::fluent`
+LL | #[diag(nonsense, code = "E0123")]
+   |        ^^^^^^^^ not found in `rustc_errors::fluent`
 
 error[E0277]: the trait bound `Hello: IntoDiagnosticArg` is not satisfied
-  --> $DIR/diagnostic-derive.rs:340:10
+  --> $DIR/diagnostic-derive.rs:331:10
    |
 LL | #[derive(SessionDiagnostic)]
    |          ^^^^^^^^^^^^^^^^^ the trait `IntoDiagnosticArg` is not implemented for `Hello`
    |
    = help: normalized in stderr
 note: required by a bound in `DiagnosticBuilder::<'a, G>::set_arg`
-  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:539:19
+  --> $COMPILER_DIR/rustc_errors/src/diagnostic_builder.rs:569:19
    |
 LL |         arg: impl IntoDiagnosticArg,
    |                   ^^^^^^^^^^^^^^^^^ required by this bound in `DiagnosticBuilder::<'a, G>::set_arg`
    = note: this error originates in the derive macro `SessionDiagnostic` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 48 previous errors
+error: aborting due to 55 previous errors
 
 Some errors have detailed explanations: E0277, E0425.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
index 582473905cf..ab95137c630 100644
--- a/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
+++ b/src/test/ui/associated-consts/defaults-cyclic-fail.stderr
@@ -2,13 +2,13 @@ error[E0391]: cycle detected when const-evaluating + checking `Tr::A`
   --> $DIR/defaults-cyclic-fail.rs:5:5
    |
 LL |     const A: u8 = Self::B;
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating + checking `Tr::B`...
   --> $DIR/defaults-cyclic-fail.rs:8:5
    |
 LL |     const B: u8 = Self::A;
-   |     ^^^^^^^^^^^
+   |     ^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires const-evaluating + checking `Tr::A`, completing the cycle
 note: cycle used when const-evaluating + checking `main::promoted[1]`
   --> $DIR/defaults-cyclic-fail.rs:16:16
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
index 51a50cfdaf9..e682b8e9e6d 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-impl.stderr
@@ -13,7 +13,7 @@ note: ...which requires const-evaluating + checking `IMPL_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:7:1
    |
 LL | const IMPL_REF_BAR: u32 = GlobalImplRef::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-impl.rs:11:1: 11:19>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-impl.rs:12:5
    |
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
index b9d1808feb3..9b0c1b14901 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait-default.stderr
@@ -13,7 +13,7 @@ note: ...which requires const-evaluating + checking `DEFAULT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:11:1
    |
 LL | const DEFAULT_REF_BAR: u32 = <GlobalDefaultRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `FooDefault::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait-default.rs:8:5
    |
diff --git a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
index 271e69206cd..48956dcedab 100644
--- a/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
+++ b/src/test/ui/associated-consts/issue-24949-assoc-const-static-recursion-trait.stderr
@@ -13,7 +13,7 @@ note: ...which requires const-evaluating + checking `TRAIT_REF_BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:7:1
    |
 LL | const TRAIT_REF_BAR: u32 = <GlobalTraitRef>::BAR;
-   | ^^^^^^^^^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires const-evaluating + checking `<impl at $DIR/issue-24949-assoc-const-static-recursion-trait.rs:11:1: 11:28>::BAR`...
   --> $DIR/issue-24949-assoc-const-static-recursion-trait.rs:12:5
    |
diff --git a/src/test/ui/associated-types/associated-types-eq-3.stderr b/src/test/ui/associated-types/associated-types-eq-3.stderr
index 19750fe1f33..fbe1a1ee8bc 100644
--- a/src/test/ui/associated-types/associated-types-eq-3.stderr
+++ b/src/test/ui/associated-types/associated-types-eq-3.stderr
@@ -36,9 +36,7 @@ error[E0271]: type mismatch resolving `<isize as Foo>::A == Bar`
   --> $DIR/associated-types-eq-3.rs:40:9
    |
 LL |     baz(&a);
-   |     --- ^^ type mismatch resolving `<isize as Foo>::A == Bar`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^ type mismatch resolving `<isize as Foo>::A == Bar`
    |
 note: expected this to be `Bar`
   --> $DIR/associated-types-eq-3.rs:12:14
diff --git a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
index 6552c8be780..389cc7beddd 100644
--- a/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
+++ b/src/test/ui/associated-types/associated-types-for-unimpl-trait.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-for-unimpl-trait.rs:10:40
+  --> $DIR/associated-types-for-unimpl-trait.rs:10:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
index b2ee1b5e6d0..1feaa612ee6 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-bound.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `T: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-bound.rs:11:21
+  --> $DIR/associated-types-no-suitable-bound.rs:11:5
    |
 LL |     fn uhoh<T>(foo: <T as Get>::Value) {}
-   |                     ^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `T`
    |
 help: consider restricting type parameter `T`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
index 2e40dbd065d..cc3ed556115 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:40
+  --> $DIR/associated-types-no-suitable-supertrait-2.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
index bd3ee2abd2c..18f2830d8b2 100644
--- a/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
+++ b/src/test/ui/associated-types/associated-types-no-suitable-supertrait.stderr
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `(T, U): Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:22:40
+  --> $DIR/associated-types-no-suitable-supertrait.rs:22:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <(T, U) as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `(T, U)`
 
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-no-suitable-supertrait.rs:17:40
+  --> $DIR/associated-types-no-suitable-supertrait.rs:17:5
    |
 LL |     fn uhoh<U:Get>(&self, foo: U, bar: <Self as Get>::Value) {}
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/associated-types-path-2.stderr b/src/test/ui/associated-types/associated-types-path-2.stderr
index 66f1ab72692..5edd5c864e1 100644
--- a/src/test/ui/associated-types/associated-types-path-2.stderr
+++ b/src/test/ui/associated-types/associated-types-path-2.stderr
@@ -17,10 +17,12 @@ LL |     f1(2i32, 4u32);
    |               ~~~
 
 error[E0277]: the trait bound `u32: Foo` is not satisfied
-  --> $DIR/associated-types-path-2.rs:29:5
+  --> $DIR/associated-types-path-2.rs:29:8
    |
 LL |     f1(2u32, 4u32);
-   |     ^^ the trait `Foo` is not implemented for `u32`
+   |     -- ^^^^ the trait `Foo` is not implemented for `u32`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `f1`
@@ -33,9 +35,7 @@ error[E0277]: the trait bound `u32: Foo` is not satisfied
   --> $DIR/associated-types-path-2.rs:29:14
    |
 LL |     f1(2u32, 4u32);
-   |     --       ^^^^ the trait `Foo` is not implemented for `u32`
-   |     |
-   |     required by a bound introduced by this call
+   |              ^^^^ the trait `Foo` is not implemented for `u32`
    |
    = help: the trait `Foo` is implemented for `i32`
 
diff --git a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
index 2e67c21940f..66d59bccdbb 100644
--- a/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
+++ b/src/test/ui/associated-types/associated-types-projection-to-unrelated-trait-in-method-without-default.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `Self: Get` is not satisfied
-  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:40
+  --> $DIR/associated-types-projection-to-unrelated-trait-in-method-without-default.rs:10:5
    |
 LL |     fn okay<U:Get>(&self, foo: U, bar: <Self as Get>::Value);
-   |                                        ^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Get` is not implemented for `Self`
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/associated-types/defaults-suitability.stderr b/src/test/ui/associated-types/defaults-suitability.stderr
index 43541c5dfbc..eadad4cd572 100644
--- a/src/test/ui/associated-types/defaults-suitability.stderr
+++ b/src/test/ui/associated-types/defaults-suitability.stderr
@@ -39,7 +39,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
 LL |     type Bar: Clone = Vec<T>;
    |                       ^^^^^^ the trait `Clone` is not implemented for `T`
    |
-   = note: required because of the requirements on the impl of `Clone` for `Vec<T>`
+   = note: required for `Vec<T>` to implement `Clone`
 note: required by a bound in `Foo::Bar`
   --> $DIR/defaults-suitability.rs:28:15
    |
@@ -83,7 +83,7 @@ error[E0277]: the trait bound `<Self as Foo2<T>>::Baz: Clone` is not satisfied
 LL |     type Bar: Clone = Vec<Self::Baz>;
    |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo2<T>>::Baz`
    |
-   = note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo2<T>>::Baz>`
+   = note: required for `Vec<<Self as Foo2<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo2::Bar`
   --> $DIR/defaults-suitability.rs:65:15
    |
@@ -100,7 +100,7 @@ error[E0277]: the trait bound `<Self as Foo25<T>>::Baz: Clone` is not satisfied
 LL |     type Bar: Clone = Vec<Self::Baz>;
    |                       ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `<Self as Foo25<T>>::Baz`
    |
-   = note: required because of the requirements on the impl of `Clone` for `Vec<<Self as Foo25<T>>::Baz>`
+   = note: required for `Vec<<Self as Foo25<T>>::Baz>` to implement `Clone`
 note: required by a bound in `Foo25::Bar`
   --> $DIR/defaults-suitability.rs:74:15
    |
diff --git a/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr b/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr
deleted file mode 100644
index 8b2b87223a5..00000000000
--- a/src/test/ui/associated-types/higher-ranked-projection.badbase.stderr
+++ /dev/null
@@ -1,17 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/higher-ranked-projection.rs:25:5
-   |
-LL |     foo(());
-   |     ^^^^^^^ one type is more general than the other
-   |
-   = note: expected reference `&'a ()`
-              found reference `&()`
-note: the lifetime requirement is introduced here
-  --> $DIR/higher-ranked-projection.rs:16:33
-   |
-LL |     where for<'a> &'a T: Mirror<Image=U>
-   |                                 ^^^^^^^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr b/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr
deleted file mode 100644
index 217392aa35b..00000000000
--- a/src/test/ui/associated-types/higher-ranked-projection.badnll.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown debugging option: `borrowck`
-
diff --git a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
index e007f5a163b..a85edd7a08d 100644
--- a/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
+++ b/src/test/ui/associated-types/hr-associated-type-bound-2.stderr
@@ -5,13 +5,13 @@ LL | impl X<'_> for u32
    | ^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`hr_associated_type_bound_2`)
-note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
+note: required for `u32` to implement `for<'b> X<'b>`
   --> $DIR/hr-associated-type-bound-2.rs:11:6
    |
 LL | impl X<'_> for u32
    |      ^^^^^     ^^^
    = note: 128 redundant requirements hidden
-   = note: required because of the requirements on the impl of `for<'b> X<'b>` for `u32`
+   = note: required for `u32` to implement `for<'b> X<'b>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/impl-wf-cycle-1.stderr b/src/test/ui/associated-types/impl-wf-cycle-1.stderr
index 939c9bbdb6b..6661347e4f8 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-1.stderr
+++ b/src/test/ui/associated-types/impl-wf-cycle-1.stderr
@@ -4,13 +4,13 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
 LL | impl<T: Grault> Grault for (T,)
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required because of the requirements on the impl of `Grault` for `(T,)`
+note: required for `(T,)` to implement `Grault`
   --> $DIR/impl-wf-cycle-1.rs:15:17
    |
 LL | impl<T: Grault> Grault for (T,)
    |                 ^^^^^^     ^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Grault` for `(T,)`
+   = note: required for `(T,)` to implement `Grault`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/associated-types/impl-wf-cycle-2.stderr b/src/test/ui/associated-types/impl-wf-cycle-2.stderr
index d02ed2cacdf..ec4ffe27c5f 100644
--- a/src/test/ui/associated-types/impl-wf-cycle-2.stderr
+++ b/src/test/ui/associated-types/impl-wf-cycle-2.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `<(T,) as Grault>::A == _`
 LL | impl<T: Grault> Grault for (T,)
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required because of the requirements on the impl of `Grault` for `(T,)`
+note: required for `(T,)` to implement `Grault`
   --> $DIR/impl-wf-cycle-2.rs:7:17
    |
 LL | impl<T: Grault> Grault for (T,)
diff --git a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
index 22daaf32910..a14a273b3ec 100644
--- a/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
+++ b/src/test/ui/associated-types/issue-27675-unchecked-bounds.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `T: Copy` is not satisfied
-  --> $DIR/issue-27675-unchecked-bounds.rs:15:31
+  --> $DIR/issue-27675-unchecked-bounds.rs:15:12
    |
 LL |     copy::<dyn Setup<From=T>>(t)
-   |     ------------------------- ^ the trait `Copy` is not implemented for `T`
-   |     |
-   |     required by a bound introduced by this call
+   |            ^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `T`
    |
 note: required by a bound in `copy`
   --> $DIR/issue-27675-unchecked-bounds.rs:10:12
diff --git a/src/test/ui/associated-types/issue-44153.stderr b/src/test/ui/associated-types/issue-44153.stderr
index 200efbe02e6..9c92f19d8bf 100644
--- a/src/test/ui/associated-types/issue-44153.stderr
+++ b/src/test/ui/associated-types/issue-44153.stderr
@@ -9,7 +9,7 @@ note: expected this to be `&()`
    |
 LL |     type Element = ();
    |                    ^^
-note: required because of the requirements on the impl of `Visit` for `()`
+note: required for `()` to implement `Visit`
   --> $DIR/issue-44153.rs:13:10
    |
 LL | impl<'a> Visit for () where
diff --git a/src/test/ui/associated-types/issue-59324.stderr b/src/test/ui/associated-types/issue-59324.stderr
index dd5ec7175b5..62cf1f37a77 100644
--- a/src/test/ui/associated-types/issue-59324.stderr
+++ b/src/test/ui/associated-types/issue-59324.stderr
@@ -45,16 +45,20 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:23:1
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
-   |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:16:8
+  --> $DIR/issue-59324.rs:16:5
    |
-LL |     fn get_service(
-   |        ^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
    |
 help: consider further restricting this bound
    |
diff --git a/src/test/ui/associated-types/issue-65774-1.stderr b/src/test/ui/associated-types/issue-65774-1.stderr
index 419de689c52..3b294d65d56 100644
--- a/src/test/ui/associated-types/issue-65774-1.stderr
+++ b/src/test/ui/associated-types/issue-65774-1.stderr
@@ -18,7 +18,7 @@ LL |         let closure = |config: &mut <S as MPU>::MpuConfig| writer.my_write(
    |                                                                            ^^^^^^^ the trait `MyDisplay` is not implemented for `T`
    |
    = help: the trait `MyDisplay` is implemented for `&'a mut T`
-note: required because of the requirements on the impl of `MyDisplay` for `&mut T`
+note: required for `&mut T` to implement `MyDisplay`
   --> $DIR/issue-65774-1.rs:5:24
    |
 LL | impl<'a, T: MyDisplay> MyDisplay for &'a mut T { }
diff --git a/src/test/ui/associated-types/substs-ppaux.normal.stderr b/src/test/ui/associated-types/substs-ppaux.normal.stderr
index 085c56870b3..501d2cfaa26 100644
--- a/src/test/ui/associated-types/substs-ppaux.normal.stderr
+++ b/src/test/ui/associated-types/substs-ppaux.normal.stderr
@@ -77,7 +77,7 @@ LL |     <str as Foo<u8>>::bar;
    |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-note: required because of the requirements on the impl of `Foo<'_, '_, u8>` for `str`
+note: required for `str` to implement `Foo<'_, '_, u8>`
   --> $DIR/substs-ppaux.rs:11:17
    |
 LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {}
diff --git a/src/test/ui/associated-types/substs-ppaux.verbose.stderr b/src/test/ui/associated-types/substs-ppaux.verbose.stderr
index b831f3b7a76..ae3e862dddd 100644
--- a/src/test/ui/associated-types/substs-ppaux.verbose.stderr
+++ b/src/test/ui/associated-types/substs-ppaux.verbose.stderr
@@ -77,7 +77,7 @@ LL |     <str as Foo<u8>>::bar;
    |     ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
-note: required because of the requirements on the impl of `Foo<'_#0r, '_#1r, u8>` for `str`
+note: required for `str` to implement `Foo<'_#0r, '_#1r, u8>`
   --> $DIR/substs-ppaux.rs:11:17
    |
 LL | impl<'a,'b,T,S> Foo<'a, 'b, S> for T {}
diff --git a/src/test/ui/async-await/issue-67252-unnamed-future.stderr b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
index 01c0d3225ba..af99b608ca1 100644
--- a/src/test/ui/async-await/issue-67252-unnamed-future.stderr
+++ b/src/test/ui/async-await/issue-67252-unnamed-future.stderr
@@ -1,8 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-67252-unnamed-future.rs:18:5
+  --> $DIR/issue-67252-unnamed-future.rs:18:11
    |
-LL |     spawn(async {
-   |     ^^^^^ future created by async block is not `Send`
+LL |       spawn(async {
+   |  ___________^
+LL | |         let _a = std::ptr::null_mut::<()>(); // `*mut ()` is not `Send`
+LL | |         AFuture.await;
+LL | |     });
+   | |_____^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*mut ()`
 note: future is not `Send` as this value is used across an await
diff --git a/src/test/ui/async-await/issue-68112.stderr b/src/test/ui/async-await/issue-68112.stderr
index 4285fbbeceb..c3553e3e0c1 100644
--- a/src/test/ui/async-await/issue-68112.stderr
+++ b/src/test/ui/async-await/issue-68112.stderr
@@ -1,8 +1,8 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:34:5
+  --> $DIR/issue-68112.rs:34:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ future created by async block is not `Send`
+   |                  ^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: future is not `Send` as it awaits another future which is not `Send`
@@ -17,10 +17,10 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error: future cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:43:5
+  --> $DIR/issue-68112.rs:43:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ future created by async block is not `Send`
+   |                  ^^^^^^^^ future created by async block is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: future is not `Send` as it awaits another future which is not `Send`
@@ -35,13 +35,15 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/issue-68112.rs:60:5
+  --> $DIR/issue-68112.rs:60:18
    |
 LL |     require_send(send_fut);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
-   = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
+   = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this `async fn` body
   --> $DIR/issue-68112.rs:47:31
    |
diff --git a/src/test/ui/async-await/issue-70594.stderr b/src/test/ui/async-await/issue-70594.stderr
index a88bce6cc99..f6ff52a5fd2 100644
--- a/src/test/ui/async-await/issue-70594.stderr
+++ b/src/test/ui/async-await/issue-70594.stderr
@@ -26,7 +26,7 @@ LL |     [1; ().await];
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `()`
+   = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     [1; ().await];
diff --git a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
index 2ce7309e1de..d2e388c78ca 100644
--- a/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
+++ b/src/test/ui/async-await/issue-70935-complex-spans.drop_tracking.stderr
@@ -5,7 +5,7 @@ LL | fn foo(tx: std::sync::mpsc::Sender<i32>) -> impl Future + Send {
    |                                             ^^^^^^^^^^^^^^^^^^ `Sender<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Sender<i32>`
-   = note: required because of the requirements on the impl of `Send` for `&Sender<i32>`
+   = note: required for `&Sender<i32>` to implement `Send`
 note: required because it's used within this closure
   --> $DIR/issue-70935-complex-spans.rs:16:13
    |
diff --git a/src/test/ui/async-await/issues/issue-62009-1.stderr b/src/test/ui/async-await/issues/issue-62009-1.stderr
index 5cbbf89a222..fb9dee11f2a 100644
--- a/src/test/ui/async-await/issues/issue-62009-1.stderr
+++ b/src/test/ui/async-await/issues/issue-62009-1.stderr
@@ -32,7 +32,7 @@ LL |     (|_| 2333).await;
    |
    = help: the trait `Future` is not implemented for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
    = note: [closure@$DIR/issue-62009-1.rs:12:6: 12:9] must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]`
+   = note: required for `[closure@$DIR/issue-62009-1.rs:12:6: 12:9]` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     (|_| 2333).await;
diff --git a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
index b2309300129..99e960f5d0f 100644
--- a/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
+++ b/src/test/ui/async-await/issues/issue-65436-raw-ptr-not-send.stderr
@@ -1,8 +1,12 @@
 error: future cannot be sent between threads safely
-  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:5
+  --> $DIR/issue-65436-raw-ptr-not-send.rs:12:17
    |
-LL |     assert_send(async {
-   |     ^^^^^^^^^^^ future created by async block is not `Send`
+LL |       assert_send(async {
+   |  _________________^
+LL | |
+LL | |         bar(Foo(std::ptr::null())).await;
+LL | |     })
+   | |_____^ future created by async block is not `Send`
    |
    = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `*const u8`
 note: future is not `Send` as this value is used across an await
diff --git a/src/test/ui/async-await/unnecessary-await.stderr b/src/test/ui/async-await/unnecessary-await.stderr
index e7e61c2baaf..dc308933697 100644
--- a/src/test/ui/async-await/unnecessary-await.stderr
+++ b/src/test/ui/async-await/unnecessary-await.stderr
@@ -8,7 +8,7 @@ LL |     boo().await;
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `()`
+   = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     boo().await;
diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
index 7d6bf58f516..0c4970a7259 100644
--- a/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-constituent-types-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `MyS2: MyTrait` is not satisfied in `(MyS2, MyS)`
-  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:5
+  --> $DIR/typeck-default-trait-impl-constituent-types-2.rs:17:18
    |
 LL |     is_mytrait::<(MyS2, MyS)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
+   |                  ^^^^^^^^^^^ within `(MyS2, MyS)`, the trait `MyTrait` is not implemented for `MyS2`
    |
    = note: required because it appears within the type `(MyS2, MyS)`
 note: required by a bound in `is_mytrait`
diff --git a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
index 985cdce1224..ce7095664c1 100644
--- a/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
+++ b/src/test/ui/auto-traits/typeck-default-trait-impl-precedence.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `u32: Signed` is not satisfied
-  --> $DIR/typeck-default-trait-impl-precedence.rs:19:5
+  --> $DIR/typeck-default-trait-impl-precedence.rs:19:20
    |
 LL |     is_defaulted::<&'static u32>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
+   |                    ^^^^^^^^^^^^ the trait `Signed` is not implemented for `u32`
    |
    = help: the trait `Signed` is implemented for `i32`
-note: required because of the requirements on the impl of `Defaulted` for `&'static u32`
+note: required for `&'static u32` to implement `Defaulted`
   --> $DIR/typeck-default-trait-impl-precedence.rs:10:19
    |
 LL | impl<'a,T:Signed> Defaulted for &'a T { }
diff --git a/src/test/ui/block-result/issue-22645.stderr b/src/test/ui/block-result/issue-22645.stderr
index 31663e8e84d..28debd60a99 100644
--- a/src/test/ui/block-result/issue-22645.stderr
+++ b/src/test/ui/block-result/issue-22645.stderr
@@ -5,7 +5,7 @@ LL |   b + 3
    |     ^ the trait `Scalar` is not implemented for `{integer}`
    |
    = help: the trait `Scalar` is implemented for `f64`
-note: required because of the requirements on the impl of `Add<{integer}>` for `Bob`
+note: required for `Bob` to implement `Add<{integer}>`
   --> $DIR/issue-22645.rs:8:19
    |
 LL | impl<RHS: Scalar> Add <RHS> for Bob {
diff --git a/src/test/ui/borrowck/issue-64453.stderr b/src/test/ui/borrowck/issue-64453.stderr
index 1f8a1acb89f..245c3a40e05 100644
--- a/src/test/ui/borrowck/issue-64453.stderr
+++ b/src/test/ui/borrowck/issue-64453.stderr
@@ -14,6 +14,7 @@ LL | static settings_dir: String = format!("");
    |                               ^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
    = note: this error originates in the macro `format` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0507]: cannot move out of static item `settings_dir`
diff --git a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
index af26169c806..b1af090aec2 100644
--- a/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
+++ b/src/test/ui/borrowck/suggest-as-ref-on-mut-closure.stderr
@@ -5,6 +5,7 @@ LL |     cb.map(|cb| cb());
    |     ^^^--------------
    |     |  |
    |     |  `*cb` moved due to this method call
+   |     help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |     move occurs because `*cb` has type `Option<&mut dyn FnMut()>`, which does not implement the `Copy` trait
    |
 note: this function takes ownership of the receiver `self`, which moves `*cb`
@@ -12,10 +13,6 @@ note: this function takes ownership of the receiver `self`, which moves `*cb`
    |
 LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
    |                            ^^^^
-help: consider calling `.as_ref()` to borrow the type's contents
-   |
-LL |     cb.as_ref().map(|cb| cb());
-   |        +++++++++
 
 error[E0596]: cannot borrow `*cb` as mutable, as it is behind a `&` reference
   --> $DIR/suggest-as-ref-on-mut-closure.rs:12:26
diff --git a/src/test/ui/chalkify/type_wf.rs b/src/test/ui/chalkify/type_wf.rs
index dd83a03fdf6..eeeefcfb7dd 100644
--- a/src/test/ui/chalkify/type_wf.rs
+++ b/src/test/ui/chalkify/type_wf.rs
@@ -15,8 +15,8 @@ fn main() {
        x: 5,
     };
 
-    let s = S { //~ ERROR the trait bound `{float}: Foo` is not satisfied
-        x: 5.0,
+    let s = S {
+        x: 5.0, //~ ERROR the trait bound `{float}: Foo` is not satisfied
     };
 
     let s = S {
diff --git a/src/test/ui/chalkify/type_wf.stderr b/src/test/ui/chalkify/type_wf.stderr
index 7f8566082cd..6e8daf63517 100644
--- a/src/test/ui/chalkify/type_wf.stderr
+++ b/src/test/ui/chalkify/type_wf.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `{float}: Foo` is not satisfied
-  --> $DIR/type_wf.rs:18:13
+  --> $DIR/type_wf.rs:19:12
    |
-LL |     let s = S {
-   |             ^ the trait `Foo` is not implemented for `{float}`
+LL |         x: 5.0,
+   |            ^^^ the trait `Foo` is not implemented for `{float}`
    |
    = help: the trait `Foo` is implemented for `i32`
 note: required by a bound in `S`
diff --git a/src/test/ui/check-static-values-constraints.stderr b/src/test/ui/check-static-values-constraints.stderr
index b28cf0d6bd0..3c193ca34ac 100644
--- a/src/test/ui/check-static-values-constraints.stderr
+++ b/src/test/ui/check-static-values-constraints.stderr
@@ -22,6 +22,7 @@ LL |     field2: SafeEnum::Variant4("str".to_string())
    |                                      ^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error[E0010]: allocations are not allowed in statics
   --> $DIR/check-static-values-constraints.rs:94:5
diff --git a/src/test/ui/closure_context/issue-26046-fn-mut.stderr b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
index 74d3c4977ee..f744b71c284 100644
--- a/src/test/ui/closure_context/issue-26046-fn-mut.stderr
+++ b/src/test/ui/closure_context/issue-26046-fn-mut.stderr
@@ -8,6 +8,8 @@ LL |         num += 1;
 ...
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
+   |
+   = note: required for the cast from `[closure@$DIR/issue-26046-fn-mut.rs:4:19: 4:21]` to the object type `dyn Fn()`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closure_context/issue-26046-fn-once.stderr b/src/test/ui/closure_context/issue-26046-fn-once.stderr
index 473e8e8417e..34f94f9dca6 100644
--- a/src/test/ui/closure_context/issue-26046-fn-once.stderr
+++ b/src/test/ui/closure_context/issue-26046-fn-once.stderr
@@ -8,6 +8,8 @@ LL |         vec
 ...
 LL |     Box::new(closure)
    |     ----------------- the requirement to implement `Fn` derives from here
+   |
+   = note: required for the cast from `[closure@$DIR/issue-26046-fn-once.rs:4:19: 4:26]` to the object type `dyn Fn() -> Vec<u8>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr
index bcde35983fc..309c63e5293 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-array-diagnostics.stderr
@@ -7,7 +7,15 @@ LL |         let [_, _s] = s;
    |                       - closure is `FnOnce` because it moves the variable `s` out of its environment
 LL |     };
 LL |     expect_fn(c);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `expect_fn`
+  --> $DIR/closure-origin-array-diagnostics.rs:5:17
+   |
+LL | fn expect_fn<F: Fn()>(_f: F) {}
+   |                 ^^^^ required by this bound in `expect_fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
index df33c4f1fd6..3e77635f9e0 100644
--- a/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
+++ b/src/test/ui/closures/2229_closure_analysis/diagnostics/closure-origin-tuple-diagnostics.stderr
@@ -7,7 +7,15 @@ LL |         let s = s.1;
    |                 --- closure is `FnOnce` because it moves the variable `s.1` out of its environment
 LL |     };
 LL |     expect_fn(c);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `expect_fn`
+  --> $DIR/closure-origin-tuple-diagnostics.rs:5:17
+   |
+LL | fn expect_fn<F: Fn()>(_f: F) {}
+   |                 ^^^^ required by this bound in `expect_fn`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/closures/closure-move-sync.stderr b/src/test/ui/closures/closure-move-sync.stderr
index 1086cfa2947..a2ca06b4e6e 100644
--- a/src/test/ui/closures/closure-move-sync.stderr
+++ b/src/test/ui/closures/closure-move-sync.stderr
@@ -1,11 +1,17 @@
 error[E0277]: `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
-  --> $DIR/closure-move-sync.rs:6:13
+  --> $DIR/closure-move-sync.rs:6:27
    |
-LL |     let t = thread::spawn(|| {
-   |             ^^^^^^^^^^^^^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
+LL |       let t = thread::spawn(|| {
+   |  _____________-------------_^
+   | |             |
+   | |             required by a bound introduced by this call
+LL | |         recv.recv().unwrap();
+LL | |
+LL | |     });
+   | |_____^ `std::sync::mpsc::Receiver<()>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `std::sync::mpsc::Receiver<()>`
-   = note: required because of the requirements on the impl of `Send` for `&std::sync::mpsc::Receiver<()>`
+   = note: required for `&std::sync::mpsc::Receiver<()>` to implement `Send`
 note: required because it's used within this closure
   --> $DIR/closure-move-sync.rs:6:27
    |
@@ -18,13 +24,15 @@ LL |     F: Send + 'static,
    |        ^^^^ required by this bound in `spawn`
 
 error[E0277]: `Sender<()>` cannot be shared between threads safely
-  --> $DIR/closure-move-sync.rs:18:5
+  --> $DIR/closure-move-sync.rs:18:19
    |
 LL |     thread::spawn(|| tx.send(()).unwrap());
-   |     ^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely
+   |     ------------- ^^^^^^^^^^^^^^^^^^^^^^^ `Sender<()>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Sender<()>`
-   = note: required because of the requirements on the impl of `Send` for `&Sender<()>`
+   = note: required for `&Sender<()>` to implement `Send`
 note: required because it's used within this closure
   --> $DIR/closure-move-sync.rs:18:19
    |
diff --git a/src/test/ui/closures/closure-wrong-kind.stderr b/src/test/ui/closures/closure-wrong-kind.stderr
index 35caf71a5e8..9ea55d764f3 100644
--- a/src/test/ui/closures/closure-wrong-kind.stderr
+++ b/src/test/ui/closures/closure-wrong-kind.stderr
@@ -6,7 +6,15 @@ LL |     let closure = |_| foo(x);
    |                   |
    |                   this closure implements `FnOnce`, not `Fn`
 LL |     bar(closure);
-   |     --- the requirement to implement `Fn` derives from here
+   |     --- ------- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `bar`
+  --> $DIR/closure-wrong-kind.rs:6:11
+   |
+LL | fn bar<T: Fn(u32)>(_: T) {}
+   |           ^^^^^^^ required by this bound in `bar`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/coherence/issue-100191-2.stderr b/src/test/ui/coherence/issue-100191-2.stderr
index ea09fb15bdf..d50c220bcfd 100644
--- a/src/test/ui/coherence/issue-100191-2.stderr
+++ b/src/test/ui/coherence/issue-100191-2.stderr
@@ -1,13 +1,13 @@
 error[E0275]: overflow evaluating the requirement `T: Trait<_>`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_100191_2`)
-note: required because of the requirements on the impl of `Trait<_>` for `T`
+note: required for `T` to implement `Trait<_>`
   --> $DIR/issue-100191-2.rs:8:20
    |
 LL | default impl<T, U> Trait<T> for U {}
    |                    ^^^^^^^^     ^
    = note: 128 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Trait<_>` for `T`
+   = note: required for `T` to implement `Trait<_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr
index a9c185e5fcb..0e8334d0338 100644
--- a/src/test/ui/const-generics/defaults/trait_objects_fail.stderr
+++ b/src/test/ui/const-generics/defaults/trait_objects_fail.stderr
@@ -2,9 +2,7 @@ error[E0277]: the trait bound `u32: Trait` is not satisfied
   --> $DIR/trait_objects_fail.rs:26:9
    |
 LL |     foo(&10_u32);
-   |     --- ^^^^^^^ the trait `Trait` is not implemented for `u32`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^^^ the trait `Trait` is not implemented for `u32`
    |
    = help: the trait `Trait<2>` is implemented for `u32`
    = note: required for the cast from `u32` to the object type `dyn Trait`
@@ -13,9 +11,7 @@ error[E0277]: the trait bound `bool: Traitor<_>` is not satisfied
   --> $DIR/trait_objects_fail.rs:28:9
    |
 LL |     bar(&true);
-   |     --- ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^ the trait `Traitor<_>` is not implemented for `bool`
    |
    = help: the trait `Traitor<2, 3>` is implemented for `bool`
    = note: required for the cast from `bool` to the object type `dyn Traitor<_>`
diff --git a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
index ababb27a869..615dc875f67 100644
--- a/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/abstract-const-as-cast-3.stderr
@@ -1,11 +1,11 @@
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:17:5
+  --> $DIR/abstract-const-as-cast-3.rs:17:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
   --> $DIR/abstract-const-as-cast-3.rs:8:22
    |
 LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
@@ -26,13 +26,13 @@ LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
               found type `{ O as u128 }`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:20:5
+  --> $DIR/abstract-const-as-cast-3.rs:20:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
   --> $DIR/abstract-const-as-cast-3.rs:8:22
    |
 LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
@@ -71,13 +71,13 @@ LL |     assert_impl::<HasCastInTraitImpl<14, 13>>();
               found type `14`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:35:5
+  --> $DIR/abstract-const-as-cast-3.rs:35:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>`
+note: required for `HasCastInTraitImpl<{ N + 1 }, { N as u128 }>` to implement `Trait`
   --> $DIR/abstract-const-as-cast-3.rs:8:22
    |
 LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
@@ -98,13 +98,13 @@ LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as u128 }>>();
               found type `{ O as u128 }`
 
 error: unconstrained generic constant
-  --> $DIR/abstract-const-as-cast-3.rs:38:5
+  --> $DIR/abstract-const-as-cast-3.rs:38:19
    |
 LL |     assert_impl::<HasCastInTraitImpl<{ N + 1 }, { N as _ }>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: try adding a `where` bound using this expression: `where [(); { O as u128 }]:`
-note: required because of the requirements on the impl of `Trait` for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>`
+note: required for `HasCastInTraitImpl<{ N + 1 }, { N as _ }>` to implement `Trait`
   --> $DIR/abstract-const-as-cast-3.rs:8:22
    |
 LL | impl<const O: usize> Trait for HasCastInTraitImpl<O, { O as u128 }> {}
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr
index 7a083733a2c..5ad457d547a 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-69654.stderr
@@ -2,7 +2,9 @@ error[E0423]: expected value, found type parameter `T`
   --> $DIR/issue-69654.rs:5:25
    |
 LL | impl<T> Bar<T> for [u8; T] {}
-   |                         ^ not a value
+   |      -                  ^ not a value
+   |      |
+   |      found this type pararmeter
 
 error[E0599]: the function or associated item `foo` exists for struct `Foo<_>`, but its trait bounds were not satisfied
   --> $DIR/issue-69654.rs:17:10
diff --git a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
index d45dfde9a79..808b305c680 100644
--- a/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
+++ b/src/test/ui/const-generics/generic_const_exprs/issue-85848.stderr
@@ -7,12 +7,12 @@ LL |     writes_to_specific_path(&cap);
    |     required by a bound introduced by this call
    |
    = help: the trait `Delegates<U>` is implemented for `T`
-note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+note: required for `&C` to implement `Contains<(), true>`
   --> $DIR/issue-85848.rs:21:12
    |
 LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+note: required for `&C` to implement `Delegates<()>`
   --> $DIR/issue-85848.rs:12:12
    |
 LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
@@ -32,12 +32,12 @@ LL |     writes_to_specific_path(&cap);
    |     required by a bound introduced by this call
    |
    = help: try adding a `where` bound using this expression: `where [(); { contains::<T, U>() }]:`
-note: required because of the requirements on the impl of `Contains<(), true>` for `&C`
+note: required for `&C` to implement `Contains<(), true>`
   --> $DIR/issue-85848.rs:21:12
    |
 LL | impl<T, U> Contains<T, { contains::<T, U>() }> for U where T: _Contains<U> {}
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^     ^
-note: required because of the requirements on the impl of `Delegates<()>` for `&C`
+note: required for `&C` to implement `Delegates<()>`
   --> $DIR/issue-85848.rs:12:12
    |
 LL | impl<T, U> Delegates<U> for T where T: Contains<U, true> {}
diff --git a/src/test/ui/consts/const-block-const-bound.stderr b/src/test/ui/consts/const-block-const-bound.stderr
index 87ca771e54e..b9c4d8866bf 100644
--- a/src/test/ui/consts/const-block-const-bound.stderr
+++ b/src/test/ui/consts/const-block-const-bound.stderr
@@ -2,7 +2,7 @@ error[E0277]: can't drop `UnconstDrop` in const contexts
   --> $DIR/const-block-const-bound.rs:20:11
    |
 LL |         f(UnconstDrop);
-   |         - ^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |         - ^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `UnconstDrop`
    |         |
    |         required by a bound introduced by this call
    |
@@ -23,7 +23,7 @@ error[E0277]: can't drop `NonDrop` in const contexts
   --> $DIR/const-block-const-bound.rs:22:11
    |
 LL |         f(NonDrop);
-   |         - ^^^^^^^ expected an implementor of trait `~const Destruct`
+   |         - ^^^^^^^ the trait `~const Destruct` is not implemented for `NonDrop`
    |         |
    |         required by a bound introduced by this call
    |
diff --git a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr
index 5306fed2251..ee352700c30 100644
--- a/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr
+++ b/src/test/ui/consts/const-blocks/fn-call-in-non-const.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
 LL |     let _: [Option<Bar>; 2] = [no_copy(); 2];
    |                                ^^^^^^^^^ the trait `Copy` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
+   = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
    = help: consider creating a new `const` item and initializing it with the result of the function call to be used in the repeat position, like `const VAL: Type = const_fn();` and `let x = [VAL; 42];`
    = help: create an inline `const` block, see RFC #2920 <https://github.com/rust-lang/rfcs/pull/2920> for more information
diff --git a/src/test/ui/consts/const-blocks/migrate-fail.stderr b/src/test/ui/consts/const-blocks/migrate-fail.stderr
index 803281c0794..928ffd0839d 100644
--- a/src/test/ui/consts/const-blocks/migrate-fail.stderr
+++ b/src/test/ui/consts/const-blocks/migrate-fail.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
    |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
+   = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
    |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
+   = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
diff --git a/src/test/ui/consts/const-blocks/nll-fail.stderr b/src/test/ui/consts/const-blocks/nll-fail.stderr
index 8841af15dc0..fede0084547 100644
--- a/src/test/ui/consts/const-blocks/nll-fail.stderr
+++ b/src/test/ui/consts/const-blocks/nll-fail.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
    |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
+   = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `Bar: Copy` is not satisfied
 LL |         let arr: [Option<Bar>; 2] = [x; 2];
    |                                      ^ the trait `Copy` is not implemented for `Bar`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<Bar>`
+   = note: required for `Option<Bar>` to implement `Copy`
    = note: the `Copy` trait is required because this value will be copied for each element of the array
 help: consider annotating `Bar` with `#[derive(Copy)]`
    |
diff --git a/src/test/ui/consts/const-blocks/trait-error.stderr b/src/test/ui/consts/const-blocks/trait-error.stderr
index ece200ad10b..b11dd4b8087 100644
--- a/src/test/ui/consts/const-blocks/trait-error.stderr
+++ b/src/test/ui/consts/const-blocks/trait-error.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `String: Copy` is not satisfied
 LL |     [Foo(String::new()); 4];
    |      ^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `String`
    |
-note: required because of the requirements on the impl of `Copy` for `Foo<String>`
+note: required for `Foo<String>` to implement `Copy`
   --> $DIR/trait-error.rs:1:10
    |
 LL | #[derive(Copy, Clone)]
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
index 345ead48151..9431fb33c53 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.32bit.stderr
@@ -278,26 +278,36 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
                ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
            }
 
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:147:62
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:147:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾allocN─╼ 00 00 00 00                         │ ╾──╼....
+           }
 
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:150:65
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:149:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 8, align: 4) {
+               ╾allocN─╼ ╾allocN─╼                         │ ╾──╼╾──╼
+           }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:157:5
+  --> $DIR/ub-wide-ptr.rs:155:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:161:5
+  --> $DIR/ub-wide-ptr.rs:159:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
index 501932cb95c..15ef703024a 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.64bit.stderr
@@ -278,26 +278,36 @@ LL | const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_,
                ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
            }
 
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:147:62
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:147:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-   |                                                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered null pointer, but expected a vtable pointer
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾──────allocN───────╼ 00 00 00 00 00 00 00 00 │ ╾──────╼........
+           }
 
-error[E0080]: evaluation of constant value failed
-  --> $DIR/ub-wide-ptr.rs:150:65
+error[E0080]: it is undefined behavior to use this value
+  --> $DIR/ub-wide-ptr.rs:149:1
    |
 LL | const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-   |                                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constructing invalid value: encountered allocN, but expected a vtable pointer
+   |
+   = 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.
+   = note: the raw bytes of the constant (size: 16, align: 8) {
+               ╾──────allocN───────╼ ╾──────allocN───────╼ │ ╾──────╼╾──────╼
+           }
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:157:5
+  --> $DIR/ub-wide-ptr.rs:155:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, 0usize))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/ub-wide-ptr.rs:161:5
+  --> $DIR/ub-wide-ptr.rs:159:5
    |
 LL |     mem::transmute::<_, &dyn Trait>((&92u8, &3u64))
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ using allocN as vtable pointer but it does not point to a vtable
diff --git a/src/test/ui/consts/const-eval/ub-wide-ptr.rs b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
index a0377ab1efd..2da694a8bc4 100644
--- a/src/test/ui/consts/const-eval/ub-wide-ptr.rs
+++ b/src/test/ui/consts/const-eval/ub-wide-ptr.rs
@@ -145,11 +145,9 @@ const TRAIT_OBJ_CONTENT_INVALID: &dyn Trait = unsafe { mem::transmute::<_, &bool
 
 // # raw trait object
 const RAW_TRAIT_OBJ_VTABLE_NULL: *const dyn Trait = unsafe { mem::transmute((&92u8, 0usize)) };
-//~^ ERROR evaluation of constant value failed
-//~| null pointer
+//~^ ERROR it is undefined behavior to use this value
 const RAW_TRAIT_OBJ_VTABLE_INVALID: *const dyn Trait = unsafe { mem::transmute((&92u8, &3u64)) };
-//~^ ERROR evaluation of constant value failed
-//~| does not point to a vtable
+//~^ ERROR it is undefined behavior to use this value
 const RAW_TRAIT_OBJ_CONTENT_INVALID: *const dyn Trait = unsafe { mem::transmute::<_, &bool>(&3u8) } as *const dyn Trait; // ok because raw
 
 // Const eval fails for these, so they need to be statics to error.
diff --git a/src/test/ui/consts/issue-32829-2.stderr b/src/test/ui/consts/issue-32829-2.stderr
index b94bdc0e3df..0fec3581873 100644
--- a/src/test/ui/consts/issue-32829-2.stderr
+++ b/src/test/ui/consts/issue-32829-2.stderr
@@ -13,6 +13,7 @@ LL |         invalid();
    |         ^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error[E0015]: cannot call non-const fn `invalid` in statics
   --> $DIR/issue-32829-2.rs:54:9
@@ -21,6 +22,7 @@ LL |         invalid();
    |         ^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/consts/issue-36163.stderr b/src/test/ui/consts/issue-36163.stderr
index 4797d10b7a8..0626ec4bcbe 100644
--- a/src/test/ui/consts/issue-36163.stderr
+++ b/src/test/ui/consts/issue-36163.stderr
@@ -8,7 +8,7 @@ note: ...which requires const-evaluating + checking `A`...
   --> $DIR/issue-36163.rs:1:1
    |
 LL | const A: isize = Foo::B as isize;
-   | ^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: ...which again requires const-evaluating + checking `Foo::B::{constant#0}`, completing the cycle
 note: cycle used when simplifying constant for the type system `Foo::B::{constant#0}`
   --> $DIR/issue-36163.rs:4:9
diff --git a/src/test/ui/consts/mir_check_nonconst.stderr b/src/test/ui/consts/mir_check_nonconst.stderr
index 2bac995eebf..1e0652722ff 100644
--- a/src/test/ui/consts/mir_check_nonconst.stderr
+++ b/src/test/ui/consts/mir_check_nonconst.stderr
@@ -5,6 +5,7 @@ LL | static foo: Foo = bar();
    |                   ^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs
index d66faa086de..67a27729db7 100644
--- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs
+++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.rs
@@ -7,7 +7,6 @@ struct Error;
 enum Enum {
    A {
      x: Error //~ ERROR
-//~^ ERROR
    }
 }
 
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
index f655600b760..9953154fd4b 100644
--- a/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
+++ b/src/test/ui/derives/derives-span-PartialEq-enum-struct-variant.stderr
@@ -18,26 +18,6 @@ help: consider annotating `Error` with `#[derive(PartialEq)]`
 LL | #[derive(PartialEq)]
    |
 
-error[E0369]: binary operation `!=` cannot be applied to type `Error`
-  --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:9:6
-   |
-LL | #[derive(PartialEq)]
-   |          --------- in this derive macro expansion
-...
-LL |      x: Error
-   |      ^^^^^^^^
-   |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
-  --> $DIR/derives-span-PartialEq-enum-struct-variant.rs:4:1
-   |
-LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider annotating `Error` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.rs b/src/test/ui/derives/derives-span-PartialEq-enum.rs
index 66edf460b31..0becc7e0d10 100644
--- a/src/test/ui/derives/derives-span-PartialEq-enum.rs
+++ b/src/test/ui/derives/derives-span-PartialEq-enum.rs
@@ -7,8 +7,7 @@ struct Error;
 enum Enum {
    A(
      Error //~ ERROR
-//~^ ERROR
-     )
+   )
 }
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-enum.stderr b/src/test/ui/derives/derives-span-PartialEq-enum.stderr
index ce4b00bfbf5..7c130452301 100644
--- a/src/test/ui/derives/derives-span-PartialEq-enum.stderr
+++ b/src/test/ui/derives/derives-span-PartialEq-enum.stderr
@@ -18,26 +18,6 @@ help: consider annotating `Error` with `#[derive(PartialEq)]`
 LL | #[derive(PartialEq)]
    |
 
-error[E0369]: binary operation `!=` cannot be applied to type `Error`
-  --> $DIR/derives-span-PartialEq-enum.rs:9:6
-   |
-LL | #[derive(PartialEq)]
-   |          --------- in this derive macro expansion
-...
-LL |      Error
-   |      ^^^^^
-   |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
-  --> $DIR/derives-span-PartialEq-enum.rs:4:1
-   |
-LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider annotating `Error` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.rs b/src/test/ui/derives/derives-span-PartialEq-struct.rs
index ce5c67af77f..c92ef5fadf7 100644
--- a/src/test/ui/derives/derives-span-PartialEq-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialEq-struct.rs
@@ -6,7 +6,6 @@ struct Error;
 #[derive(PartialEq)]
 struct Struct {
     x: Error //~ ERROR
-//~^ ERROR
 }
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-struct.stderr
index c5c8f255fb3..ba3d6ced3f4 100644
--- a/src/test/ui/derives/derives-span-PartialEq-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialEq-struct.stderr
@@ -18,26 +18,6 @@ help: consider annotating `Error` with `#[derive(PartialEq)]`
 LL | #[derive(PartialEq)]
    |
 
-error[E0369]: binary operation `!=` cannot be applied to type `Error`
-  --> $DIR/derives-span-PartialEq-struct.rs:8:5
-   |
-LL | #[derive(PartialEq)]
-   |          --------- in this derive macro expansion
-LL | struct Struct {
-LL |     x: Error
-   |     ^^^^^^^^
-   |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
-  --> $DIR/derives-span-PartialEq-struct.rs:4:1
-   |
-LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider annotating `Error` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs
index eaa62831136..10ac347aa0b 100644
--- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs
+++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.rs
@@ -6,7 +6,6 @@ struct Error;
 #[derive(PartialEq)]
 struct Struct(
     Error //~ ERROR
-//~^ ERROR
 );
 
 fn main() {}
diff --git a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
index f5d609cb33f..ab0b56a9eef 100644
--- a/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
+++ b/src/test/ui/derives/derives-span-PartialEq-tuple-struct.stderr
@@ -18,26 +18,6 @@ help: consider annotating `Error` with `#[derive(PartialEq)]`
 LL | #[derive(PartialEq)]
    |
 
-error[E0369]: binary operation `!=` cannot be applied to type `Error`
-  --> $DIR/derives-span-PartialEq-tuple-struct.rs:8:5
-   |
-LL | #[derive(PartialEq)]
-   |          --------- in this derive macro expansion
-LL | struct Struct(
-LL |     Error
-   |     ^^^^^
-   |
-note: an implementation of `PartialEq<_>` might be missing for `Error`
-  --> $DIR/derives-span-PartialEq-tuple-struct.rs:4:1
-   |
-LL | struct Error;
-   | ^^^^^^^^^^^^ must implement `PartialEq<_>`
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider annotating `Error` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
-   |
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0369`.
diff --git a/src/test/ui/derives/deriving-copyclone.stderr b/src/test/ui/derives/deriving-copyclone.stderr
index 13097edf0ad..80e2dd7fede 100644
--- a/src/test/ui/derives/deriving-copyclone.stderr
+++ b/src/test/ui/derives/deriving-copyclone.stderr
@@ -2,11 +2,11 @@ error[E0277]: the trait bound `B<C>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:31:13
    |
 LL |     is_copy(B { a: 1, b: C });
-   |     ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
+   |     ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<C>`
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Copy` for `B<C>`
+note: required for `B<C>` to implement `Copy`
   --> $DIR/deriving-copyclone.rs:9:10
    |
 LL | #[derive(Copy, Clone)]
@@ -26,11 +26,11 @@ error[E0277]: the trait bound `B<C>: Clone` is not satisfied
   --> $DIR/deriving-copyclone.rs:32:14
    |
 LL |     is_clone(B { a: 1, b: C });
-   |     -------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Clone`
+   |     -------- ^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `B<C>`
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Clone` for `B<C>`
+note: required for `B<C>` to implement `Clone`
   --> $DIR/deriving-copyclone.rs:9:16
    |
 LL | #[derive(Copy, Clone)]
@@ -50,11 +50,11 @@ error[E0277]: the trait bound `B<D>: Copy` is not satisfied
   --> $DIR/deriving-copyclone.rs:35:13
    |
 LL |     is_copy(B { a: 1, b: D });
-   |     ------- ^^^^^^^^^^^^^^^^ expected an implementor of trait `Copy`
+   |     ------- ^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `B<D>`
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Copy` for `B<D>`
+note: required for `B<D>` to implement `Copy`
   --> $DIR/deriving-copyclone.rs:9:10
    |
 LL | #[derive(Copy, Clone)]
diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.rs b/src/test/ui/derives/deriving-no-inner-impl-error-message.rs
index 39e41a59ef4..b3ce31bf0d3 100644
--- a/src/test/ui/derives/deriving-no-inner-impl-error-message.rs
+++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.rs
@@ -3,7 +3,6 @@ struct NoCloneOrEq;
 #[derive(PartialEq)]
 struct E {
     x: NoCloneOrEq //~ ERROR binary operation `==` cannot be applied to type `NoCloneOrEq`
-         //~^ ERROR binary operation `!=` cannot be applied to type `NoCloneOrEq`
 }
 #[derive(Clone)]
 struct C {
diff --git a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
index 7875f072356..ef8c44caacf 100644
--- a/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
+++ b/src/test/ui/derives/deriving-no-inner-impl-error-message.stderr
@@ -18,28 +18,8 @@ help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
 LL | #[derive(PartialEq)]
    |
 
-error[E0369]: binary operation `!=` cannot be applied to type `NoCloneOrEq`
-  --> $DIR/deriving-no-inner-impl-error-message.rs:5:5
-   |
-LL | #[derive(PartialEq)]
-   |          --------- in this derive macro expansion
-LL | struct E {
-LL |     x: NoCloneOrEq
-   |     ^^^^^^^^^^^^^^
-   |
-note: an implementation of `PartialEq<_>` might be missing for `NoCloneOrEq`
-  --> $DIR/deriving-no-inner-impl-error-message.rs:1:1
-   |
-LL | struct NoCloneOrEq;
-   | ^^^^^^^^^^^^^^^^^^ must implement `PartialEq<_>`
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: consider annotating `NoCloneOrEq` with `#[derive(PartialEq)]`
-   |
-LL | #[derive(PartialEq)]
-   |
-
 error[E0277]: the trait bound `NoCloneOrEq: Clone` is not satisfied
-  --> $DIR/deriving-no-inner-impl-error-message.rs:10:5
+  --> $DIR/deriving-no-inner-impl-error-message.rs:9:5
    |
 LL | #[derive(Clone)]
    |          ----- in this derive macro expansion
@@ -53,7 +33,7 @@ help: consider annotating `NoCloneOrEq` with `#[derive(Clone)]`
 LL | #[derive(Clone)]
    |
 
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 Some errors have detailed explanations: E0277, E0369.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/deriving/deriving-all-codegen.stdout b/src/test/ui/deriving/deriving-all-codegen.stdout
index 21fe663f067..65f7dec8408 100644
--- a/src/test/ui/deriving/deriving-all-codegen.stdout
+++ b/src/test/ui/deriving/deriving-all-codegen.stdout
@@ -122,10 +122,6 @@ impl ::core::cmp::PartialEq for Point {
     fn eq(&self, other: &Point) -> bool {
         self.x == other.x && self.y == other.y
     }
-    #[inline]
-    fn ne(&self, other: &Point) -> bool {
-        self.x != other.x || self.y != other.y
-    }
 }
 impl ::core::marker::StructuralEq for Point {}
 #[automatically_derived]
@@ -239,13 +235,6 @@ impl ::core::cmp::PartialEq for Big {
                     self.b6 == other.b6 && self.b7 == other.b7 &&
             self.b8 == other.b8
     }
-    #[inline]
-    fn ne(&self, other: &Big) -> bool {
-        self.b1 != other.b1 || self.b2 != other.b2 || self.b3 != other.b3 ||
-                            self.b4 != other.b4 || self.b5 != other.b5 ||
-                    self.b6 != other.b6 || self.b7 != other.b7 ||
-            self.b8 != other.b8
-    }
 }
 impl ::core::marker::StructuralEq for Big {}
 #[automatically_derived]
@@ -361,8 +350,6 @@ impl ::core::marker::StructuralPartialEq for Unsized {}
 impl ::core::cmp::PartialEq for Unsized {
     #[inline]
     fn eq(&self, other: &Unsized) -> bool { self.0 == other.0 }
-    #[inline]
-    fn ne(&self, other: &Unsized) -> bool { self.0 != other.0 }
 }
 impl ::core::marker::StructuralEq for Unsized {}
 #[automatically_derived]
@@ -428,8 +415,6 @@ impl ::core::marker::StructuralPartialEq for PackedCopy {}
 impl ::core::cmp::PartialEq for PackedCopy {
     #[inline]
     fn eq(&self, other: &PackedCopy) -> bool { { self.0 } == { other.0 } }
-    #[inline]
-    fn ne(&self, other: &PackedCopy) -> bool { { self.0 } != { other.0 } }
 }
 impl ::core::marker::StructuralEq for PackedCopy {}
 #[automatically_derived]
@@ -503,12 +488,6 @@ impl ::core::cmp::PartialEq for PackedNonCopy {
         let Self(ref __self_1_0) = *other;
         *__self_0_0 == *__self_1_0
     }
-    #[inline]
-    fn ne(&self, other: &PackedNonCopy) -> bool {
-        let Self(ref __self_0_0) = *self;
-        let Self(ref __self_1_0) = *other;
-        *__self_0_0 != *__self_1_0
-    }
 }
 impl ::core::marker::StructuralEq for PackedNonCopy {}
 #[automatically_derived]
@@ -638,13 +617,6 @@ impl ::core::cmp::PartialEq for Enum1 {
                 *__self_0 == *__arg1_0,
         }
     }
-    #[inline]
-    fn ne(&self, other: &Enum1) -> bool {
-        match (self, other) {
-            (Enum1::Single { x: __self_0 }, Enum1::Single { x: __arg1_0 }) =>
-                *__self_0 != *__arg1_0,
-        }
-    }
 }
 impl ::core::marker::StructuralEq for Enum1 {}
 #[automatically_derived]
@@ -883,20 +855,6 @@ impl ::core::cmp::PartialEq for Mixed {
                 _ => true,
             }
     }
-    #[inline]
-    fn ne(&self, other: &Mixed) -> bool {
-        let __self_tag = ::core::intrinsics::discriminant_value(self);
-        let __arg1_tag = ::core::intrinsics::discriminant_value(other);
-        __self_tag != __arg1_tag ||
-            match (self, other) {
-                (Mixed::R(__self_0), Mixed::R(__arg1_0)) =>
-                    *__self_0 != *__arg1_0,
-                (Mixed::S { d1: __self_0, d2: __self_1 }, Mixed::S {
-                    d1: __arg1_0, d2: __arg1_1 }) =>
-                    *__self_0 != *__arg1_0 || *__self_1 != *__arg1_1,
-                _ => false,
-            }
-    }
 }
 impl ::core::marker::StructuralEq for Mixed {}
 #[automatically_derived]
@@ -1023,21 +981,6 @@ impl ::core::cmp::PartialEq for Fielded {
                 _ => unsafe { ::core::intrinsics::unreachable() }
             }
     }
-    #[inline]
-    fn ne(&self, other: &Fielded) -> bool {
-        let __self_tag = ::core::intrinsics::discriminant_value(self);
-        let __arg1_tag = ::core::intrinsics::discriminant_value(other);
-        __self_tag != __arg1_tag ||
-            match (self, other) {
-                (Fielded::X(__self_0), Fielded::X(__arg1_0)) =>
-                    *__self_0 != *__arg1_0,
-                (Fielded::Y(__self_0), Fielded::Y(__arg1_0)) =>
-                    *__self_0 != *__arg1_0,
-                (Fielded::Z(__self_0), Fielded::Z(__arg1_0)) =>
-                    *__self_0 != *__arg1_0,
-                _ => unsafe { ::core::intrinsics::unreachable() }
-            }
-    }
 }
 impl ::core::marker::StructuralEq for Fielded {}
 #[automatically_derived]
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
index 26764bc0ee5..b69fcd5d32a 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-1.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
-  --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:8
+  --> $DIR/issue-21659-show-relevant-trait-impls-1.rs:24:12
    |
 LL |     f1.foo(1usize);
-   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        --- ^^^^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        |
+   |        required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<A>`:
              <Bar as Foo<i32>>
diff --git a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
index bb175367e1f..5e0e4a0115a 100644
--- a/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
+++ b/src/test/ui/did_you_mean/issue-21659-show-relevant-trait-impls-2.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Bar: Foo<usize>` is not satisfied
-  --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:8
+  --> $DIR/issue-21659-show-relevant-trait-impls-2.rs:28:12
    |
 LL |     f1.foo(1usize);
-   |        ^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        --- ^^^^^^ the trait `Foo<usize>` is not implemented for `Bar`
+   |        |
+   |        required by a bound introduced by this call
    |
    = help: the following other types implement trait `Foo<A>`:
              <Bar as Foo<i16>>
diff --git a/src/test/ui/drop/drop-foreign-fundamental.rs b/src/test/ui/drop/drop-foreign-fundamental.rs
new file mode 100644
index 00000000000..c43df40d6c2
--- /dev/null
+++ b/src/test/ui/drop/drop-foreign-fundamental.rs
@@ -0,0 +1,23 @@
+use std::ops::Deref;
+use std::pin::Pin;
+
+struct Whatever<T>(T);
+
+impl<T> Deref for Whatever<T> {
+    type Target = T;
+
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+struct A;
+
+impl Drop for Pin<Whatever<A>> {
+    //~^ ERROR  the `Drop` trait may only be implemented for local structs, enums, and unions
+    fn drop(&mut self) {}
+}
+
+fn main() {
+    let x = Pin::new(Whatever(1.0f32));
+}
diff --git a/src/test/ui/drop/drop-foreign-fundamental.stderr b/src/test/ui/drop/drop-foreign-fundamental.stderr
new file mode 100644
index 00000000000..fbd1ba08591
--- /dev/null
+++ b/src/test/ui/drop/drop-foreign-fundamental.stderr
@@ -0,0 +1,9 @@
+error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
+  --> $DIR/drop-foreign-fundamental.rs:16:15
+   |
+LL | impl Drop for Pin<Whatever<A>> {
+   |               ^^^^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0120`.
diff --git a/src/test/ui/dropck/drop-on-non-struct.rs b/src/test/ui/dropck/drop-on-non-struct.rs
index ef5e18126dc..145eab126c2 100644
--- a/src/test/ui/dropck/drop-on-non-struct.rs
+++ b/src/test/ui/dropck/drop-on-non-struct.rs
@@ -1,5 +1,5 @@
 impl<'a> Drop for &'a mut isize {
-    //~^ ERROR the `Drop` trait may only be implemented for structs, enums, and unions
+    //~^ ERROR the `Drop` trait may only be implemented for local structs, enums, and unions
     //~^^ ERROR E0117
     fn drop(&mut self) {
         println!("kaboom");
@@ -8,8 +8,7 @@ impl<'a> Drop for &'a mut isize {
 
 impl Drop for Nonexistent {
     //~^ ERROR cannot find type `Nonexistent`
-    fn drop(&mut self) { }
+    fn drop(&mut self) {}
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/src/test/ui/dropck/drop-on-non-struct.stderr b/src/test/ui/dropck/drop-on-non-struct.stderr
index e52728f3781..e8fbe5e9726 100644
--- a/src/test/ui/dropck/drop-on-non-struct.stderr
+++ b/src/test/ui/dropck/drop-on-non-struct.stderr
@@ -15,11 +15,11 @@ LL | impl<'a> Drop for &'a mut isize {
    |
    = note: define and implement a trait or new type instead
 
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
   --> $DIR/drop-on-non-struct.rs:1:19
    |
 LL | impl<'a> Drop for &'a mut isize {
-   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union
+   |                   ^^^^^^^^^^^^^ must be a struct, enum, or union in the current crate
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/error-codes/E0117.rs b/src/test/ui/error-codes/E0117.rs
index 22b48657385..406d24e3666 100644
--- a/src/test/ui/error-codes/E0117.rs
+++ b/src/test/ui/error-codes/E0117.rs
@@ -1,4 +1,4 @@
 impl Drop for u32 {} //~ ERROR E0117
-//~| ERROR the `Drop` trait may only be implemented for structs, enums, and unions
+//~| ERROR the `Drop` trait may only be implemented for local structs, enums, and unions
 
 fn main() {}
diff --git a/src/test/ui/error-codes/E0117.stderr b/src/test/ui/error-codes/E0117.stderr
index 76d9f5cc0e5..f144aa9f72c 100644
--- a/src/test/ui/error-codes/E0117.stderr
+++ b/src/test/ui/error-codes/E0117.stderr
@@ -9,11 +9,11 @@ LL | impl Drop for u32 {}
    |
    = note: define and implement a trait or new type instead
 
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
   --> $DIR/E0117.rs:1:15
    |
 LL | impl Drop for u32 {}
-   |               ^^^ must be a struct, enum, or union
+   |               ^^^ must be a struct, enum, or union in the current crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/error-codes/E0120.stderr b/src/test/ui/error-codes/E0120.stderr
index 6c306455e42..75778f1f94a 100644
--- a/src/test/ui/error-codes/E0120.stderr
+++ b/src/test/ui/error-codes/E0120.stderr
@@ -1,8 +1,8 @@
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
   --> $DIR/E0120.rs:3:15
    |
 LL | impl Drop for dyn MyTrait {
-   |               ^^^^^^^^^^^ must be a struct, enum, or union
+   |               ^^^^^^^^^^^ must be a struct, enum, or union in the current crate
 
 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 dfffbb182ad..87cfaa489c6 100644
--- a/src/test/ui/error-codes/E0275.stderr
+++ b/src/test/ui/error-codes/E0275.stderr
@@ -5,13 +5,13 @@ LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by 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 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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/E0275.rs:5:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |         ^^^     ^
    = note: 127 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Foo` for `Bar<T>`
+   = note: required for `Bar<T>` to implement `Foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/error-codes/E0277-2.stderr b/src/test/ui/error-codes/E0277-2.stderr
index ca2cb884240..a2abf37931a 100644
--- a/src/test/ui/error-codes/E0277-2.stderr
+++ b/src/test/ui/error-codes/E0277-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `*const u8` cannot be sent between threads safely
-  --> $DIR/E0277-2.rs:16:5
+  --> $DIR/E0277-2.rs:16:15
    |
 LL |     is_send::<Foo>();
-   |     ^^^^^^^^^^^^^^ `*const u8` cannot be sent between threads safely
+   |               ^^^ `*const u8` cannot be sent between threads safely
    |
    = help: within `Foo`, the trait `Send` is not implemented for `*const u8`
 note: required because it appears within the type `Baz`
diff --git a/src/test/ui/extern/extern-types-unsized.stderr b/src/test/ui/extern/extern-types-unsized.stderr
index 8d6713261d5..a79caced111 100644
--- a/src/test/ui/extern/extern-types-unsized.stderr
+++ b/src/test/ui/extern/extern-types-unsized.stderr
@@ -16,10 +16,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:25:5
+  --> $DIR/extern-types-unsized.rs:25:20
    |
 LL |     assert_sized::<Foo>();
-   |     ^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^ doesn't have a size known at compile-time
    |
    = help: within `Foo`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Foo`
@@ -38,10 +38,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:28:5
+  --> $DIR/extern-types-unsized.rs:28:20
    |
 LL |     assert_sized::<Bar<A>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Bar<A>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
@@ -60,10 +60,10 @@ LL | fn assert_sized<T: ?Sized>() {}
    |                  ++++++++
 
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/extern-types-unsized.rs:31:5
+  --> $DIR/extern-types-unsized.rs:31:20
    |
 LL |     assert_sized::<Bar<Bar<A>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `Bar<Bar<A>>`, the trait `Sized` is not implemented for `A`
 note: required because it appears within the type `Bar<A>`
diff --git a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
index 0557340f792..b7757740d9e 100644
--- a/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
+++ b/src/test/ui/feature-gates/feature-gate-unsized_fn_params.stderr
@@ -15,9 +15,7 @@ error[E0277]: the size for values of type `(dyn Foo + 'static)` cannot be known
   --> $DIR/feature-gate-unsized_fn_params.rs:24:9
    |
 LL |     foo(*x);
-   |     --- ^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `(dyn Foo + 'static)`
    = help: unsized fn params are gated as an unstable feature
diff --git a/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs
new file mode 100644
index 00000000000..49f1cba7151
--- /dev/null
+++ b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.rs
@@ -0,0 +1,30 @@
+// check-fail
+// This file is used to test the behavior of the early-pass syntax warnings.
+// If macro syntax is stabilized, replace with a different unstable syntax.
+
+macro a() {}
+//~^ ERROR: `macro` is experimental
+
+#[cfg(FALSE)]
+macro b() {}
+
+macro_rules! identity {
+    ($($x:tt)*) => ($($x)*);
+}
+
+identity! {
+    macro c() {}
+    //~^ ERROR: `macro` is experimental
+}
+
+#[cfg(FALSE)]
+identity! {
+    macro d() {} // No error
+}
+
+identity! {
+    #[cfg(FALSE)]
+    macro e() {}
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr
new file mode 100644
index 00000000000..49550d811ba
--- /dev/null
+++ b/src/test/ui/feature-gates/soft-syntax-gates-with-errors.stderr
@@ -0,0 +1,21 @@
+error[E0658]: `macro` is experimental
+  --> $DIR/soft-syntax-gates-with-errors.rs:5:1
+   |
+LL | macro a() {}
+   | ^^^^^^^^^^^^
+   |
+   = note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
+   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
+
+error[E0658]: `macro` is experimental
+  --> $DIR/soft-syntax-gates-with-errors.rs:16:5
+   |
+LL |     macro c() {}
+   |     ^^^^^^^^^^^^
+   |
+   = note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
+   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs
new file mode 100644
index 00000000000..ca4ad2320f6
--- /dev/null
+++ b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.rs
@@ -0,0 +1,26 @@
+// check-pass
+// This file is used to test the behavior of the early-pass syntax warnings.
+// If macro syntax is stabilized, replace with a different unstable syntax.
+
+#[cfg(FALSE)]
+macro b() {}
+//~^ WARN: `macro` is experimental
+//~| WARN: unstable syntax
+
+macro_rules! identity {
+    ($($x:tt)*) => ($($x)*);
+}
+
+#[cfg(FALSE)]
+identity! {
+    macro d() {} // No error
+}
+
+identity! {
+    #[cfg(FALSE)]
+    macro e() {}
+    //~^ WARN: `macro` is experimental
+    //~| WARN: unstable syntax
+}
+
+fn main() {}
diff --git a/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr
new file mode 100644
index 00000000000..3d9c22e5487
--- /dev/null
+++ b/src/test/ui/feature-gates/soft-syntax-gates-without-errors.stderr
@@ -0,0 +1,24 @@
+warning: `macro` is experimental
+  --> $DIR/soft-syntax-gates-without-errors.rs:6:1
+   |
+LL | macro b() {}
+   | ^^^^^^^^^^^^
+   |
+   = note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
+   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: `macro` is experimental
+  --> $DIR/soft-syntax-gates-without-errors.rs:21:5
+   |
+LL |     macro e() {}
+   |     ^^^^^^^^^^^^
+   |
+   = note: see issue #39412 <https://github.com/rust-lang/rust/issues/39412> for more information
+   = help: add `#![feature(decl_macro)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/fmt/ifmt-unimpl.stderr b/src/test/ui/fmt/ifmt-unimpl.stderr
index dbcb2eb6693..0e34f913511 100644
--- a/src/test/ui/fmt/ifmt-unimpl.stderr
+++ b/src/test/ui/fmt/ifmt-unimpl.stderr
@@ -14,7 +14,7 @@ LL |     format!("{:X}", "3");
              NonZeroI8
              NonZeroIsize
            and 21 others
-   = note: required because of the requirements on the impl of `UpperHex` for `&str`
+   = note: required for `&str` to implement `UpperHex`
 note: required by a bound in `ArgumentV1::<'a>::new_upper_hex`
   --> $SRC_DIR/core/src/fmt/mod.rs:LL:COL
    |
diff --git a/src/test/ui/fmt/send-sync.stderr b/src/test/ui/fmt/send-sync.stderr
index 7c7a3c8846b..3ed040c3ab3 100644
--- a/src/test/ui/fmt/send-sync.stderr
+++ b/src/test/ui/fmt/send-sync.stderr
@@ -1,14 +1,16 @@
 error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
-  --> $DIR/send-sync.rs:8:5
+  --> $DIR/send-sync.rs:8:10
    |
 LL |     send(format_args!("{:?}", c));
-   |     ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `[ArgumentV1<'_>]`, the trait `Sync` is not implemented for `core::fmt::Opaque`
    = note: required because it appears within the type `&core::fmt::Opaque`
    = note: required because it appears within the type `ArgumentV1<'_>`
    = note: required because it appears within the type `[ArgumentV1<'_>]`
-   = note: required because of the requirements on the impl of `Send` for `&[ArgumentV1<'_>]`
+   = note: required for `&[ArgumentV1<'_>]` to implement `Send`
    = note: required because it appears within the type `Arguments<'_>`
 note: required by a bound in `send`
   --> $DIR/send-sync.rs:1:12
@@ -17,10 +19,12 @@ LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `core::fmt::Opaque` cannot be shared between threads safely
-  --> $DIR/send-sync.rs:9:5
+  --> $DIR/send-sync.rs:9:10
    |
 LL |     sync(format_args!("{:?}", c));
-   |     ^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     ---- ^^^^^^^^^^^^^^^^^^^^^^^ `core::fmt::Opaque` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Arguments<'_>`, the trait `Sync` is not implemented for `core::fmt::Opaque`
    = note: required because it appears within the type `&core::fmt::Opaque`
diff --git a/src/test/ui/for/for-c-in-str.rs b/src/test/ui/for/for-c-in-str.rs
index 86a1c1a34e9..b086128d28c 100644
--- a/src/test/ui/for/for-c-in-str.rs
+++ b/src/test/ui/for/for-c-in-str.rs
@@ -5,7 +5,7 @@ fn main() {
         //~^ ERROR `&str` is not an iterator
         //~| NOTE `&str` is not an iterator
         //~| HELP the trait `Iterator` is not implemented for `&str`
-        //~| NOTE required because of the requirements on the impl of `IntoIterator` for `&str`
+        //~| NOTE required for `&str` to implement `IntoIterator`
         //~| NOTE in this expansion of desugaring of `for` loop
         //~| NOTE in this expansion of desugaring of `for` loop
         //~| NOTE in this expansion of desugaring of `for` loop
diff --git a/src/test/ui/for/for-c-in-str.stderr b/src/test/ui/for/for-c-in-str.stderr
index 07ddc8ea78f..959a7c43fff 100644
--- a/src/test/ui/for/for-c-in-str.stderr
+++ b/src/test/ui/for/for-c-in-str.stderr
@@ -5,7 +5,7 @@ LL |     for c in "asdf" {
    |              ^^^^^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `&str`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&str`
+   = note: required for `&str` to implement `IntoIterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/for/for-loop-bogosity.stderr b/src/test/ui/for/for-loop-bogosity.stderr
index 0bdd75b3555..9bf8056e82e 100644
--- a/src/test/ui/for/for-loop-bogosity.stderr
+++ b/src/test/ui/for/for-loop-bogosity.stderr
@@ -5,7 +5,7 @@ LL |     for x in bogus {
    |              ^^^^^ `MyStruct` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `MyStruct`
-   = note: required because of the requirements on the impl of `IntoIterator` for `MyStruct`
+   = note: required for `MyStruct` to implement `IntoIterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/generator/drop-tracking-parent-expression.stderr b/src/test/ui/generator/drop-tracking-parent-expression.stderr
index 522a300b3ed..fbf5d6e0725 100644
--- a/src/test/ui/generator/drop-tracking-parent-expression.stderr
+++ b/src/test/ui/generator/drop-tracking-parent-expression.stderr
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -41,10 +41,10 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
@@ -83,10 +83,10 @@ LL | fn assert_send<T: Send>(_thing: T) {}
    = note: this error originates in the macro `type_combinations` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-tracking-parent-expression.rs:24:13
+  --> $DIR/drop-tracking-parent-expression.rs:24:25
    |
 LL |               assert_send(g);
-   |               ^^^^^^^^^^^ generator is not `Send`
+   |                           ^ generator is not `Send`
 ...
 LL | /     type_combinations!(
 LL | |         // OK
diff --git a/src/test/ui/generator/drop-yield-twice.stderr b/src/test/ui/generator/drop-yield-twice.stderr
index 5bc6ea5600f..0808a2c85ee 100644
--- a/src/test/ui/generator/drop-yield-twice.stderr
+++ b/src/test/ui/generator/drop-yield-twice.stderr
@@ -1,8 +1,14 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/drop-yield-twice.rs:7:5
+  --> $DIR/drop-yield-twice.rs:7:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |         let guard = Foo(42);
+LL | |         yield;
+LL | |         drop(guard);
+LL | |         yield;
+LL | |     })
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/drop-yield-twice.rs:7:17: 7:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
diff --git a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
index 2a39a08ee39..8f5d2429a28 100644
--- a/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
+++ b/src/test/ui/generator/generator-yielding-or-returning-itself.stderr
@@ -1,8 +1,15 @@
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36] as Generator>::Return == [generator@$DIR/generator-yielding-or-returning-itself.rs:15:34: 15:36]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:15:5
+  --> $DIR/generator-yielding-or-returning-itself.rs:15:34
    |
-LL |     want_cyclic_generator_return(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+LL |       want_cyclic_generator_return(|| {
+   |  _____----------------------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         if false { yield None.unwrap(); }
+LL | |         None.unwrap()
+LL | |     })
+   | |_____^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
@@ -17,10 +24,17 @@ LL |     where T: Generator<Yield = (), Return = T>
    |                                    ^^^^^^^^^^ required by this bound in `want_cyclic_generator_return`
 
 error[E0271]: type mismatch resolving `<[generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35] as Generator>::Yield == [generator@$DIR/generator-yielding-or-returning-itself.rs:28:33: 28:35]`
-  --> $DIR/generator-yielding-or-returning-itself.rs:28:5
+  --> $DIR/generator-yielding-or-returning-itself.rs:28:33
    |
-LL |     want_cyclic_generator_yield(|| {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ cyclic type of infinite size
+LL |       want_cyclic_generator_yield(|| {
+   |  _____---------------------------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         if false { yield None.unwrap(); }
+LL | |         None.unwrap()
+LL | |     })
+   | |_____^ cyclic type of infinite size
    |
    = note: closures cannot capture themselves or take themselves as argument;
            this error may be the result of a recent compiler bug-fix,
diff --git a/src/test/ui/generator/issue-68112.rs b/src/test/ui/generator/issue-68112.rs
index 3fcef773b68..21026f45cb8 100644
--- a/src/test/ui/generator/issue-68112.rs
+++ b/src/test/ui/generator/issue-68112.rs
@@ -63,7 +63,8 @@ fn test2() {
     require_send(send_gen);
     //~^ ERROR `RefCell<i32>` cannot be shared between threads safely
     //~| NOTE `RefCell<i32>` cannot be shared between threads safely
-    //~| NOTE requirements on the impl
+    //~| NOTE required for
+    //~| NOTE required by a bound introduced by this call
     //~| NOTE captures the following types
 }
 
diff --git a/src/test/ui/generator/issue-68112.stderr b/src/test/ui/generator/issue-68112.stderr
index 1d5b97e984f..eb99d42c920 100644
--- a/src/test/ui/generator/issue-68112.stderr
+++ b/src/test/ui/generator/issue-68112.stderr
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/issue-68112.rs:40:5
+  --> $DIR/issue-68112.rs:40:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |                  ^^^^^^^^ generator is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: generator is not `Send` as this value is used across a yield
@@ -23,13 +23,15 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/issue-68112.rs:63:5
+  --> $DIR/issue-68112.rs:63:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
-   = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
+   = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this generator
   --> $DIR/issue-68112.rs:48:5
    |
diff --git a/src/test/ui/generator/not-send-sync.stderr b/src/test/ui/generator/not-send-sync.stderr
index 0b31bb4fdb1..a821c57b923 100644
--- a/src/test/ui/generator/not-send-sync.stderr
+++ b/src/test/ui/generator/not-send-sync.stderr
@@ -1,11 +1,18 @@
 error[E0277]: `Cell<i32>` cannot be shared between threads safely
-  --> $DIR/not-send-sync.rs:16:5
+  --> $DIR/not-send-sync.rs:16:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
+LL |       assert_send(|| {
+   |  _____-----------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^ `Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
-   = note: required because of the requirements on the impl of `Send` for `&Cell<i32>`
+   = note: required for `&Cell<i32>` to implement `Send`
 note: required because it's used within this generator
   --> $DIR/not-send-sync.rs:16:17
    |
@@ -18,10 +25,15 @@ LL |     fn assert_send<T: Send>(_: T) {}
    |                       ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be shared between threads safely
-  --> $DIR/not-send-sync.rs:9:5
-   |
-LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+  --> $DIR/not-send-sync.rs:9:17
+   |
+LL |       assert_sync(|| {
+   |  _________________^
+LL | |
+LL | |         let a = Cell::new(2);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Sync`
    |
    = help: within `[generator@$DIR/not-send-sync.rs:9:17: 9:19]`, the trait `Sync` is not implemented for `Cell<i32>`
 note: generator is not `Sync` as this value is used across a yield
diff --git a/src/test/ui/generator/partial-drop.stderr b/src/test/ui/generator/partial-drop.stderr
index 1004fc64da9..9baafe54e84 100644
--- a/src/test/ui/generator/partial-drop.stderr
+++ b/src/test/ui/generator/partial-drop.stderr
@@ -1,8 +1,15 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:14:5
+  --> $DIR/partial-drop.rs:14:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+LL | |         drop(guard.foo);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:14:17: 14:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
@@ -22,10 +29,17 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:22:5
+  --> $DIR/partial-drop.rs:22:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+...  |
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:22:17: 22:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
@@ -45,10 +59,17 @@ LL | fn assert_send<T: Send>(_: T) {}
    |                   ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be sent between threads safely
-  --> $DIR/partial-drop.rs:32:5
+  --> $DIR/partial-drop.rs:32:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ generator is not `Send`
+LL |       assert_send(|| {
+   |  _________________^
+LL | |
+LL | |         // FIXME: it would be nice to make this work.
+LL | |         let guard = Bar { foo: Foo, x: 42 };
+...  |
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Send`
    |
    = help: within `[generator@$DIR/partial-drop.rs:32:17: 32:19]`, the trait `Send` is not implemented for `Foo`
 note: generator is not `Send` as this value is used across a yield
diff --git a/src/test/ui/generator/print/generator-print-verbose-1.stderr b/src/test/ui/generator/print/generator-print-verbose-1.stderr
index 5b61f1e8f2d..3a83021dd99 100644
--- a/src/test/ui/generator/print/generator-print-verbose-1.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-1.stderr
@@ -1,8 +1,8 @@
 error: generator cannot be sent between threads safely
-  --> $DIR/generator-print-verbose-1.rs:37:5
+  --> $DIR/generator-print-verbose-1.rs:37:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ generator is not `Send`
+   |                  ^^^^^^^^ generator is not `Send`
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
 note: generator is not `Send` as this value is used across a yield
@@ -21,13 +21,15 @@ LL | fn require_send(_: impl Send) {}
    |                         ^^^^ required by this bound in `require_send`
 
 error[E0277]: `RefCell<i32>` cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-1.rs:56:5
+  --> $DIR/generator-print-verbose-1.rs:56:18
    |
 LL |     require_send(send_gen);
-   |     ^^^^^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     ------------ ^^^^^^^^ `RefCell<i32>` cannot be shared between threads safely
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `RefCell<i32>`
-   = note: required because of the requirements on the impl of `Send` for `Arc<RefCell<i32>>`
+   = note: required for `Arc<RefCell<i32>>` to implement `Send`
 note: required because it's used within this generator
   --> $DIR/generator-print-verbose-1.rs:42:5
    |
diff --git a/src/test/ui/generator/print/generator-print-verbose-2.stderr b/src/test/ui/generator/print/generator-print-verbose-2.stderr
index eb79d2e6eed..909e49c38b8 100644
--- a/src/test/ui/generator/print/generator-print-verbose-2.stderr
+++ b/src/test/ui/generator/print/generator-print-verbose-2.stderr
@@ -1,11 +1,18 @@
 error[E0277]: `Cell<i32>` cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-2.rs:19:5
+  --> $DIR/generator-print-verbose-2.rs:19:17
    |
-LL |     assert_send(|| {
-   |     ^^^^^^^^^^^ `Cell<i32>` cannot be shared between threads safely
+LL |       assert_send(|| {
+   |  _____-----------_^
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         drop(&a);
+LL | |         yield;
+LL | |     });
+   | |_____^ `Cell<i32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
-   = note: required because of the requirements on the impl of `Send` for `&'_#4r Cell<i32>`
+   = note: required for `&'_#4r Cell<i32>` to implement `Send`
 note: required because it's used within this generator
   --> $DIR/generator-print-verbose-2.rs:19:17
    |
@@ -18,10 +25,15 @@ LL |     fn assert_send<T: Send>(_: T) {}
    |                       ^^^^ required by this bound in `assert_send`
 
 error: generator cannot be shared between threads safely
-  --> $DIR/generator-print-verbose-2.rs:12:5
-   |
-LL |     assert_sync(|| {
-   |     ^^^^^^^^^^^ generator is not `Sync`
+  --> $DIR/generator-print-verbose-2.rs:12:17
+   |
+LL |       assert_sync(|| {
+   |  _________________^
+LL | |
+LL | |         let a = Cell::new(2);
+LL | |         yield;
+LL | |     });
+   | |_____^ generator is not `Sync`
    |
    = help: within `[main::{closure#0} upvar_tys=() {Cell<i32>, ()}]`, the trait `Sync` is not implemented for `Cell<i32>`
 note: generator is not `Sync` as this value is used across a yield
diff --git a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr
index ee1afbe5b58..dcfb211744c 100644
--- a/src/test/ui/generator/yield-outside-generator-issue-78653.stderr
+++ b/src/test/ui/generator/yield-outside-generator-issue-78653.stderr
@@ -12,7 +12,7 @@ LL |     yield || for i in 0 { }
    |
    = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
+   = note: required for `{integer}` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
index 98c304cc90b..8193f491e69 100644
--- a/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
+++ b/src/test/ui/generic-associated-types/bugs/issue-88460.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `for<'a> <_ as Trait>::Assoc<'a>: Marker` is not satisfied
-  --> $DIR/issue-88460.rs:30:5
+  --> $DIR/issue-88460.rs:30:10
    |
 LL |     test(Foo);
-   |     ^^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
+   |     ---- ^^^ the trait `for<'a> Marker` is not implemented for `<_ as Trait>::Assoc<'a>`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Marker` is implemented for `()`
 note: required by a bound in `test`
diff --git a/src/test/ui/generic-associated-types/impl_bounds.stderr b/src/test/ui/generic-associated-types/impl_bounds.stderr
index ce79c635add..4f8d673d1cf 100644
--- a/src/test/ui/generic-associated-types/impl_bounds.stderr
+++ b/src/test/ui/generic-associated-types/impl_bounds.stderr
@@ -42,7 +42,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL |     type C = String where Self: Copy;
    |                                 ^^^^ the trait `Copy` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+note: required for `Fooy<T>` to implement `Copy`
   --> $DIR/impl_bounds.rs:11:10
    |
 LL | #[derive(Copy, Clone)]
@@ -67,7 +67,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL |     fn d() where Self: Copy {}
    |                        ^^^^ the trait `Copy` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Copy` for `Fooy<T>`
+note: required for `Fooy<T>` to implement `Copy`
   --> $DIR/impl_bounds.rs:11:10
    |
 LL | #[derive(Copy, Clone)]
diff --git a/src/test/ui/generic-associated-types/issue-74824.stderr b/src/test/ui/generic-associated-types/issue-74824.stderr
index 8517eb9fa21..eabc806c2b7 100644
--- a/src/test/ui/generic-associated-types/issue-74824.stderr
+++ b/src/test/ui/generic-associated-types/issue-74824.stderr
@@ -16,7 +16,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
 LL |     type Copy<T>: Copy = Box<T>;
    |                          ^^^^^^ the trait `Clone` is not implemented for `T`
    |
-   = note: required because of the requirements on the impl of `Clone` for `Box<T>`
+   = note: required for `Box<T>` to implement `Clone`
 note: required by a bound in `UnsafeCopy::Copy`
   --> $DIR/issue-74824.rs:7:19
    |
diff --git a/src/test/ui/generic-associated-types/issue-76535.base.stderr b/src/test/ui/generic-associated-types/issue-76535.base.stderr
index 5decd58bbcd..fe5fe964e99 100644
--- a/src/test/ui/generic-associated-types/issue-76535.base.stderr
+++ b/src/test/ui/generic-associated-types/issue-76535.base.stderr
@@ -43,7 +43,7 @@ LL | pub trait SuperTrait {
 LL |     type SubType<'a>: SubTrait where Self: 'a;
    |          ^^^^^^^ ...because it contains the generic associated type `SubType`
    = help: consider moving `SubType` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>` for `Box<SuperStruct>`
+   = note: required for `Box<SuperStruct>` to implement `CoerceUnsized<Box<dyn SuperTrait<SubType = SubStruct<'_>>>>`
    = note: required by cast to type `Box<dyn SuperTrait<SubType = SubStruct<'_>>>`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/generic-associated-types/issue-79422.base.stderr b/src/test/ui/generic-associated-types/issue-79422.base.stderr
index 404c975d64a..0ed75ba1efc 100644
--- a/src/test/ui/generic-associated-types/issue-79422.base.stderr
+++ b/src/test/ui/generic-associated-types/issue-79422.base.stderr
@@ -43,7 +43,7 @@ LL | trait MapLike<K, V> {
 LL |     type VRefCont<'a>: RefCont<'a, V> where Self: 'a;
    |          ^^^^^^^^ ...because it contains the generic associated type `VRefCont`
    = help: consider moving `VRefCont` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>` for `Box<BTreeMap<u8, u8>>`
+   = note: required for `Box<BTreeMap<u8, u8>>` to implement `CoerceUnsized<Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>>`
    = note: required by cast to type `Box<dyn MapLike<u8, u8, VRefCont = (dyn RefCont<'_, u8> + 'static)>>`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
index 51017ffbd41..ab5598e364f 100644
--- a/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/issue-62203-hrtb-ice.stderr
@@ -44,7 +44,7 @@ LL | |             },
 LL | |         },
    | |_________^ expected struct `Unit3`, found struct `Unit4`
    |
-note: required because of the requirements on the impl of `for<'r> T0<'r, (&'r u8,)>` for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>`
+note: required for `L<[closure@$DIR/issue-62203-hrtb-ice.rs:42:16: 42:19]>` to implement `for<'r> T0<'r, (&'r u8,)>`
   --> $DIR/issue-62203-hrtb-ice.rs:17:16
    |
 LL | impl<'a, A, T> T0<'a, A> for L<T>
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
index 066bf431a83..b30dd36d2ad 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-62529-3.stderr
@@ -1,8 +1,10 @@
 error[E0277]: expected a `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
-  --> $DIR/issue-62529-3.rs:25:9
+  --> $DIR/issue-62529-3.rs:25:14
    |
 LL |         call(f, ());
-   |         ^^^^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+   |         ---- ^ expected an `Fn<(<_ as ATC<'a>>::Type,)>` closure, found `F`
+   |         |
+   |         required by a bound introduced by this call
    |
    = note: expected a closure with arguments `((),)`
               found a closure with arguments `(<_ as ATC<'a>>::Type,)`
diff --git a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
index a6858154dfb..14fe1803b73 100644
--- a/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
+++ b/src/test/ui/higher-rank-trait-bounds/normalize-under-binder/issue-89118.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL |     C: StackContext,
    |        ^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
-note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
 LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
@@ -24,7 +24,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL | impl<C> EthernetWorker<C> {}
    |         ^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
-note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
 LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
@@ -44,7 +44,7 @@ error[E0277]: the trait bound `for<'a> &'a (): BufferMut` is not satisfied
 LL |     type Handler = Ctx<C::Dispatcher>;
    |                    ^^^^^^^^^^^^^^^^^^ the trait `for<'a> BufferMut` is not implemented for `&'a ()`
    |
-note: required because of the requirements on the impl of `for<'a> BufferUdpStateContext<&'a ()>` for `Ctx<()>`
+note: required for `Ctx<()>` to implement `for<'a> BufferUdpStateContext<&'a ()>`
   --> $DIR/issue-89118.rs:5:23
    |
 LL | impl<B: BufferMut, C> BufferUdpStateContext<B> for C {}
diff --git a/src/test/ui/impl-trait/issues/issue-86800.rs b/src/test/ui/impl-trait/issues/issue-86800.rs
index 19edeaffc49..351243c6727 100644
--- a/src/test/ui/impl-trait/issues/issue-86800.rs
+++ b/src/test/ui/impl-trait/issues/issue-86800.rs
@@ -1,6 +1,14 @@
 #![feature(type_alias_impl_trait)]
 
 // edition:2021
+// unset-rustc-env:RUST_BACKTRACE
+// compile-flags:-Z treat-err-as-bug=1
+// error-pattern:stack backtrace:
+// failure-status:101
+// normalize-stderr-test "note: .*" -> ""
+// normalize-stderr-test "thread 'rustc' .*" -> ""
+// normalize-stderr-test " +[0-9]+:.*\n" -> ""
+// normalize-stderr-test " +at .*\n" -> ""
 
 use std::future::Future;
 
@@ -23,7 +31,6 @@ struct Context {
 type TransactionResult<O> = Result<O, ()>;
 
 type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-//~^ ERROR unconstrained opaque type
 
 fn execute_transaction_fut<'f, F, O>(
     f: F,
diff --git a/src/test/ui/impl-trait/issues/issue-86800.stderr b/src/test/ui/impl-trait/issues/issue-86800.stderr
index 787aecc5b84..135d06d44ad 100644
--- a/src/test/ui/impl-trait/issues/issue-86800.stderr
+++ b/src/test/ui/impl-trait/issues/issue-86800.stderr
@@ -1,10 +1,19 @@
-error: unconstrained opaque type
-  --> $DIR/issue-86800.rs:25:34
-   |
-LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
-   |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: `TransactionFuture` must be used in combination with a concrete type within the same module
 
-error: aborting due to previous error
+stack backtrace:
 
+error: internal compiler error: unexpected panic
+
+
+
+
+
+
+
+
+
+query stack during panic:
+#0 [mir_borrowck] borrow-checking `execute_transaction_fut`
+#1 [type_of] computing type of `TransactionFuture::{opaque#0}`
+#2 [check_mod_item_types] checking item types in top-level module
+#3 [analysis] running analysis passes on this crate
+end of query stack
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.rs b/src/test/ui/impl-trait/nested-return-type2-tait.rs
index a2a49c5535d..42613d5ccd9 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait.rs
+++ b/src/test/ui/impl-trait/nested-return-type2-tait.rs
@@ -1,5 +1,7 @@
 #![feature(type_alias_impl_trait)]
 
+// check-pass
+
 trait Duh {}
 
 impl Duh for i32 {}
@@ -17,13 +19,13 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
 
 type Sendable = impl Send;
 
-// The `Sendable` here is then later compared against the inference var
-// created, causing the inference var to be set to `Sendable` instead of
+// The `Sendable` here is converted to an inference var and then later compared
+// against the inference var created, causing the inference var to be set to
+// the hidden type of `Sendable` instead of
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
-// type does not implement `Duh`, even if its hidden type does. So we error out.
+// type does not implement `Duh`, but if its hidden type does.
 fn foo() -> impl Trait<Assoc = Sendable> {
-    //~^ ERROR `Sendable: Duh` is not satisfied
     || 42
 }
 
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait.stderr b/src/test/ui/impl-trait/nested-return-type2-tait.stderr
deleted file mode 100644
index 1079a86ce9e..00000000000
--- a/src/test/ui/impl-trait/nested-return-type2-tait.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0277]: the trait bound `Sendable: Duh` is not satisfied
-  --> $DIR/nested-return-type2-tait.rs:25:13
-   |
-LL | fn foo() -> impl Trait<Assoc = Sendable> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `Sendable`
-   |
-   = help: the trait `Duh` is implemented for `i32`
-note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait.rs:27:5: 27:7]`
-  --> $DIR/nested-return-type2-tait.rs:14:31
-   |
-LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
-   |                               ^^^^^     ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.rs b/src/test/ui/impl-trait/nested-return-type2-tait2.rs
index fcc077ec18e..af8e0663054 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait2.rs
+++ b/src/test/ui/impl-trait/nested-return-type2-tait2.rs
@@ -24,8 +24,8 @@ type Traitable = impl Trait<Assoc = Sendable>;
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does. So we error out.
 fn foo() -> Traitable {
-    //~^ ERROR `Sendable: Duh` is not satisfied
     || 42
+    //~^ ERROR `Sendable: Duh` is not satisfied
 }
 
 fn main() {
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
index 847b9400085..348c737b0b1 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
+++ b/src/test/ui/impl-trait/nested-return-type2-tait2.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Sendable: Duh` is not satisfied
-  --> $DIR/nested-return-type2-tait2.rs:26:13
+  --> $DIR/nested-return-type2-tait2.rs:27:5
    |
-LL | fn foo() -> Traitable {
-   |             ^^^^^^^^^ the trait `Duh` is not implemented for `Sendable`
+LL |     || 42
+   |     ^^^^^ the trait `Duh` is not implemented for `Sendable`
    |
    = help: the trait `Duh` is implemented for `i32`
-note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait2.rs:28:5: 28:7]`
+note: required for `[closure@$DIR/nested-return-type2-tait2.rs:27:5: 27:7]` to implement `Trait`
   --> $DIR/nested-return-type2-tait2.rs:14:31
    |
 LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.rs b/src/test/ui/impl-trait/nested-return-type2-tait3.rs
index 665c7a8cab9..74fd8a9dda0 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait3.rs
+++ b/src/test/ui/impl-trait/nested-return-type2-tait3.rs
@@ -23,8 +23,8 @@ type Traitable = impl Trait<Assoc = impl Send>;
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does. So we error out.
 fn foo() -> Traitable {
-    //~^ ERROR `impl Send: Duh` is not satisfied
     || 42
+    //~^ ERROR `impl Send: Duh` is not satisfied
 }
 
 fn main() {
diff --git a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
index 7b7f06b8e13..6ac67141557 100644
--- a/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
+++ b/src/test/ui/impl-trait/nested-return-type2-tait3.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `impl Send: Duh` is not satisfied
-  --> $DIR/nested-return-type2-tait3.rs:25:13
+  --> $DIR/nested-return-type2-tait3.rs:26:5
    |
-LL | fn foo() -> Traitable {
-   |             ^^^^^^^^^ the trait `Duh` is not implemented for `impl Send`
+LL |     || 42
+   |     ^^^^^ the trait `Duh` is not implemented for `impl Send`
    |
    = help: the trait `Duh` is implemented for `i32`
-note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2-tait3.rs:27:5: 27:7]`
+note: required for `[closure@$DIR/nested-return-type2-tait3.rs:26:5: 26:7]` to implement `Trait`
   --> $DIR/nested-return-type2-tait3.rs:14:31
    |
 LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
diff --git a/src/test/ui/impl-trait/nested-return-type2.rs b/src/test/ui/impl-trait/nested-return-type2.rs
index 279641a46c3..39928d543e1 100644
--- a/src/test/ui/impl-trait/nested-return-type2.rs
+++ b/src/test/ui/impl-trait/nested-return-type2.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 trait Duh {}
 
 impl Duh for i32 {}
@@ -18,9 +20,11 @@ impl<R: Duh, F: FnMut() -> R> Trait for F {
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does.
+// Lazy TAIT would error out, but we inserted a hack to make it work again,
+// keeping backwards compatibility.
 fn foo() -> impl Trait<Assoc = impl Send> {
-    //~^ ERROR `impl Send: Duh` is not satisfied
     || 42
 }
 
-fn main() {}
+fn main() {
+}
diff --git a/src/test/ui/impl-trait/nested-return-type2.stderr b/src/test/ui/impl-trait/nested-return-type2.stderr
deleted file mode 100644
index f28a084af89..00000000000
--- a/src/test/ui/impl-trait/nested-return-type2.stderr
+++ /dev/null
@@ -1,16 +0,0 @@
-error[E0277]: the trait bound `impl Send: Duh` is not satisfied
-  --> $DIR/nested-return-type2.rs:21:13
-   |
-LL | fn foo() -> impl Trait<Assoc = impl Send> {
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Duh` is not implemented for `impl Send`
-   |
-   = help: the trait `Duh` is implemented for `i32`
-note: required because of the requirements on the impl of `Trait` for `[closure@$DIR/nested-return-type2.rs:23:5: 23:7]`
-  --> $DIR/nested-return-type2.rs:12:31
-   |
-LL | impl<R: Duh, F: FnMut() -> R> Trait for F {
-   |                               ^^^^^     ^
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/impl-trait/nested_impl_trait.stderr b/src/test/ui/impl-trait/nested_impl_trait.stderr
index bb4ae5e8282..3291cad6882 100644
--- a/src/test/ui/impl-trait/nested_impl_trait.stderr
+++ b/src/test/ui/impl-trait/nested_impl_trait.stderr
@@ -53,7 +53,7 @@ LL | fn bad_in_ret_position(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                              ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
    |
    = help: the trait `Into<U>` is implemented for `T`
-   = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+   = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
 
 error[E0277]: the trait bound `impl Debug: From<impl Into<u32>>` is not satisfied
   --> $DIR/nested_impl_trait.rs:18:34
@@ -62,7 +62,7 @@ LL |     fn bad(x: impl Into<u32>) -> impl Into<impl Debug> { x }
    |                                  ^^^^^^^^^^^^^^^^^^^^^ the trait `From<impl Into<u32>>` is not implemented for `impl Debug`
    |
    = help: the trait `Into<U>` is implemented for `T`
-   = note: required because of the requirements on the impl of `Into<impl Debug>` for `impl Into<u32>`
+   = note: required for `impl Into<u32>` to implement `Into<impl Debug>`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
index ade0dfa1bb3..cf2998bbf40 100644
--- a/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
+++ b/src/test/ui/impl-trait/projection-mismatch-in-impl-where-clause.stderr
@@ -9,7 +9,7 @@ note: expected this to be `u8`
    |
 LL |     type Assoc = u8;
    |                  ^^
-note: required because of the requirements on the impl of `Test` for `()`
+note: required for `()` to implement `Test`
   --> $DIR/projection-mismatch-in-impl-where-clause.rs:11:9
    |
 LL | impl<T> Test for T where T: Super<Assoc = ()> {}
diff --git a/src/test/ui/implied-bounds/issue-100690.rs b/src/test/ui/implied-bounds/issue-100690.rs
new file mode 100644
index 00000000000..5599cd410ba
--- /dev/null
+++ b/src/test/ui/implied-bounds/issue-100690.rs
@@ -0,0 +1,45 @@
+// This code (probably) _should_ compile, but it currently does not because we
+// are not smart enough about implied bounds.
+
+use std::io;
+
+fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
+//~^ NOTE required by a bound in this
+where
+    F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
+    //~^ NOTE required by this bound in `real_dispatch`
+    //~| NOTE required by a bound in `real_dispatch`
+{
+    todo!()
+}
+
+#[derive(Debug)]
+struct UIView<'a, T: 'a> {
+    _phantom: std::marker::PhantomData<&'a mut T>,
+}
+
+trait Handle<'a, T: 'a, V, R> {
+    fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
+    where
+        F: FnOnce(&mut V) -> R + Send + 'static;
+}
+
+#[derive(Debug, Clone)]
+struct TUIHandle<T> {
+    _phantom: std::marker::PhantomData<T>,
+}
+
+impl<'a, T: 'a> Handle<'a, T, UIView<'a, T>, Result<(), io::Error>> for TUIHandle<T> {
+    fn dispatch<F>(&self, f: F) -> Result<(), io::Error>
+    where
+        F: FnOnce(&mut UIView<'a, T>) -> Result<(), io::Error> + Send + 'static,
+    {
+        real_dispatch(f)
+        //~^ ERROR expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
+        //~| NOTE expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
+        //~| NOTE expected a closure with arguments
+        //~| NOTE required by a bound introduced by this call
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/implied-bounds/issue-100690.stderr b/src/test/ui/implied-bounds/issue-100690.stderr
new file mode 100644
index 00000000000..3f6af70d8ed
--- /dev/null
+++ b/src/test/ui/implied-bounds/issue-100690.stderr
@@ -0,0 +1,22 @@
+error[E0277]: expected a `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
+  --> $DIR/issue-100690.rs:37:23
+   |
+LL |         real_dispatch(f)
+   |         ------------- ^ expected an `FnOnce<(&mut UIView<'_, T>,)>` closure, found `F`
+   |         |
+   |         required by a bound introduced by this call
+   |
+   = note: expected a closure with arguments `(&mut UIView<'a, T>,)`
+              found a closure with arguments `(&mut UIView<'_, T>,)`
+note: required by a bound in `real_dispatch`
+  --> $DIR/issue-100690.rs:9:8
+   |
+LL | fn real_dispatch<T, F>(f: F) -> Result<(), io::Error>
+   |    ------------- required by a bound in this
+...
+LL |     F: FnOnce(&mut UIView<T>) -> Result<(), io::Error> + Send + 'static,
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `real_dispatch`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/index-help.stderr b/src/test/ui/index-help.stderr
index b36f4dab829..e020d029875 100644
--- a/src/test/ui/index-help.stderr
+++ b/src/test/ui/index-help.stderr
@@ -6,7 +6,7 @@ LL |     x[0i32];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i32>` for `Vec<{integer}>`
+   = note: required for `Vec<{integer}>` to implement `Index<i32>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/indexing-requires-a-uint.stderr b/src/test/ui/indexing-requires-a-uint.stderr
index fbff20f8dee..7a741cfc7de 100644
--- a/src/test/ui/indexing-requires-a-uint.stderr
+++ b/src/test/ui/indexing-requires-a-uint.stderr
@@ -6,7 +6,7 @@ LL |     [0][0u8];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<u8>` for `[{integer}]`
+   = note: required for `[{integer}]` to implement `Index<u8>`
 
 error[E0308]: mismatched types
   --> $DIR/indexing-requires-a-uint.rs:12:18
diff --git a/src/test/ui/inference/issue-71732.stderr b/src/test/ui/inference/issue-71732.stderr
index 04673a375cf..79bee33280d 100644
--- a/src/test/ui/inference/issue-71732.stderr
+++ b/src/test/ui/inference/issue-71732.stderr
@@ -2,7 +2,9 @@ error[E0283]: type annotations needed
   --> $DIR/issue-71732.rs:18:10
    |
 LL |         .get(&"key".into())
-   |          ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get`
+   |          ^^^ ------------- type must be known at this point
+   |          |
+   |          cannot infer type of the type parameter `Q` declared on the associated function `get`
    |
    = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl Borrow<str> for String;
@@ -13,7 +15,7 @@ note: required by a bound in `HashMap::<K, V, S>::get`
    |
 LL |         K: Borrow<Q>,
    |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |         .get::<Q>(&"key".into())
    |             +++++
diff --git a/src/test/ui/inference/issue-86162-1.stderr b/src/test/ui/inference/issue-86162-1.stderr
index e395e65fad0..4f621b82dc5 100644
--- a/src/test/ui/inference/issue-86162-1.stderr
+++ b/src/test/ui/inference/issue-86162-1.stderr
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
 LL |     foo(gen()); //<- Do not suggest `foo::<impl Clone>()`!
    |     --- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
    |     |
-   |     type must be known at this point
+   |     required by a bound introduced by this call
    |
    = note: cannot satisfy `_: Clone`
 note: required by a bound in `foo`
diff --git a/src/test/ui/inference/issue-86162-2.stderr b/src/test/ui/inference/issue-86162-2.stderr
index 30e6e10eaa2..9aff2cec160 100644
--- a/src/test/ui/inference/issue-86162-2.stderr
+++ b/src/test/ui/inference/issue-86162-2.stderr
@@ -4,7 +4,7 @@ error[E0283]: type annotations needed
 LL |     Foo::bar(gen()); //<- Do not suggest `Foo::bar::<impl Clone>()`!
    |     -------- ^^^ cannot infer type of the type parameter `T` declared on the function `gen`
    |     |
-   |     type must be known at this point
+   |     required by a bound introduced by this call
    |
    = note: cannot satisfy `_: Clone`
 note: required by a bound in `Foo::bar`
diff --git a/src/test/ui/integral-indexing.stderr b/src/test/ui/integral-indexing.stderr
index 3f9094d124e..bbbb2a86a22 100644
--- a/src/test/ui/integral-indexing.stderr
+++ b/src/test/ui/integral-indexing.stderr
@@ -6,7 +6,7 @@ LL |     v[3u8];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<u8>` for `Vec<isize>`
+   = note: required for `Vec<isize>` to implement `Index<u8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:7:7
@@ -16,7 +16,7 @@ LL |     v[3i8];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i8>` for `Vec<isize>`
+   = note: required for `Vec<isize>` to implement `Index<i8>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:8:7
@@ -26,7 +26,7 @@ LL |     v[3u32];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<u32>` for `Vec<isize>`
+   = note: required for `Vec<isize>` to implement `Index<u32>`
 
 error[E0277]: the type `[isize]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:9:7
@@ -36,7 +36,7 @@ LL |     v[3i32];
    |
    = help: the trait `SliceIndex<[isize]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i32>` for `Vec<isize>`
+   = note: required for `Vec<isize>` to implement `Index<i32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u8`
   --> $DIR/integral-indexing.rs:12:18
@@ -46,7 +46,7 @@ LL |     s.as_bytes()[3u8];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u8`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<u8>` for `[u8]`
+   = note: required for `[u8]` to implement `Index<u8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i8`
   --> $DIR/integral-indexing.rs:13:18
@@ -56,7 +56,7 @@ LL |     s.as_bytes()[3i8];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i8`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i8>` for `[u8]`
+   = note: required for `[u8]` to implement `Index<i8>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `u32`
   --> $DIR/integral-indexing.rs:14:18
@@ -66,7 +66,7 @@ LL |     s.as_bytes()[3u32];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `u32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<u32>` for `[u8]`
+   = note: required for `[u8]` to implement `Index<u32>`
 
 error[E0277]: the type `[u8]` cannot be indexed by `i32`
   --> $DIR/integral-indexing.rs:15:18
@@ -76,7 +76,7 @@ LL |     s.as_bytes()[3i32];
    |
    = help: the trait `SliceIndex<[u8]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i32>` for `[u8]`
+   = note: required for `[u8]` to implement `Index<i32>`
 
 error: aborting due to 8 previous errors
 
diff --git a/src/test/ui/interior-mutability/interior-mutability.stderr b/src/test/ui/interior-mutability/interior-mutability.stderr
index 349fb6dafa3..94f41c92598 100644
--- a/src/test/ui/interior-mutability/interior-mutability.stderr
+++ b/src/test/ui/interior-mutability/interior-mutability.stderr
@@ -1,12 +1,14 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/interior-mutability.rs:5:5
+  --> $DIR/interior-mutability.rs:5:18
    |
 LL |     catch_unwind(|| { x.set(23); });
-   |     ^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |     ------------ ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: within `Cell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `Cell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `&Cell<i32>`
+   = note: required for `&Cell<i32>` to implement `UnwindSafe`
 note: required because it's used within this closure
   --> $DIR/interior-mutability.rs:5:18
    |
diff --git a/src/test/ui/issues/issue-100605.rs b/src/test/ui/issues/issue-100605.rs
new file mode 100644
index 00000000000..917a45c15bb
--- /dev/null
+++ b/src/test/ui/issues/issue-100605.rs
@@ -0,0 +1,9 @@
+fn takes_option(_arg: Option<&String>) {}
+
+fn main() {
+    takes_option(&None); //~ ERROR 4:18: 4:23: mismatched types [E0308]
+
+    let x = String::from("x");
+    let res = Some(x);
+    takes_option(&res); //~ ERROR 8:18: 8:22: mismatched types [E0308]
+}
diff --git a/src/test/ui/issues/issue-100605.stderr b/src/test/ui/issues/issue-100605.stderr
new file mode 100644
index 00000000000..886e3cd6bb7
--- /dev/null
+++ b/src/test/ui/issues/issue-100605.stderr
@@ -0,0 +1,46 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-100605.rs:4:18
+   |
+LL |     takes_option(&None);
+   |     ------------ ^^^^^ expected enum `Option`, found `&Option<_>`
+   |     |
+   |     arguments to this function are incorrect
+   |
+   = note:   expected enum `Option<&String>`
+           found reference `&Option<_>`
+note: function defined here
+  --> $DIR/issue-100605.rs:1:4
+   |
+LL | fn takes_option(_arg: Option<&String>) {}
+   |    ^^^^^^^^^^^^ ---------------------
+help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`
+   |
+LL |     takes_option(None.as_ref());
+   |                  ~~~~~~~~~~~~~
+help: consider removing the borrow
+   |
+LL -     takes_option(&None);
+LL +     takes_option(None);
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/issue-100605.rs:8:18
+   |
+LL |     takes_option(&res);
+   |     ------------ ^^^^
+   |     |            |
+   |     |            expected enum `Option`, found `&Option<String>`
+   |     |            help: you can convert from `&Option<T>` to `Option<&T>` using `.as_ref()`: `res.as_ref()`
+   |     arguments to this function are incorrect
+   |
+   = note:   expected enum `Option<&String>`
+           found reference `&Option<String>`
+note: function defined here
+  --> $DIR/issue-100605.rs:1:4
+   |
+LL | fn takes_option(_arg: Option<&String>) {}
+   |    ^^^^^^^^^^^^ ---------------------
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/issues/issue-16538.mir.stderr b/src/test/ui/issues/issue-16538.mir.stderr
index 7dab7de7619..e320df4b7ad 100644
--- a/src/test/ui/issues/issue-16538.mir.stderr
+++ b/src/test/ui/issues/issue-16538.mir.stderr
@@ -5,6 +5,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error[E0133]: use of extern static is unsafe and requires unsafe function or block
   --> $DIR/issue-16538.rs:14:30
diff --git a/src/test/ui/issues/issue-16538.thir.stderr b/src/test/ui/issues/issue-16538.thir.stderr
index a18b0197d87..4a862869274 100644
--- a/src/test/ui/issues/issue-16538.thir.stderr
+++ b/src/test/ui/issues/issue-16538.thir.stderr
@@ -21,6 +21,7 @@ LL | static foo: &Y::X = &*Y::foo(Y::x as *const Y::X);
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-17252.stderr b/src/test/ui/issues/issue-17252.stderr
index 3a629e1ebf4..b8f54416a08 100644
--- a/src/test/ui/issues/issue-17252.stderr
+++ b/src/test/ui/issues/issue-17252.stderr
@@ -2,7 +2,7 @@ error[E0391]: cycle detected when const-evaluating + checking `FOO`
   --> $DIR/issue-17252.rs:1:1
    |
 LL | const FOO: usize = FOO;
-   | ^^^^^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: ...which immediately requires const-evaluating + checking `FOO` again
 note: cycle used when const-evaluating + checking `main::{constant#0}`
diff --git a/src/test/ui/issues/issue-18611.stderr b/src/test/ui/issues/issue-18611.stderr
index bd18d46223e..22c3470b61e 100644
--- a/src/test/ui/issues/issue-18611.stderr
+++ b/src/test/ui/issues/issue-18611.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `isize: HasState` is not satisfied
-  --> $DIR/issue-18611.rs:1:18
+  --> $DIR/issue-18611.rs:1:1
    |
-LL | fn add_state(op: <isize as HasState>::State) {
-   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasState` is not implemented for `isize`
+LL | / fn add_state(op: <isize as HasState>::State) {
+LL | |
+LL | | }
+   | |_^ the trait `HasState` is not implemented for `isize`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-20162.stderr b/src/test/ui/issues/issue-20162.stderr
index d70bf6e1d92..3f9b3be9851 100644
--- a/src/test/ui/issues/issue-20162.stderr
+++ b/src/test/ui/issues/issue-20162.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `X: Ord` is not satisfied
-  --> $DIR/issue-20162.rs:5:7
+  --> $DIR/issue-20162.rs:5:5
    |
 LL |     b.sort();
-   |       ^^^^ the trait `Ord` is not implemented for `X`
+   |     ^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `Ord` is not implemented for `X`
    |
 note: required by a bound in `slice::<impl [T]>::sort`
   --> $SRC_DIR/alloc/src/slice.rs:LL:COL
diff --git a/src/test/ui/issues/issue-20413.stderr b/src/test/ui/issues/issue-20413.stderr
index ea493c58a33..2db60b641ee 100644
--- a/src/test/ui/issues/issue-20413.stderr
+++ b/src/test/ui/issues/issue-20413.stderr
@@ -14,13 +14,13 @@ LL | impl<T> Foo for T where NoData<T>: Foo {
    |                                    ^^^
    |
    = help: consider increasing the recursion limit by 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 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>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
   --> $DIR/issue-20413.rs:8:9
    |
 LL | impl<T> Foo for T where NoData<T>: Foo {
    |         ^^^     ^
    = note: 127 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Foo` for `NoData<T>`
+   = note: required for `NoData<T>` to implement `Foo`
 
 error[E0275]: overflow evaluating the requirement `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Baz`
   --> $DIR/issue-20413.rs:27:42
@@ -29,18 +29,18 @@ LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
-note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
    = note: 126 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Baz` for `EvenLessData<T>`
+   = note: required for `EvenLessData<T>` to implement `Baz`
 
 error[E0275]: overflow evaluating the requirement `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>: Bar`
   --> $DIR/issue-20413.rs:34:42
@@ -49,18 +49,18 @@ LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |                                          ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_20413`)
-note: required because of the requirements on the impl of `Baz` for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+note: required for `EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Baz`
   --> $DIR/issue-20413.rs:34:9
    |
 LL | impl<T> Baz for T where AlmostNoData<T>: Bar {
    |         ^^^     ^
-note: required because of the requirements on the impl of `Bar` for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+note: required for `AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<EvenLessData<AlmostNoData<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Bar`
   --> $DIR/issue-20413.rs:27:9
    |
 LL | impl<T> Bar for T where EvenLessData<T>: Baz {
    |         ^^^     ^
    = note: 126 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Bar` for `AlmostNoData<T>`
+   = note: required for `AlmostNoData<T>` to implement `Bar`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/issues/issue-20605.stderr b/src/test/ui/issues/issue-20605.stderr
index 41eefe3f8e9..e1858b63989 100644
--- a/src/test/ui/issues/issue-20605.stderr
+++ b/src/test/ui/issues/issue-20605.stderr
@@ -2,10 +2,10 @@ error[E0277]: the size for values of type `dyn Iterator<Item = &'a mut u8>` cann
   --> $DIR/issue-20605.rs:2:17
    |
 LL |     for item in *things { *item = 0 }
-   |                 ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |                 ^^^^^^^ the trait `IntoIterator` is not implemented for `dyn Iterator<Item = &'a mut u8>`
    |
    = note: the trait bound `dyn Iterator<Item = &'a mut u8>: IntoIterator` is not satisfied
-   = note: required because of the requirements on the impl of `IntoIterator` for `dyn Iterator<Item = &'a mut u8>`
+   = note: required for `dyn Iterator<Item = &'a mut u8>` to implement `IntoIterator`
 help: consider mutably borrowing here
    |
 LL |     for item in &mut *things { *item = 0 }
diff --git a/src/test/ui/issues/issue-20831-debruijn.stderr b/src/test/ui/issues/issue-20831-debruijn.stderr
index 57f9575bdbd..ef62dece836 100644
--- a/src/test/ui/issues/issue-20831-debruijn.stderr
+++ b/src/test/ui/issues/issue-20831-debruijn.stderr
@@ -1,8 +1,14 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'a` due to conflicting requirements
-  --> $DIR/issue-20831-debruijn.rs:28:8
+  --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |        ^^^^^^^^^
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |         //
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
    |
 note: first, the lifetime cannot outlive the anonymous lifetime defined here...
   --> $DIR/issue-20831-debruijn.rs:28:58
@@ -15,10 +21,16 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | impl<'a> Publisher<'a> for MyStruct<'a> {
    |      ^^
 note: ...so that the types are compatible
-  --> $DIR/issue-20831-debruijn.rs:28:8
+  --> $DIR/issue-20831-debruijn.rs:28:5
    |
-LL |     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
-   |        ^^^^^^^^^
+LL | /     fn subscribe(&mut self, t : Box<dyn Subscriber<Input=<Self as Publisher>::Output> + 'a>) {
+LL | |         // Not obvious, but there is an implicit lifetime here -------^
+LL | |
+LL | |         //
+...  |
+LL | |         self.sub = t;
+LL | |     }
+   | |_____^
    = note: expected `<MyStruct<'a> as Publisher<'_>>`
               found `<MyStruct<'_> as Publisher<'_>>`
 
diff --git a/src/test/ui/issues/issue-21763.stderr b/src/test/ui/issues/issue-21763.stderr
index b8b38c0a723..72c65029746 100644
--- a/src/test/ui/issues/issue-21763.stderr
+++ b/src/test/ui/issues/issue-21763.stderr
@@ -1,12 +1,12 @@
 error[E0277]: `Rc<()>` cannot be sent between threads safely
-  --> $DIR/issue-21763.rs:9:5
+  --> $DIR/issue-21763.rs:9:11
    |
 LL |     foo::<HashMap<Rc<()>, Rc<()>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
+   |           ^^^^^^^^^^^^^^^^^^^^^^^ `Rc<()>` cannot be sent between threads safely
    |
    = help: within `(Rc<()>, Rc<()>)`, the trait `Send` is not implemented for `Rc<()>`
    = note: required because it appears within the type `(Rc<()>, Rc<()>)`
-   = note: required because of the requirements on the impl of `Send` for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>`
+   = note: required for `hashbrown::raw::RawTable<(Rc<()>, Rc<()>)>` to implement `Send`
    = note: required because it appears within the type `hashbrown::map::HashMap<Rc<()>, Rc<()>, RandomState>`
    = note: required because it appears within the type `HashMap<Rc<()>, Rc<()>>`
 note: required by a bound in `foo`
diff --git a/src/test/ui/issues/issue-22872.stderr b/src/test/ui/issues/issue-22872.stderr
index a84cb7d8c59..7382d40c010 100644
--- a/src/test/ui/issues/issue-22872.stderr
+++ b/src/test/ui/issues/issue-22872.stderr
@@ -5,7 +5,7 @@ LL |     let _: Box<dyn for<'b> Wrap<'b>> = Box::new(Wrapper(process));
    |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^ `<P as Process<'_>>::Item` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `<P as Process<'_>>::Item`
-note: required because of the requirements on the impl of `for<'b> Wrap<'b>` for `Wrapper<P>`
+note: required for `Wrapper<P>` to implement `for<'b> Wrap<'b>`
   --> $DIR/issue-22872.rs:7:13
    |
 LL | impl<'b, P> Wrap<'b> for Wrapper<P>
diff --git a/src/test/ui/issues/issue-23122-2.stderr b/src/test/ui/issues/issue-23122-2.stderr
index 7519e632d54..f6cda3de5c7 100644
--- a/src/test/ui/issues/issue-23122-2.stderr
+++ b/src/test/ui/issues/issue-23122-2.stderr
@@ -1,15 +1,10 @@
-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: Sized`
+error[E0275]: overflow evaluating the requirement `<T as Next>::Next`
   --> $DIR/issue-23122-2.rs:10:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by 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 as Next>::Next>`
-  --> $DIR/issue-23122-2.rs:9:15
-   |
-LL | impl<T: Next> Next for GetNext<T> {
-   |               ^^^^     ^^^^^^^^^^
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-23302-3.stderr b/src/test/ui/issues/issue-23302-3.stderr
index dcb99605da0..e9314207537 100644
--- a/src/test/ui/issues/issue-23302-3.stderr
+++ b/src/test/ui/issues/issue-23302-3.stderr
@@ -2,13 +2,13 @@ error[E0391]: cycle detected when const-evaluating + checking `A`
   --> $DIR/issue-23302-3.rs:1:1
    |
 LL | const A: i32 = B;
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^
    |
 note: ...which requires const-evaluating + checking `B`...
   --> $DIR/issue-23302-3.rs:3:1
    |
 LL | const B: i32 = A;
-   | ^^^^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^
    = note: ...which again requires const-evaluating + checking `A`, completing the cycle
 note: cycle used when simplifying constant for the type system `A`
   --> $DIR/issue-23302-3.rs:1:1
diff --git a/src/test/ui/issues/issue-25901.stderr b/src/test/ui/issues/issue-25901.stderr
index e933745c44e..c6c80e41cf6 100644
--- a/src/test/ui/issues/issue-25901.stderr
+++ b/src/test/ui/issues/issue-25901.stderr
@@ -16,6 +16,7 @@ note: impl defined here, but it is not `const`
 LL | impl Deref for A {
    | ^^^^^^^^^^^^^^^^
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-31173.rs b/src/test/ui/issues/issue-31173.rs
index 472a95d4636..04efa27189b 100644
--- a/src/test/ui/issues/issue-31173.rs
+++ b/src/test/ui/issues/issue-31173.rs
@@ -4,12 +4,12 @@ pub fn get_tok(it: &mut IntoIter<u8>) {
     let mut found_e = false;
 
     let temp: Vec<u8> = it
+        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .take_while(|&x| {
             found_e = true;
             false
         })
         .cloned()
-        //~^ ERROR to be an iterator that yields `&_`, but it yields `u8`
         .collect(); //~ ERROR the method
 }
 
diff --git a/src/test/ui/issues/issue-31173.stderr b/src/test/ui/issues/issue-31173.stderr
index e89105540df..e3334eef3ad 100644
--- a/src/test/ui/issues/issue-31173.stderr
+++ b/src/test/ui/issues/issue-31173.stderr
@@ -1,8 +1,16 @@
-error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>` to be an iterator that yields `&_`, but it yields `u8`
-  --> $DIR/issue-31173.rs:11:10
-   |
-LL |         .cloned()
-   |          ^^^^^^ expected reference, found `u8`
+error[E0271]: expected `TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>` to be an iterator that yields `&_`, but it yields `u8`
+  --> $DIR/issue-31173.rs:6:25
+   |
+LL |       let temp: Vec<u8> = it
+   |  _________________________^
+LL | |
+LL | |         .take_while(|&x| {
+LL | |             found_e = true;
+LL | |             false
+LL | |         })
+   | |__________^ expected reference, found `u8`
+LL |           .cloned()
+   |            ------ required by a bound introduced by this call
    |
    = note: expected reference `&_`
                    found type `u8`
@@ -12,27 +20,27 @@ note: required by a bound in `cloned`
 LL |         Self: Sized + Iterator<Item = &'a T>,
    |                                ^^^^^^^^^^^^ required by this bound in `cloned`
 
-error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>`, but its trait bounds were not satisfied
+error[E0599]: the method `collect` exists for struct `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>`, but its trait bounds were not satisfied
   --> $DIR/issue-31173.rs:13:10
    |
 LL |         .collect();
-   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>` due to unsatisfied trait bounds
-   |
-  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
-   |
-LL | pub struct Cloned<I> {
-   | -------------------- doesn't satisfy `_: Iterator`
+   |          ^^^^^^^ method cannot be called on `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>` due to unsatisfied trait bounds
    |
   ::: $SRC_DIR/core/src/iter/adapters/take_while.rs:LL:COL
    |
 LL | pub struct TakeWhile<I, P> {
    | -------------------------- doesn't satisfy `<_ as Iterator>::Item = &_`
    |
+  ::: $SRC_DIR/core/src/iter/adapters/cloned.rs:LL:COL
+   |
+LL | pub struct Cloned<I> {
+   | -------------------- doesn't satisfy `_: Iterator`
+   |
    = note: the following trait bounds were not satisfied:
-           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]> as Iterator>::Item = &_`
-           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
-           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
-           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:7:21: 7:25]>>: Iterator`
+           `<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]> as Iterator>::Item = &_`
+           which is required by `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           `Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
+           which is required by `&mut Cloned<TakeWhile<&mut std::vec::IntoIter<u8>, [closure@$DIR/issue-31173.rs:8:21: 8:25]>>: Iterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-32709.stderr b/src/test/ui/issues/issue-32709.stderr
index 112cb335932..1d595ca5649 100644
--- a/src/test/ui/issues/issue-32709.stderr
+++ b/src/test/ui/issues/issue-32709.stderr
@@ -10,7 +10,7 @@ LL |     Err(5)?;
    = help: the following other types implement trait `FromResidual<R>`:
              <Result<T, F> as FromResidual<Result<Infallible, E>>>
              <Result<T, F> as FromResidual<Yeet<E>>>
-   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, {integer}>>` for `Result<i32, ()>`
+   = note: required for `Result<i32, ()>` to implement `FromResidual<Result<Infallible, {integer}>>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-33941.stderr b/src/test/ui/issues/issue-33941.stderr
index 565a7fef379..691b8f88f4e 100644
--- a/src/test/ui/issues/issue-33941.stderr
+++ b/src/test/ui/issues/issue-33941.stderr
@@ -1,8 +1,10 @@
 error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
-  --> $DIR/issue-33941.rs:6:36
+  --> $DIR/issue-33941.rs:6:14
    |
 LL |     for _ in HashMap::new().iter().cloned() {}
-   |                                    ^^^^^^ expected reference, found tuple
+   |              ^^^^^^^^^^^^^^^^^^^^^ ------ required by a bound introduced by this call
+   |              |
+   |              expected reference, found tuple
    |
    = note: expected reference `&_`
                   found tuple `(&_, &_)`
@@ -20,8 +22,8 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    |
    = note:  expected tuple `(&_, &_)`
            found reference `&_`
-   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
-   = note: required because of the requirements on the impl of `IntoIterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+   = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
+   = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `IntoIterator`
 
 error[E0271]: expected `std::collections::hash_map::Iter<'_, _, _>` to be an iterator that yields `&_`, but it yields `(&_, &_)`
   --> $DIR/issue-33941.rs:6:14
@@ -31,7 +33,7 @@ LL |     for _ in HashMap::new().iter().cloned() {}
    |
    = note:  expected tuple `(&_, &_)`
            found reference `&_`
-   = note: required because of the requirements on the impl of `Iterator` for `Cloned<std::collections::hash_map::Iter<'_, _, _>>`
+   = note: required for `Cloned<std::collections::hash_map::Iter<'_, _, _>>` to implement `Iterator`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/issues/issue-34334.stderr b/src/test/ui/issues/issue-34334.stderr
index 48ae2df691c..72082f0cd17 100644
--- a/src/test/ui/issues/issue-34334.stderr
+++ b/src/test/ui/issues/issue-34334.stderr
@@ -13,10 +13,12 @@ LL |     let sr: Vec<(u32, _, _)> = vec![];
    |                            +
 
 error[E0277]: a value of type `Vec<(u32, _, _)>` cannot be built from an iterator over elements of type `()`
-  --> $DIR/issue-34334.rs:5:87
+  --> $DIR/issue-34334.rs:5:33
    |
 LL |     let sr2: Vec<(u32, _, _)> = sr.iter().map(|(faction, th_sender, th_receiver)| {}).collect();
-   |                                                                                       ^^^^^^^ value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
+   |                                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |                                 |
+   |                                 value of type `Vec<(u32, _, _)>` cannot be built from `std::iter::Iterator<Item=()>`
    |
    = help: the trait `FromIterator<()>` is not implemented for `Vec<(u32, _, _)>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
diff --git a/src/test/ui/issues/issue-34349.stderr b/src/test/ui/issues/issue-34349.stderr
index d0b51961b44..8e9a16619f3 100644
--- a/src/test/ui/issues/issue-34349.stderr
+++ b/src/test/ui/issues/issue-34349.stderr
@@ -7,7 +7,15 @@ LL |         farewell.push_str("!!!");
    |         -------- closure is `FnMut` because it mutates the variable `farewell` here
 ...
 LL |     apply(diary);
-   |     ----- the requirement to implement `Fn` derives from here
+   |     ----- ----- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `apply`
+  --> $DIR/issue-34349.rs:11:32
+   |
+LL |     fn apply<F>(f: F) where F: Fn() {
+   |                                ^^^^ required by this bound in `apply`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-35570.rs b/src/test/ui/issues/issue-35570.rs
index 42cef9a47f2..a2b0222d4f3 100644
--- a/src/test/ui/issues/issue-35570.rs
+++ b/src/test/ui/issues/issue-35570.rs
@@ -6,7 +6,8 @@ trait Trait2<'a> {
 }
 
 fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
-//~^ the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+    //~^ ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+    //~| ERROR the trait bound `for<'a> (): Trait2<'a>` is not satisfied
     let _e: (usize, usize) = unsafe{mem::transmute(param)};
 }
 
diff --git a/src/test/ui/issues/issue-35570.stderr b/src/test/ui/issues/issue-35570.stderr
index 2697d46bdb2..ebc40f6786f 100644
--- a/src/test/ui/issues/issue-35570.stderr
+++ b/src/test/ui/issues/issue-35570.stderr
@@ -1,9 +1,19 @@
 error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
+  --> $DIR/issue-35570.rs:8:1
+   |
+LL | / fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
+LL | |
+LL | |
+LL | |     let _e: (usize, usize) = unsafe{mem::transmute(param)};
+LL | | }
+   | |_^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
+
+error[E0277]: the trait bound `for<'a> (): Trait2<'a>` is not satisfied
   --> $DIR/issue-35570.rs:8:40
    |
 LL | fn _ice(param: Box<dyn for <'a> Trait1<<() as Trait2<'a>>::Ty>>) {
    |                                        ^^^^^^^^^^^^^^^^^^^^^^ the trait `for<'a> Trait2<'a>` is not implemented for `()`
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-38821.stderr b/src/test/ui/issues/issue-38821.stderr
index cdf1f0dfc53..9abd2436b8a 100644
--- a/src/test/ui/issues/issue-38821.stderr
+++ b/src/test/ui/issues/issue-38821.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `<Col as Expression>::SqlType: NotNull` is not sat
 LL | #[derive(Debug, Copy, Clone)]
    |                 ^^^^ the trait `NotNull` is not implemented for `<Col as Expression>::SqlType`
    |
-note: required because of the requirements on the impl of `IntoNullable` for `<Col as Expression>::SqlType`
+note: required for `<Col as Expression>::SqlType` to implement `IntoNullable`
   --> $DIR/issue-38821.rs:9:18
    |
 LL | impl<T: NotNull> IntoNullable for T {
diff --git a/src/test/ui/issues/issue-39970.stderr b/src/test/ui/issues/issue-39970.stderr
index 1f64a90bc1c..774575d1d01 100644
--- a/src/test/ui/issues/issue-39970.stderr
+++ b/src/test/ui/issues/issue-39970.stderr
@@ -9,7 +9,7 @@ note: expected this to be `()`
    |
 LL |     type Element = &'a ();
    |                    ^^^^^^
-note: required because of the requirements on the impl of `Visit` for `()`
+note: required for `()` to implement `Visit`
   --> $DIR/issue-39970.rs:13:6
    |
 LL | impl Visit for () where
diff --git a/src/test/ui/issues/issue-40827.stderr b/src/test/ui/issues/issue-40827.stderr
index 11c23e5b659..7f5c578ae4f 100644
--- a/src/test/ui/issues/issue-40827.stderr
+++ b/src/test/ui/issues/issue-40827.stderr
@@ -12,7 +12,7 @@ note: required because it appears within the type `Bar`
    |
 LL | enum Bar {
    |      ^^^
-   = note: required because of the requirements on the impl of `Send` for `Arc<Bar>`
+   = note: required for `Arc<Bar>` to implement `Send`
 note: required because it appears within the type `Foo`
   --> $DIR/issue-40827.rs:4:8
    |
@@ -38,7 +38,7 @@ note: required because it appears within the type `Bar`
    |
 LL | enum Bar {
    |      ^^^
-   = note: required because of the requirements on the impl of `Send` for `Arc<Bar>`
+   = note: required for `Arc<Bar>` to implement `Send`
 note: required because it appears within the type `Foo`
   --> $DIR/issue-40827.rs:4:8
    |
diff --git a/src/test/ui/issues/issue-41974.stderr b/src/test/ui/issues/issue-41974.stderr
index fcbb4014025..e249db9df53 100644
--- a/src/test/ui/issues/issue-41974.stderr
+++ b/src/test/ui/issues/issue-41974.stderr
@@ -7,11 +7,11 @@ LL | impl<T> Drop for T where T: A {
    = note: implementing a foreign trait is only possible if at least one of the types for which it is implemented is local
    = note: only traits defined in the current crate can be implemented for a type parameter
 
-error[E0120]: the `Drop` trait may only be implemented for structs, enums, and unions
+error[E0120]: the `Drop` trait may only be implemented for local structs, enums, and unions
   --> $DIR/issue-41974.rs:7:18
    |
 LL | impl<T> Drop for T where T: A {
-   |                  ^ must be a struct, enum, or union
+   |                  ^ must be a struct, enum, or union in the current crate
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/issues/issue-59488.rs b/src/test/ui/issues/issue-59488.rs
index 922b593935a..384501e3e5d 100644
--- a/src/test/ui/issues/issue-59488.rs
+++ b/src/test/ui/issues/issue-59488.rs
@@ -30,4 +30,5 @@ fn main() {
     assert_eq!(Foo::Bar, i);
     //~^ ERROR binary operation `==` cannot be applied to type `fn(usize) -> Foo {Foo::Bar}` [E0369]
     //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277]
+    //~| ERROR `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug` [E0277]
 }
diff --git a/src/test/ui/issues/issue-59488.stderr b/src/test/ui/issues/issue-59488.stderr
index 7ce3dedaa88..bb6843a1958 100644
--- a/src/test/ui/issues/issue-59488.stderr
+++ b/src/test/ui/issues/issue-59488.stderr
@@ -106,7 +106,26 @@ LL |     assert_eq!(Foo::Bar, i);
            and 68 others
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 9 previous errors
+error[E0277]: `fn(usize) -> Foo {Foo::Bar}` doesn't implement `Debug`
+  --> $DIR/issue-59488.rs:30:5
+   |
+LL |     assert_eq!(Foo::Bar, i);
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ `fn(usize) -> Foo {Foo::Bar}` cannot be formatted using `{:?}` because it doesn't implement `Debug`
+   |
+   = help: the trait `Debug` is not implemented for `fn(usize) -> Foo {Foo::Bar}`
+   = help: the following other types implement trait `Debug`:
+             extern "C" fn() -> Ret
+             extern "C" fn(A, B) -> Ret
+             extern "C" fn(A, B, ...) -> Ret
+             extern "C" fn(A, B, C) -> Ret
+             extern "C" fn(A, B, C, ...) -> Ret
+             extern "C" fn(A, B, C, D) -> Ret
+             extern "C" fn(A, B, C, D, ...) -> Ret
+             extern "C" fn(A, B, C, D, E) -> Ret
+           and 68 others
+   = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 10 previous errors
 
 Some errors have detailed explanations: E0277, E0308, E0369.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/src/test/ui/issues/issue-60218.stderr b/src/test/ui/issues/issue-60218.stderr
index 870b2501447..dd72b6515dd 100644
--- a/src/test/ui/issues/issue-60218.stderr
+++ b/src/test/ui/issues/issue-60218.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `&u32: Foo` is not satisfied
-  --> $DIR/issue-60218.rs:18:27
+  --> $DIR/issue-60218.rs:18:19
    |
 LL |     trigger_error(vec![], |x: &u32| x)
-   |     -------------         ^^^^^^^^^^^ the trait `Foo` is not implemented for `&u32`
+   |     ------------- ^^^^^^ the trait `Foo` is not implemented for `&u32`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
index d6e39251632..2de15037650 100644
--- a/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
+++ b/src/test/ui/issues/issue-66923-show-error-for-correct-call.stderr
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:39
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:8:24
    |
 LL |     let x2: Vec<f64> = x1.into_iter().collect();
-   |                                       ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |                        ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |                        |
+   |                        value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
@@ -13,10 +15,12 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `Vec<f64>` cannot be built from an iterator over elements of type `&f64`
-  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:29
+  --> $DIR/issue-66923-show-error-for-correct-call.rs:12:14
    |
 LL |     let x3 = x1.into_iter().collect::<Vec<f64>>();
-   |                             ^^^^^^^ value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
+   |              ^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |              |
+   |              value of type `Vec<f64>` cannot be built from `std::iter::Iterator<Item=&f64>`
    |
    = help: the trait `FromIterator<&f64>` is not implemented for `Vec<f64>`
    = help: the trait `FromIterator<T>` is implemented for `Vec<T>`
diff --git a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
index 733456a1a8b..37e2c3bddc8 100644
--- a/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
+++ b/src/test/ui/issues/issue-67039-unsound-pin-partialeq.stderr
@@ -6,7 +6,7 @@ LL |     let _ = Pin::new(Apple) == Rc::pin(Apple);
    |
    = note: expected struct `Apple`
               found struct `Rc<Apple>`
-   = note: required because of the requirements on the impl of `PartialEq<Pin<Rc<Apple>>>` for `Pin<Apple>`
+   = note: required for `Pin<Apple>` to implement `PartialEq<Pin<Rc<Apple>>>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/issues/issue-69455.stderr b/src/test/ui/issues/issue-69455.stderr
index b732df764e5..9d11cf19ea7 100644
--- a/src/test/ui/issues/issue-69455.stderr
+++ b/src/test/ui/issues/issue-69455.stderr
@@ -16,7 +16,7 @@ error[E0283]: type annotations needed
 LL |     println!("{}", 23u64.test(xs.iter().sum()));
    |                          ----           ^^^ cannot infer type of the type parameter `S` declared on the associated function `sum`
    |                          |
-   |                          type must be known at this point
+   |                          required by a bound introduced by this call
    |
 note: multiple `impl`s satisfying `u64: Test<_>` found
   --> $DIR/issue-69455.rs:11:1
diff --git a/src/test/ui/issues/issue-7364.stderr b/src/test/ui/issues/issue-7364.stderr
index 1018a92f64d..5dc8c2b607e 100644
--- a/src/test/ui/issues/issue-7364.stderr
+++ b/src/test/ui/issues/issue-7364.stderr
@@ -5,7 +5,7 @@ LL | static boxed: Box<RefCell<isize>> = Box::new(RefCell::new(0));
    |               ^^^^^^^^^^^^^^^^^^^ `RefCell<isize>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `RefCell<isize>`
-   = note: required because of the requirements on the impl of `Sync` for `Unique<RefCell<isize>>`
+   = note: required for `Unique<RefCell<isize>>` to implement `Sync`
    = note: required because it appears within the type `Box<RefCell<isize>>`
    = note: shared static variables must have a type that implements `Sync`
 
diff --git a/src/test/ui/iterators/collect-into-array.rs b/src/test/ui/iterators/collect-into-array.rs
index a1144c8cb8c..7d35da82532 100644
--- a/src/test/ui/iterators/collect-into-array.rs
+++ b/src/test/ui/iterators/collect-into-array.rs
@@ -4,4 +4,5 @@ fn main() {
     //~^ ERROR an array of type `[u32; 10]` cannot be built directly from an iterator
     //~| NOTE try collecting into a `Vec<{integer}>`, then using `.try_into()`
     //~| NOTE required by a bound in `collect`
+    //~| NOTE required by a bound introduced by this call
 }
diff --git a/src/test/ui/iterators/collect-into-array.stderr b/src/test/ui/iterators/collect-into-array.stderr
index 7be53a4873b..7fe9707e6d2 100644
--- a/src/test/ui/iterators/collect-into-array.stderr
+++ b/src/test/ui/iterators/collect-into-array.stderr
@@ -1,8 +1,10 @@
 error[E0277]: an array of type `[u32; 10]` cannot be built directly from an iterator
-  --> $DIR/collect-into-array.rs:3:39
+  --> $DIR/collect-into-array.rs:3:31
    |
 LL |     let whatever: [u32; 10] = (0..10).collect();
-   |                                       ^^^^^^^ try collecting into a `Vec<{integer}>`, then using `.try_into()`
+   |                               ^^^^^^^ ------- required by a bound introduced by this call
+   |                               |
+   |                               try collecting into a `Vec<{integer}>`, then using `.try_into()`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[u32; 10]`
 note: required by a bound in `collect`
diff --git a/src/test/ui/iterators/collect-into-slice.rs b/src/test/ui/iterators/collect-into-slice.rs
index aafa6bc8b95..5eade075613 100644
--- a/src/test/ui/iterators/collect-into-slice.rs
+++ b/src/test/ui/iterators/collect-into-slice.rs
@@ -1,15 +1,20 @@
 fn process_slice(data: &[i32]) {
     //~^ NOTE required by a bound in this
+    //~| NOTE required by a bound in this
     todo!()
 }
 
 fn main() {
     let some_generated_vec = (0..10).collect();
     //~^ ERROR the size for values of type `[i32]` cannot be known at compilation time
+    //~| ERROR the size for values of type `[i32]` cannot be known at compilation time
     //~| ERROR a slice of type `[i32]` cannot be built since `[i32]` has no definite size
     //~| NOTE try explicitly collecting into a `Vec<{integer}>`
     //~| NOTE required by a bound in `collect`
+    //~| NOTE required by a bound in `collect`
     //~| NOTE all local variables must have a statically known size
     //~| NOTE doesn't have a size known at compile-time
+    //~| NOTE doesn't have a size known at compile-time
+    //~| NOTE required by a bound introduced by this call
     process_slice(&some_generated_vec);
 }
diff --git a/src/test/ui/iterators/collect-into-slice.stderr b/src/test/ui/iterators/collect-into-slice.stderr
index 4842e65fe97..bce40118bdf 100644
--- a/src/test/ui/iterators/collect-into-slice.stderr
+++ b/src/test/ui/iterators/collect-into-slice.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
-  --> $DIR/collect-into-slice.rs:7:9
+  --> $DIR/collect-into-slice.rs:8:9
    |
 LL |     let some_generated_vec = (0..10).collect();
    |         ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -8,11 +8,26 @@ LL |     let some_generated_vec = (0..10).collect();
    = note: all local variables must have a statically known size
    = help: unsized locals are gated as an unstable feature
 
+error[E0277]: the size for values of type `[i32]` cannot be known at compilation time
+  --> $DIR/collect-into-slice.rs:8:38
+   |
+LL |     let some_generated_vec = (0..10).collect();
+   |                                      ^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[i32]`
+note: required by a bound in `collect`
+  --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
+   |
+LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
+   |                ^ required by this bound in `collect`
+
 error[E0277]: a slice of type `[i32]` cannot be built since `[i32]` has no definite size
-  --> $DIR/collect-into-slice.rs:7:38
+  --> $DIR/collect-into-slice.rs:8:30
    |
 LL |     let some_generated_vec = (0..10).collect();
-   |                                      ^^^^^^^ try explicitly collecting into a `Vec<{integer}>`
+   |                              ^^^^^^^ ------- required by a bound introduced by this call
+   |                              |
+   |                              try explicitly collecting into a `Vec<{integer}>`
    |
    = help: the trait `FromIterator<{integer}>` is not implemented for `[i32]`
 note: required by a bound in `collect`
@@ -21,6 +36,6 @@ note: required by a bound in `collect`
 LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
-error: aborting due to 2 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/iterators/integral.stderr b/src/test/ui/iterators/integral.stderr
index 5e2744bab95..047a71f98d9 100644
--- a/src/test/ui/iterators/integral.stderr
+++ b/src/test/ui/iterators/integral.stderr
@@ -6,7 +6,7 @@ LL |     for _ in 42 {}
    |
    = help: the trait `Iterator` is not implemented for `{integer}`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `{integer}`
+   = note: required for `{integer}` to implement `IntoIterator`
 
 error[E0277]: `u8` is not an iterator
   --> $DIR/integral.rs:4:14
@@ -16,7 +16,7 @@ LL |     for _ in 42 as u8 {}
    |
    = help: the trait `Iterator` is not implemented for `u8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `u8`
+   = note: required for `u8` to implement `IntoIterator`
 
 error[E0277]: `i8` is not an iterator
   --> $DIR/integral.rs:6:14
@@ -26,7 +26,7 @@ LL |     for _ in 42 as i8 {}
    |
    = help: the trait `Iterator` is not implemented for `i8`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `i8`
+   = note: required for `i8` to implement `IntoIterator`
 
 error[E0277]: `u16` is not an iterator
   --> $DIR/integral.rs:8:14
@@ -36,7 +36,7 @@ LL |     for _ in 42 as u16 {}
    |
    = help: the trait `Iterator` is not implemented for `u16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `u16`
+   = note: required for `u16` to implement `IntoIterator`
 
 error[E0277]: `i16` is not an iterator
   --> $DIR/integral.rs:10:14
@@ -46,7 +46,7 @@ LL |     for _ in 42 as i16 {}
    |
    = help: the trait `Iterator` is not implemented for `i16`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `i16`
+   = note: required for `i16` to implement `IntoIterator`
 
 error[E0277]: `u32` is not an iterator
   --> $DIR/integral.rs:12:14
@@ -56,7 +56,7 @@ LL |     for _ in 42 as u32 {}
    |
    = help: the trait `Iterator` is not implemented for `u32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `u32`
+   = note: required for `u32` to implement `IntoIterator`
 
 error[E0277]: `i32` is not an iterator
   --> $DIR/integral.rs:14:14
@@ -66,7 +66,7 @@ LL |     for _ in 42 as i32 {}
    |
    = help: the trait `Iterator` is not implemented for `i32`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `i32`
+   = note: required for `i32` to implement `IntoIterator`
 
 error[E0277]: `u64` is not an iterator
   --> $DIR/integral.rs:16:14
@@ -76,7 +76,7 @@ LL |     for _ in 42 as u64 {}
    |
    = help: the trait `Iterator` is not implemented for `u64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `u64`
+   = note: required for `u64` to implement `IntoIterator`
 
 error[E0277]: `i64` is not an iterator
   --> $DIR/integral.rs:18:14
@@ -86,7 +86,7 @@ LL |     for _ in 42 as i64 {}
    |
    = help: the trait `Iterator` is not implemented for `i64`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `i64`
+   = note: required for `i64` to implement `IntoIterator`
 
 error[E0277]: `usize` is not an iterator
   --> $DIR/integral.rs:20:14
@@ -96,7 +96,7 @@ LL |     for _ in 42 as usize {}
    |
    = help: the trait `Iterator` is not implemented for `usize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `usize`
+   = note: required for `usize` to implement `IntoIterator`
 
 error[E0277]: `isize` is not an iterator
   --> $DIR/integral.rs:22:14
@@ -106,7 +106,7 @@ LL |     for _ in 42 as isize {}
    |
    = help: the trait `Iterator` is not implemented for `isize`
    = note: if you want to iterate between `start` until a value `end`, use the exclusive range syntax `start..end` or the inclusive range syntax `start..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `isize`
+   = note: required for `isize` to implement `IntoIterator`
 
 error[E0277]: `{float}` is not an iterator
   --> $DIR/integral.rs:24:14
@@ -115,7 +115,7 @@ LL |     for _ in 42.0 {}
    |              ^^^^ `{float}` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `{float}`
-   = note: required because of the requirements on the impl of `IntoIterator` for `{float}`
+   = note: required for `{float}` to implement `IntoIterator`
 
 error: aborting due to 12 previous errors
 
diff --git a/src/test/ui/iterators/issue-28098.stderr b/src/test/ui/iterators/issue-28098.stderr
index e7128248f93..53b610c1723 100644
--- a/src/test/ui/iterators/issue-28098.stderr
+++ b/src/test/ui/iterators/issue-28098.stderr
@@ -15,7 +15,7 @@ LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
-   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
+   = note: required for `bool` to implement `IntoIterator`
 
 error[E0277]: `()` is not an iterator
   --> $DIR/issue-28098.rs:8:28
@@ -54,7 +54,7 @@ LL |     for _ in false {}
    |              ^^^^^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
-   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
+   = note: required for `bool` to implement `IntoIterator`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/iterators/ranges.stderr b/src/test/ui/iterators/ranges.stderr
index 440a8960a4c..b9fbcd5304b 100644
--- a/src/test/ui/iterators/ranges.stderr
+++ b/src/test/ui/iterators/ranges.stderr
@@ -6,7 +6,7 @@ LL |     for _ in ..10 {}
    |
    = help: the trait `Iterator` is not implemented for `RangeTo<{integer}>`
    = note: `..end` is a `RangeTo`, which cannot be iterated on; you might have meant to have a bounded `Range`: `0..end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `RangeTo<{integer}>`
+   = note: required for `RangeTo<{integer}>` to implement `IntoIterator`
 
 error[E0277]: `RangeToInclusive<{integer}>` is not an iterator
   --> $DIR/ranges.rs:4:14
@@ -16,7 +16,7 @@ LL |     for _ in ..=10 {}
    |
    = help: the trait `Iterator` is not implemented for `RangeToInclusive<{integer}>`
    = note: `..=end` is a `RangeToInclusive`, which cannot be iterated on; you might have meant to have a bounded `RangeInclusive`: `0..=end`
-   = note: required because of the requirements on the impl of `IntoIterator` for `RangeToInclusive<{integer}>`
+   = note: required for `RangeToInclusive<{integer}>` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/iterators/string.stderr b/src/test/ui/iterators/string.stderr
index d9c40fe1ba6..ddfe0169b84 100644
--- a/src/test/ui/iterators/string.stderr
+++ b/src/test/ui/iterators/string.stderr
@@ -5,7 +5,7 @@ LL |     for _ in "".to_owned() {}
    |              ^^^^^^^^^^^^^ `String` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `String`
-   = note: required because of the requirements on the impl of `IntoIterator` for `String`
+   = note: required for `String` to implement `IntoIterator`
 
 error[E0277]: `&str` is not an iterator
   --> $DIR/string.rs:4:14
@@ -14,7 +14,7 @@ LL |     for _ in "" {}
    |              ^^ `&str` is not an iterator; try calling `.chars()` or `.bytes()`
    |
    = help: the trait `Iterator` is not implemented for `&str`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&str`
+   = note: required for `&str` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.rs b/src/test/ui/kindck/kindck-impl-type-params-2.rs
index 8b0771985dc..8950fc51e64 100644
--- a/src/test/ui/kindck/kindck-impl-type-params-2.rs
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.rs
@@ -11,5 +11,5 @@ fn take_param<T:Foo>(foo: &T) { }
 fn main() {
     let x: Box<_> = Box::new(3);
     take_param(&x);
-    //~^ ERROR the trait bound `Box<{integer}>: Foo` is not satisfied
+    //~^ ERROR the trait bound `Box<{integer}>: Copy` is not satisfied
 }
diff --git a/src/test/ui/kindck/kindck-impl-type-params-2.stderr b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
index 89975e9683d..930d96375bf 100644
--- a/src/test/ui/kindck/kindck-impl-type-params-2.stderr
+++ b/src/test/ui/kindck/kindck-impl-type-params-2.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-impl-type-params-2.rs:13:16
    |
 LL |     take_param(&x);
@@ -6,7 +6,7 @@ LL |     take_param(&x);
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
+note: required for `Box<{integer}>` to implement `Foo`
   --> $DIR/kindck-impl-type-params-2.rs:6:14
    |
 LL | impl<T:Copy> Foo for T {
diff --git a/src/test/ui/kindck/kindck-impl-type-params.stderr b/src/test/ui/kindck/kindck-impl-type-params.stderr
index 902349135c5..8dbe0c38c1e 100644
--- a/src/test/ui/kindck/kindck-impl-type-params.stderr
+++ b/src/test/ui/kindck/kindck-impl-type-params.stderr
@@ -4,7 +4,7 @@ error[E0277]: `T` cannot be sent between threads safely
 LL |     let a = &t as &dyn Gettable<T>;
    |             ^^ `T` cannot be sent between threads safely
    |
-note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -21,7 +21,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL |     let a = &t as &dyn Gettable<T>;
    |             ^^ the trait `Copy` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -38,7 +38,7 @@ error[E0277]: `T` cannot be sent between threads safely
 LL |     let a: &dyn Gettable<T> = &t;
    |                               ^^ `T` cannot be sent between threads safely
    |
-note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -55,7 +55,7 @@ error[E0277]: the trait bound `T: Copy` is not satisfied
 LL |     let a: &dyn Gettable<T> = &t;
    |                               ^^ the trait `Copy` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Gettable<T>` for `S<T>`
+note: required for `S<T>` to implement `Gettable<T>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -73,7 +73,7 @@ LL |     let a = t as Box<dyn Gettable<String>>;
    |             ^ the trait `Copy` is not implemented for `String`
    |
    = help: the trait `Gettable<T>` is implemented for `S<T>`
-note: required because of the requirements on the impl of `Gettable<String>` for `S<String>`
+note: required for `S<String>` to implement `Gettable<String>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
@@ -87,7 +87,7 @@ LL |     let a: Box<dyn Gettable<Foo>> = t;
    |                                     ^ the trait `Copy` is not implemented for `Foo`
    |
    = help: the trait `Gettable<T>` is implemented for `S<T>`
-note: required because of the requirements on the impl of `Gettable<Foo>` for `S<Foo>`
+note: required for `S<Foo>` to implement `Gettable<Foo>`
   --> $DIR/kindck-impl-type-params.rs:12:32
    |
 LL | impl<T: Send + Copy + 'static> Gettable<T> for S<T> {}
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
index 016cd393c85..e81d2441e6e 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.curr.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
@@ -6,7 +6,7 @@ LL |     take_param(&x);
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
+note: required for `Box<{integer}>` to implement `Foo`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
    |
 LL | impl<T:Copy> Foo for T {
@@ -44,7 +44,7 @@ LL | trait Foo : Copy {
    |       ---   ^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Foo>` for `&Box<{integer}>`
+   = note: required for `&Box<{integer}>` to implement `CoerceUnsized<&dyn Foo>`
    = note: required by cast to type `&dyn Foo`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
index eaf34dff41b..2380533b9c3 100644
--- a/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
+++ b/src/test/ui/kindck/kindck-inherited-copy-bound.object_safe_for_dispatch.stderr
@@ -1,4 +1,4 @@
-error[E0277]: the trait bound `Box<{integer}>: Foo` is not satisfied
+error[E0277]: the trait bound `Box<{integer}>: Copy` is not satisfied
   --> $DIR/kindck-inherited-copy-bound.rs:21:16
    |
 LL |     take_param(&x);
@@ -6,7 +6,7 @@ LL |     take_param(&x);
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Foo` for `Box<{integer}>`
+note: required for `Box<{integer}>` to implement `Foo`
   --> $DIR/kindck-inherited-copy-bound.rs:14:14
    |
 LL | impl<T:Copy> Foo for T {
@@ -30,7 +30,7 @@ LL | trait Foo : Copy {
    |       ---   ^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Foo>` for `&Box<i32>`
+   = note: required for `&Box<i32>` to implement `CoerceUnsized<&dyn Foo>`
    = note: required by cast to type `&dyn Foo`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/kindck/kindck-nonsendable-1.stderr b/src/test/ui/kindck/kindck-nonsendable-1.stderr
index eab003a1107..cc6e1f59c77 100644
--- a/src/test/ui/kindck/kindck-nonsendable-1.stderr
+++ b/src/test/ui/kindck/kindck-nonsendable-1.stderr
@@ -1,10 +1,12 @@
 error[E0277]: `Rc<usize>` cannot be sent between threads safely
-  --> $DIR/kindck-nonsendable-1.rs:9:5
+  --> $DIR/kindck-nonsendable-1.rs:9:9
    |
 LL |     bar(move|| foo(x));
-   |     ^^^ ------ within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`
-   |     |
-   |     `Rc<usize>` cannot be sent between threads safely
+   |     --- ------^^^^^^^
+   |     |   |
+   |     |   `Rc<usize>` cannot be sent between threads safely
+   |     |   within this `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`
+   |     required by a bound introduced by this call
    |
    = help: within `[closure@$DIR/kindck-nonsendable-1.rs:9:9: 9:15]`, the trait `Send` is not implemented for `Rc<usize>`
 note: required because it's used within this closure
diff --git a/src/test/ui/kindck/kindck-send-object.stderr b/src/test/ui/kindck/kindck-send-object.stderr
index f14983a5189..e9bbeeacd70 100644
--- a/src/test/ui/kindck/kindck-send-object.stderr
+++ b/src/test/ui/kindck/kindck-send-object.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object.rs:12:5
+  --> $DIR/kindck-send-object.rs:12:19
    |
 LL |     assert_send::<&'static (dyn Dummy + 'static)>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
-   = note: required because of the requirements on the impl of `Send` for `&'static (dyn Dummy + 'static)`
+   = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object.rs:5:18
    |
@@ -13,13 +13,13 @@ LL | fn assert_send<T:Send>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
-  --> $DIR/kindck-send-object.rs:17:5
+  --> $DIR/kindck-send-object.rs:17:19
    |
 LL |     assert_send::<Box<dyn Dummy>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `dyn Dummy`
-   = note: required because of the requirements on the impl of `Send` for `Unique<dyn Dummy>`
+   = note: required for `Unique<dyn Dummy>` to implement `Send`
    = note: required because it appears within the type `Box<dyn Dummy>`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object.rs:5:18
diff --git a/src/test/ui/kindck/kindck-send-object1.stderr b/src/test/ui/kindck/kindck-send-object1.stderr
index 1f5e21cbf97..11f597fee91 100644
--- a/src/test/ui/kindck/kindck-send-object1.stderr
+++ b/src/test/ui/kindck/kindck-send-object1.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `(dyn Dummy + 'a)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object1.rs:10:5
+  --> $DIR/kindck-send-object1.rs:10:19
    |
 LL |     assert_send::<&'a dyn Dummy>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'a)`
-   = note: required because of the requirements on the impl of `Send` for `&'a (dyn Dummy + 'a)`
+   = note: required for `&'a (dyn Dummy + 'a)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object1.rs:5:18
    |
@@ -13,13 +13,13 @@ LL | fn assert_send<T:Send+'static>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `(dyn Dummy + 'a)` cannot be sent between threads safely
-  --> $DIR/kindck-send-object1.rs:28:5
+  --> $DIR/kindck-send-object1.rs:28:19
    |
 LL |     assert_send::<Box<dyn Dummy + 'a>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'a)` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `(dyn Dummy + 'a)`
-   = note: required because of the requirements on the impl of `Send` for `Unique<(dyn Dummy + 'a)>`
+   = note: required for `Unique<(dyn Dummy + 'a)>` to implement `Send`
    = note: required because it appears within the type `Box<(dyn Dummy + 'a)>`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object1.rs:5:18
diff --git a/src/test/ui/kindck/kindck-send-object2.stderr b/src/test/ui/kindck/kindck-send-object2.stderr
index 527127e95a2..b8af33d0dc1 100644
--- a/src/test/ui/kindck/kindck-send-object2.stderr
+++ b/src/test/ui/kindck/kindck-send-object2.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `(dyn Dummy + 'static)` cannot be shared between threads safely
-  --> $DIR/kindck-send-object2.rs:7:5
+  --> $DIR/kindck-send-object2.rs:7:19
    |
 LL |     assert_send::<&'static dyn Dummy>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
+   |                   ^^^^^^^^^^^^^^^^^^ `(dyn Dummy + 'static)` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `(dyn Dummy + 'static)`
-   = note: required because of the requirements on the impl of `Send` for `&'static (dyn Dummy + 'static)`
+   = note: required for `&'static (dyn Dummy + 'static)` to implement `Send`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object2.rs:3:18
    |
@@ -13,13 +13,13 @@ LL | fn assert_send<T:Send>() { }
    |                  ^^^^ required by this bound in `assert_send`
 
 error[E0277]: `dyn Dummy` cannot be sent between threads safely
-  --> $DIR/kindck-send-object2.rs:12:5
+  --> $DIR/kindck-send-object2.rs:12:19
    |
 LL |     assert_send::<Box<dyn Dummy>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^^^ `dyn Dummy` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `dyn Dummy`
-   = note: required because of the requirements on the impl of `Send` for `Unique<dyn Dummy>`
+   = note: required for `Unique<dyn Dummy>` to implement `Send`
    = note: required because it appears within the type `Box<dyn Dummy>`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-object2.rs:3:18
diff --git a/src/test/ui/kindck/kindck-send-owned.stderr b/src/test/ui/kindck/kindck-send-owned.stderr
index 454291aa95b..b03f56465ce 100644
--- a/src/test/ui/kindck/kindck-send-owned.stderr
+++ b/src/test/ui/kindck/kindck-send-owned.stderr
@@ -1,11 +1,11 @@
 error[E0277]: `*mut u8` cannot be sent between threads safely
-  --> $DIR/kindck-send-owned.rs:12:5
+  --> $DIR/kindck-send-owned.rs:12:19
    |
 LL |     assert_send::<Box<*mut u8>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
+   |                   ^^^^^^^^^^^^ `*mut u8` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `*mut u8`
-   = note: required because of the requirements on the impl of `Send` for `Unique<*mut u8>`
+   = note: required for `Unique<*mut u8>` to implement `Send`
    = note: required because it appears within the type `Box<*mut u8>`
 note: required by a bound in `assert_send`
   --> $DIR/kindck-send-owned.rs:3:18
diff --git a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
index 6b87da0c040..33f82448dd2 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/branches.stderr
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:28
+  --> $DIR/branches.rs:19:9
    |
 LL |         std::iter::empty().collect()
-   |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Bar`
 note: required by a bound in `collect`
diff --git a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
index 42a1f782d29..57978edf2bf 100644
--- a/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
+++ b/src/test/ui/lazy-type-alias-impl-trait/recursion4.stderr
@@ -1,8 +1,10 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:28
+  --> $DIR/recursion4.rs:10:9
    |
 LL |     x = std::iter::empty().collect();
-   |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `Foo`
 note: required by a bound in `collect`
@@ -12,10 +14,12 @@ LL |     fn collect<B: FromIterator<Self::Item>>(self) -> B
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `collect`
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:28
+  --> $DIR/recursion4.rs:19:9
    |
 LL |     x = std::iter::empty().collect();
-   |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
+   |         ^^^^^^^^^^^^^^^^^^ ------- required by a bound introduced by this call
+   |         |
+   |         value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
    |
    = help: the trait `FromIterator<_>` is not implemented for `impl Debug`
 note: required by a bound in `collect`
diff --git a/src/test/ui/lexical-scopes.stderr b/src/test/ui/lexical-scopes.stderr
index 3b2a062c1c2..ad11f72a31d 100644
--- a/src/test/ui/lexical-scopes.stderr
+++ b/src/test/ui/lexical-scopes.stderr
@@ -1,6 +1,8 @@
 error[E0574]: expected struct, variant or union type, found type parameter `T`
   --> $DIR/lexical-scopes.rs:3:13
    |
+LL | fn f<T>() {
+   |      - found this type pararmeter
 LL |     let t = T { i: 0 };
    |             ^ not a struct, variant or union type
 
diff --git a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs
new file mode 100644
index 00000000000..1bc4a381257
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.rs
@@ -0,0 +1,30 @@
+// edition:2018
+// compile-flags: -Zdrop-tracking
+#![feature(must_not_suspend)]
+#![deny(must_not_suspend)]
+
+#[must_not_suspend = "You gotta use Umm's, ya know?"]
+struct Umm {
+    i: i64
+}
+
+struct Bar {
+    u: Umm,
+}
+
+async fn other() {}
+
+impl Bar {
+    async fn uhoh(&mut self) {
+        let guard = &mut self.u; //~ ERROR `Umm` held across
+
+        other().await;
+
+        *guard = Umm {
+            i: 2
+        }
+    }
+}
+
+fn main() {
+}
diff --git a/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
new file mode 100644
index 00000000000..c49d2712853
--- /dev/null
+++ b/src/test/ui/lint/must_not_suspend/ref-drop-tracking.stderr
@@ -0,0 +1,27 @@
+error: reference to `Umm` held across a suspend point, but should not be
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+LL |
+LL |         other().await;
+   |                ------ the value is held across this suspend point
+   |
+note: the lint level is defined here
+  --> $DIR/ref-drop-tracking.rs:4:9
+   |
+LL | #![deny(must_not_suspend)]
+   |         ^^^^^^^^^^^^^^^^
+note: You gotta use Umm's, ya know?
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+help: consider using a block (`{ ... }`) to shrink the value's scope, ending before the suspend point
+  --> $DIR/ref-drop-tracking.rs:19:13
+   |
+LL |         let guard = &mut self.u;
+   |             ^^^^^
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
deleted file mode 100644
index 217392aa35b..00000000000
--- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllleak.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown debugging option: `borrowck`
-
diff --git a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr b/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr
deleted file mode 100644
index 217392aa35b..00000000000
--- a/src/test/ui/lub-glb/old-lub-glb-hr-noteq1.nllnoleak.stderr
+++ /dev/null
@@ -1,2 +0,0 @@
-error: unknown debugging option: `borrowck`
-
diff --git a/src/test/ui/macros/stringify.rs b/src/test/ui/macros/stringify.rs
index 8e71ed7c112..082c1abb8f2 100644
--- a/src/test/ui/macros/stringify.rs
+++ b/src/test/ui/macros/stringify.rs
@@ -3,11 +3,18 @@
 // compile-flags: --test
 
 #![feature(async_closure)]
+#![feature(box_patterns)]
+#![feature(box_syntax)]
 #![feature(const_trait_impl)]
+#![feature(decl_macro)]
 #![feature(generators)]
 #![feature(half_open_range_patterns)]
+#![feature(label_break_value)]
 #![feature(more_qualified_paths)]
 #![feature(raw_ref_op)]
+#![feature(trait_alias)]
+#![feature(try_blocks)]
+#![feature(type_ascription)]
 #![deny(unused_macros)]
 
 macro_rules! stringify_block {
diff --git a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
index c2515c40b1d..36748fae13c 100644
--- a/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
+++ b/src/test/ui/mismatched_types/method-help-unsatisfied-bound.stderr
@@ -1,8 +1,10 @@
 error[E0277]: `Foo` doesn't implement `Debug`
-  --> $DIR/method-help-unsatisfied-bound.rs:5:7
+  --> $DIR/method-help-unsatisfied-bound.rs:5:5
    |
 LL |     a.unwrap();
-   |       ^^^^^^ `Foo` cannot be formatted using `{:?}`
+   |     ^ ------ required by a bound introduced by this call
+   |     |
+   |     `Foo` cannot be formatted using `{:?}`
    |
    = help: the trait `Debug` is not implemented for `Foo`
    = note: add `#[derive(Debug)]` to `Foo` or manually `impl Debug for Foo`
diff --git a/src/test/ui/mutexguard-sync.stderr b/src/test/ui/mutexguard-sync.stderr
index b3c77b13eaf..3fbb2ddf183 100644
--- a/src/test/ui/mutexguard-sync.stderr
+++ b/src/test/ui/mutexguard-sync.stderr
@@ -7,7 +7,7 @@ LL |     test_sync(guard);
    |     required by a bound introduced by this call
    |
    = help: the trait `Sync` is not implemented for `Cell<i32>`
-   = note: required because of the requirements on the impl of `Sync` for `MutexGuard<'_, Cell<i32>>`
+   = note: required for `MutexGuard<'_, Cell<i32>>` to implement `Sync`
 note: required by a bound in `test_sync`
   --> $DIR/mutexguard-sync.rs:5:17
    |
diff --git a/src/test/ui/never_type/defaulted-never-note.fallback.stderr b/src/test/ui/never_type/defaulted-never-note.fallback.stderr
index 4c8b4922473..283aca1b084 100644
--- a/src/test/ui/never_type/defaulted-never-note.fallback.stderr
+++ b/src/test/ui/never_type/defaulted-never-note.fallback.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `!: ImplementedForUnitButNotNever` is not satisfied
-  --> $DIR/defaulted-never-note.rs:30:5
+  --> $DIR/defaulted-never-note.rs:30:9
    |
 LL |     foo(_x);
-   |     ^^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+   |     --- ^^ the trait `ImplementedForUnitButNotNever` is not implemented for `!`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `ImplementedForUnitButNotNever` is implemented for `()`
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
diff --git a/src/test/ui/never_type/defaulted-never-note.rs b/src/test/ui/never_type/defaulted-never-note.rs
index aefc739a0a0..d30ffcd3846 100644
--- a/src/test/ui/never_type/defaulted-never-note.rs
+++ b/src/test/ui/never_type/defaulted-never-note.rs
@@ -32,6 +32,7 @@ fn smeg() {
     //[fallback]~| NOTE the trait `ImplementedForUnitButNotNever` is not implemented
     //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()`
     //[fallback]~| NOTE this error might have been caused
+    //[fallback]~| NOTE required by a bound introduced by this call
     //[fallback]~| HELP did you intend
 }
 
diff --git a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
index dee2b1d704b..3215c4669d5 100644
--- a/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
+++ b/src/test/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `!: Test` is not satisfied
-  --> $DIR/diverging-fallback-no-leak.rs:17:5
+  --> $DIR/diverging-fallback-no-leak.rs:17:23
    |
 LL |     unconstrained_arg(return);
-   |     ^^^^^^^^^^^^^^^^^ the trait `Test` is not implemented for `!`
+   |     ----------------- ^^^^^^ the trait `Test` is not implemented for `!`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `Test`:
              ()
diff --git a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
index 54abed38300..6dc039fc35d 100644
--- a/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
+++ b/src/test/ui/never_type/feature-gate-never_type_fallback.stderr
@@ -1,8 +1,12 @@
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/feature-gate-never_type_fallback.rs:10:5
+  --> $DIR/feature-gate-never_type_fallback.rs:10:9
    |
 LL |     foo(panic!())
-   |     ^^^ the trait `T` is not implemented for `()`
+   |     --- ^^^^^^^^
+   |     |   |
+   |     |   the trait `T` is not implemented for `()`
+   |     |   this tail expression is of type `_`
+   |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
   --> $DIR/feature-gate-never_type_fallback.rs:13:16
diff --git a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
index e2045591390..06e902bca70 100644
--- a/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
+++ b/src/test/ui/never_type/never-value-fallback-issue-66757.nofallback.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `E: From<()>` is not satisfied
-  --> $DIR/never-value-fallback-issue-66757.rs:28:5
+  --> $DIR/never-value-fallback-issue-66757.rs:28:26
    |
 LL |     <E as From<_>>::from(never);
-   |     ^^^^^^^^^^^^^^^^^^^^ the trait `From<()>` is not implemented for `E`
+   |     -------------------- ^^^^^ the trait `From<()>` is not implemented for `E`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `From<!>` is implemented for `E`
 
diff --git a/src/test/ui/nll/normalization-bounds-error.stderr b/src/test/ui/nll/normalization-bounds-error.stderr
index 6da3d5d9692..6abe53127c3 100644
--- a/src/test/ui/nll/normalization-bounds-error.stderr
+++ b/src/test/ui/nll/normalization-bounds-error.stderr
@@ -1,8 +1,8 @@
 error[E0495]: cannot infer an appropriate lifetime for lifetime parameter `'d` due to conflicting requirements
-  --> $DIR/normalization-bounds-error.rs:12:4
+  --> $DIR/normalization-bounds-error.rs:12:1
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   |    ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'d` as defined here...
   --> $DIR/normalization-bounds-error.rs:12:14
@@ -15,10 +15,10 @@ note: ...but the lifetime must also be valid for the lifetime `'a` as defined he
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
    |                  ^^
 note: ...so that the types are compatible
-  --> $DIR/normalization-bounds-error.rs:12:4
+  --> $DIR/normalization-bounds-error.rs:12:1
    |
 LL | fn visit_seq<'d, 'a: 'd>() -> <&'a () as Visitor<'d>>::Value {}
-   |    ^^^^^^^^^
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: expected `Visitor<'d>`
               found `Visitor<'_>`
 
diff --git a/src/test/ui/no-send-res-ports.stderr b/src/test/ui/no-send-res-ports.stderr
index 249c2fe2fa7..c864b93dbbb 100644
--- a/src/test/ui/no-send-res-ports.stderr
+++ b/src/test/ui/no-send-res-ports.stderr
@@ -1,10 +1,17 @@
 error[E0277]: `Rc<()>` cannot be sent between threads safely
-  --> $DIR/no-send-res-ports.rs:25:5
+  --> $DIR/no-send-res-ports.rs:25:19
    |
-LL |     thread::spawn(move|| {
-   |     ^^^^^^^^^^^^^ ------ within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`
-   |     |
-   |     `Rc<()>` cannot be sent between threads safely
+LL |       thread::spawn(move|| {
+   |       ------------- ^-----
+   |       |             |
+   |  _____|_____________within this `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`
+   | |     |
+   | |     required by a bound introduced by this call
+LL | |
+LL | |         let y = x;
+LL | |         println!("{:?}", y);
+LL | |     });
+   | |_____^ `Rc<()>` cannot be sent between threads safely
    |
    = help: within `[closure@$DIR/no-send-res-ports.rs:25:19: 25:25]`, the trait `Send` is not implemented for `Rc<()>`
 note: required because it appears within the type `Port<()>`
diff --git a/src/test/ui/not-clone-closure.stderr b/src/test/ui/not-clone-closure.stderr
index 37d94cf0ebd..f61ee661bb7 100644
--- a/src/test/ui/not-clone-closure.stderr
+++ b/src/test/ui/not-clone-closure.stderr
@@ -1,11 +1,13 @@
 error[E0277]: the trait bound `S: Clone` is not satisfied in `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
-  --> $DIR/not-clone-closure.rs:11:23
+  --> $DIR/not-clone-closure.rs:11:17
    |
 LL |     let hello = move || {
    |                 ------- within this `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`
 ...
 LL |     let hello = hello.clone();
-   |                       ^^^^^ within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
+   |                 ^^^^^ ----- required by a bound introduced by this call
+   |                 |
+   |                 within `[closure@$DIR/not-clone-closure.rs:7:17: 7:24]`, the trait `Clone` is not implemented for `S`
    |
 note: required because it's used within this closure
   --> $DIR/not-clone-closure.rs:7:17
diff --git a/src/test/ui/not-panic/not-panic-safe-2.stderr b/src/test/ui/not-panic/not-panic-safe-2.stderr
index 65594702bc4..3b0f83b3b9a 100644
--- a/src/test/ui/not-panic/not-panic-safe-2.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-2.stderr
@@ -1,12 +1,12 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-2.rs:10:5
+  --> $DIR/not-panic-safe-2.rs:10:14
    |
 LL |     assert::<Rc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `Rc<RefCell<i32>>`
+   = note: required for `Rc<RefCell<i32>>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-2.rs:7:14
    |
@@ -14,15 +14,15 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-2.rs:10:5
+  --> $DIR/not-panic-safe-2.rs:10:14
    |
 LL |     assert::<Rc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `Rc<RefCell<i32>>`
+   = note: required for `Rc<RefCell<i32>>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-2.rs:7:14
    |
diff --git a/src/test/ui/not-panic/not-panic-safe-3.stderr b/src/test/ui/not-panic/not-panic-safe-3.stderr
index db3fdb25345..9e9a12764a4 100644
--- a/src/test/ui/not-panic/not-panic-safe-3.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-3.stderr
@@ -1,12 +1,12 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-3.rs:10:5
+  --> $DIR/not-panic-safe-3.rs:10:14
    |
 LL |     assert::<Arc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `Arc<RefCell<i32>>`
+   = note: required for `Arc<RefCell<i32>>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-3.rs:7:14
    |
@@ -14,15 +14,15 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-3.rs:10:5
+  --> $DIR/not-panic-safe-3.rs:10:14
    |
 LL |     assert::<Arc<RefCell<i32>>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `Arc<RefCell<i32>>`
+   = note: required for `Arc<RefCell<i32>>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-3.rs:7:14
    |
diff --git a/src/test/ui/not-panic/not-panic-safe-4.stderr b/src/test/ui/not-panic/not-panic-safe-4.stderr
index 079601b39c0..fc1c594d0d4 100644
--- a/src/test/ui/not-panic/not-panic-safe-4.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-4.stderr
@@ -1,12 +1,12 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-4.rs:9:5
+  --> $DIR/not-panic-safe-4.rs:9:14
    |
 LL |     assert::<&RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `&RefCell<i32>`
+   = note: required for `&RefCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-4.rs:6:14
    |
@@ -14,15 +14,15 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-4.rs:9:5
+  --> $DIR/not-panic-safe-4.rs:9:14
    |
 LL |     assert::<&RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `&RefCell<i32>`
+   = note: required for `&RefCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-4.rs:6:14
    |
diff --git a/src/test/ui/not-panic/not-panic-safe-5.stderr b/src/test/ui/not-panic/not-panic-safe-5.stderr
index edd0f72dd3b..cb78370b48a 100644
--- a/src/test/ui/not-panic/not-panic-safe-5.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-5.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-5.rs:9:5
+  --> $DIR/not-panic-safe-5.rs:9:14
    |
 LL |     assert::<*const UnsafeCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `*const UnsafeCell<i32>`
+   = note: required for `*const UnsafeCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-5.rs:6:14
    |
diff --git a/src/test/ui/not-panic/not-panic-safe-6.stderr b/src/test/ui/not-panic/not-panic-safe-6.stderr
index f3b784a2956..7986e341eb0 100644
--- a/src/test/ui/not-panic/not-panic-safe-6.stderr
+++ b/src/test/ui/not-panic/not-panic-safe-6.stderr
@@ -1,12 +1,12 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-6.rs:9:5
+  --> $DIR/not-panic-safe-6.rs:9:14
    |
 LL |     assert::<*mut RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<i32>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `*mut RefCell<i32>`
+   = note: required for `*mut RefCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-6.rs:6:14
    |
@@ -14,15 +14,15 @@ LL | fn assert<T: UnwindSafe + ?Sized>() {}
    |              ^^^^^^^^^^ required by this bound in `assert`
 
 error[E0277]: the type `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/not-panic-safe-6.rs:9:5
+  --> $DIR/not-panic-safe-6.rs:9:14
    |
 LL |     assert::<*mut RefCell<i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
+   |              ^^^^^^^^^^^^^^^^^ `UnsafeCell<isize>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
    |
    = help: within `RefCell<i32>`, the trait `RefUnwindSafe` is not implemented for `UnsafeCell<isize>`
    = note: required because it appears within the type `Cell<isize>`
    = note: required because it appears within the type `RefCell<i32>`
-   = note: required because of the requirements on the impl of `UnwindSafe` for `*mut RefCell<i32>`
+   = note: required for `*mut RefCell<i32>` to implement `UnwindSafe`
 note: required by a bound in `assert`
   --> $DIR/not-panic-safe-6.rs:6:14
    |
diff --git a/src/test/ui/object-safety/issue-19538.stderr b/src/test/ui/object-safety/issue-19538.stderr
index 7b37e1f95dc..8420637b3de 100644
--- a/src/test/ui/object-safety/issue-19538.stderr
+++ b/src/test/ui/object-safety/issue-19538.stderr
@@ -29,7 +29,7 @@ LL |     fn foo<T>(&self, val: T);
 LL | trait Bar: Foo { }
    |       --- this trait cannot be made into an object...
    = help: consider moving `foo` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&mut dyn Bar>` for `&mut Thing`
+   = note: required for `&mut Thing` to implement `CoerceUnsized<&mut dyn Bar>`
    = note: required by cast to type `&mut dyn Bar`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
index 9ba3b251e66..f44de07d5da 100644
--- a/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-associated-consts.object_safe_for_dispatch.stderr
@@ -12,7 +12,7 @@ LL | trait Bar {
 LL |     const X: usize;
    |           ^ ...because it contains this associated `const`
    = help: consider moving `X` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error: aborting due to previous error
diff --git a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
index 86355627c79..9a2d472d5e7 100644
--- a/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-generics.object_safe_for_dispatch.stderr
@@ -12,7 +12,7 @@ LL | trait Bar {
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
    = help: consider moving `bar` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error[E0038]: the trait `Bar` cannot be made into an object
@@ -29,7 +29,7 @@ LL | trait Bar {
 LL |     fn bar<T>(&self, t: T);
    |        ^^^ ...because method `bar` has generic type parameters
    = help: consider moving `bar` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
index f48628c9d11..40a298bd1a7 100644
--- a/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-mentions-Self.object_safe_for_dispatch.stderr
@@ -12,7 +12,7 @@ LL | trait Bar {
 LL |     fn bar(&self, x: &Self);
    |                      ^^^^^ ...because method `bar` references the `Self` type in this parameter
    = help: consider moving `bar` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error[E0038]: the trait `Baz` cannot be made into an object
@@ -29,7 +29,7 @@ LL | trait Baz {
 LL |     fn baz(&self) -> Self;
    |                      ^^^^ ...because method `baz` references the `Self` type in its return type
    = help: consider moving `baz` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Baz>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Baz>`
    = note: required by cast to type `&dyn Baz`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
index ea1c575ff8c..da87b58c9e2 100644
--- a/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-no-static.object_safe_for_dispatch.stderr
@@ -11,7 +11,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo() {}
    |        ^^^ ...because associated function `foo` has no `self` parameter
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<Bar>`
+   = note: required for `Box<Bar>` to implement `CoerceUnsized<Box<dyn Foo>>`
    = note: required by cast to type `Box<dyn Foo>`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
diff --git a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
index b6e4903b079..6c29c8d5f7c 100644
--- a/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-sized-2.object_safe_for_dispatch.stderr
@@ -11,7 +11,7 @@ LL | trait Bar
    |       --- this trait cannot be made into an object...
 LL |     where Self : Sized
    |                  ^^^^^ ...because it requires `Self: Sized`
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error: aborting due to previous error
diff --git a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
index 645852c7e71..70a44ed6101 100644
--- a/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
+++ b/src/test/ui/object-safety/object-safety-sized.object_safe_for_dispatch.stderr
@@ -11,7 +11,7 @@ LL | trait Bar : Sized {
    |       ---   ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Bar>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Bar>`
    = note: required by cast to type `&dyn Bar`
 
 error: aborting due to previous error
diff --git a/src/test/ui/on-unimplemented/multiple-impls.stderr b/src/test/ui/on-unimplemented/multiple-impls.stderr
index 6e3601d7bf4..d47a398412f 100644
--- a/src/test/ui/on-unimplemented/multiple-impls.stderr
+++ b/src/test/ui/on-unimplemented/multiple-impls.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/multiple-impls.rs:33:18
+  --> $DIR/multiple-impls.rs:33:33
    |
 LL |     Index::index(&[] as &[i32], 2u32);
-   |     ------------ ^^^^^^^^^^^^^ trait message
+   |     ------------                ^^^^ trait message
    |     |
    |     required by a bound introduced by this call
    |
@@ -12,10 +12,10 @@ LL |     Index::index(&[] as &[i32], 2u32);
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Foo<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:35:18
+  --> $DIR/multiple-impls.rs:35:33
    |
 LL |     Index::index(&[] as &[i32], Foo(2u32));
-   |     ------------ ^^^^^^^^^^^^^ on impl for Foo
+   |     ------------                ^^^^^^^^^ on impl for Foo
    |     |
    |     required by a bound introduced by this call
    |
@@ -25,10 +25,10 @@ LL |     Index::index(&[] as &[i32], Foo(2u32));
              <[i32] as Index<Foo<usize>>>
 
 error[E0277]: the trait bound `[i32]: Index<Bar<u32>>` is not satisfied
-  --> $DIR/multiple-impls.rs:37:18
+  --> $DIR/multiple-impls.rs:37:33
    |
 LL |     Index::index(&[] as &[i32], Bar(2u32));
-   |     ------------ ^^^^^^^^^^^^^ on impl for Bar
+   |     ------------                ^^^^^^^^^ on impl for Bar
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/on-unimplemented/on-impl.stderr b/src/test/ui/on-unimplemented/on-impl.stderr
index 396c062cfe2..01315b85409 100644
--- a/src/test/ui/on-unimplemented/on-impl.stderr
+++ b/src/test/ui/on-unimplemented/on-impl.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `[i32]: Index<u32>` is not satisfied
-  --> $DIR/on-impl.rs:22:25
+  --> $DIR/on-impl.rs:22:47
    |
 LL |     Index::<u32>::index(&[1, 2, 3] as &[i32], 2u32);
-   |     ------------------- ^^^^^^^^^^^^^^^^^^^^ a usize is required to index into a slice
+   |     -------------------                       ^^^^ a usize is required to index into a slice
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/on-unimplemented/slice-index.stderr b/src/test/ui/on-unimplemented/slice-index.stderr
index 72f67a68515..a7ec3bda85e 100644
--- a/src/test/ui/on-unimplemented/slice-index.stderr
+++ b/src/test/ui/on-unimplemented/slice-index.stderr
@@ -6,7 +6,7 @@ LL |     x[1i32];
    |
    = help: the trait `SliceIndex<[i32]>` is not implemented for `i32`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<i32>` for `[i32]`
+   = note: required for `[i32]` to implement `Index<i32>`
 
 error[E0277]: the type `[i32]` cannot be indexed by `RangeTo<i32>`
   --> $DIR/slice-index.rs:9:7
@@ -18,7 +18,7 @@ LL |     x[..1i32];
    = help: the following other types implement trait `SliceIndex<T>`:
              <RangeTo<usize> as SliceIndex<[T]>>
              <RangeTo<usize> as SliceIndex<str>>
-   = note: required because of the requirements on the impl of `Index<RangeTo<i32>>` for `[i32]`
+   = note: required for `[i32]` to implement `Index<RangeTo<i32>>`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/or-patterns/inner-or-pat.or3.stderr b/src/test/ui/or-patterns/inner-or-pat.or3.stderr
new file mode 100644
index 00000000000..2236a38c37b
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat.or3.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/inner-or-pat.rs:38:54
+   |
+LL |     match x {
+   |           - this expression has type `&str`
+LL |         x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
+   |                                                      ^^ expected `str`, found `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/src/test/ui/or-patterns/inner-or-pat.or4.stderr b/src/test/ui/or-patterns/inner-or-pat.or4.stderr
new file mode 100644
index 00000000000..058873ff5ff
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat.or4.stderr
@@ -0,0 +1,11 @@
+error[E0408]: variable `x` is not bound in all patterns
+  --> $DIR/inner-or-pat.rs:53:37
+   |
+LL |         (x @ "red" | (x @ "blue" |  "red")) => {
+   |                       -             ^^^^^ pattern doesn't bind `x`
+   |                       |
+   |                       variable not in all patterns
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0408`.
diff --git a/src/test/ui/or-patterns/inner-or-pat.rs b/src/test/ui/or-patterns/inner-or-pat.rs
new file mode 100644
index 00000000000..f4cf4b0c188
--- /dev/null
+++ b/src/test/ui/or-patterns/inner-or-pat.rs
@@ -0,0 +1,73 @@
+// revisions: or1 or2 or3 or4 or5
+// [or1] run-pass
+// [or2] run-pass
+// [or5] run-pass
+
+#![allow(unreachable_patterns)]
+#![allow(unused_variables)]
+#![allow(unused_parens)]
+#![allow(dead_code)]
+
+
+
+fn foo() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | "no" | "nop") | ("hey" | "gg")) |
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}
+
+fn bar() {
+    let x = "foo";
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" | x @ "red")) => {
+        }
+        _ => (),
+    }
+}
+
+#[cfg(or3)]
+fn zot() {
+    let x = "foo";
+    match x {
+        x @ ((("h" | "ho" | "yo" | ("dude" | "w")) | () | "nop") | ("hey" | "gg")) |
+        //[or3]~^ ERROR mismatched types
+        x @ ("black" | "pink") |
+        x @ ("red" | "blue") => {
+        }
+        _ => (),
+    }
+}
+
+
+#[cfg(or4)]
+fn hey() {
+    let x = "foo";
+    match x {
+        x @ ("foo" | "bar") |
+        (x @ "red" | (x @ "blue" |  "red")) => {
+        //[or4]~^ variable `x` is not bound in all patterns
+        }
+        _ => (),
+    }
+}
+
+fn don() {
+    enum Foo {
+        A,
+        B,
+        C,
+    }
+
+    match Foo::A {
+        | _foo @ (Foo::A | Foo::B) => {}
+        Foo::C => {}
+    };
+}
+
+fn main(){}
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
index 6f9a631b092..dda5c0bb59d 100644
--- a/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.rs
@@ -7,7 +7,7 @@ fn main() {}
 
 // Test the `pat` macro fragment parser:
 macro_rules! accept_pat {
-    ($p:pat) => {}
+    ($p:pat) => {};
 }
 
 accept_pat!((p | q));
@@ -21,28 +21,28 @@ accept_pat!([p | q]);
 #[cfg(FALSE)]
 fn or_patterns() {
     // Top level of `let`:
-    let (| A | B);
+    let (A | B);
     let (A | B);
     let (A | B): u8;
     let (A | B) = 0;
     let (A | B): u8 = 0;
 
     // Top level of `for`:
-    for | A | B in 0 {}
+    for A | B in 0 {}
     for A | B in 0 {}
 
     // Top level of `while`:
-    while let | A | B = 0 {}
+    while let A | B = 0 {}
     while let A | B = 0 {}
 
     // Top level of `if`:
-    if let | A | B = 0 {}
+    if let A | B = 0 {}
     if let A | B = 0 {}
 
     // Top level of `match` arms:
     match 0 {
-        | A | B => {},
-        A | B => {},
+        A | B => {}
+        A | B => {}
     }
 
     // Functions:
@@ -68,6 +68,8 @@ fn or_patterns() {
 
     // These bind as `(prefix p) | q` as opposed to `prefix (p | q)`:
     let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
+                     //~^ WARN box pattern syntax is experimental
+                     //~| WARN unstable syntax
     let (&0 | 1);
     let (&mut 0 | 1);
     let (x @ 0 | 1);
diff --git a/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
new file mode 100644
index 00000000000..c43fe192a73
--- /dev/null
+++ b/src/test/ui/or-patterns/or-patterns-syntactic-pass.stderr
@@ -0,0 +1,13 @@
+warning: box pattern syntax is experimental
+  --> $DIR/or-patterns-syntactic-pass.rs:70:10
+   |
+LL |     let (box 0 | 1); // Unstable; we *can* change the precedence if we want.
+   |          ^^^^^
+   |
+   = note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
+   = help: add `#![feature(box_patterns)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 1 warning emitted
+
diff --git a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs
index afbd13e6fd9..d8346653c25 100644
--- a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs
+++ b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.rs
@@ -3,7 +3,11 @@
 #[cfg(FALSE)]
 fn syntax() {
     foo::<T = u8, T: Ord, String>();
+    //~^ WARN associated type bounds are unstable
+    //~| WARN unstable syntax
     foo::<T = u8, 'a, T: Ord>();
+    //~^ WARN associated type bounds are unstable
+    //~| WARN unstable syntax
 }
 
 fn main() {}
diff --git a/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr
new file mode 100644
index 00000000000..7e843c7f4d0
--- /dev/null
+++ b/src/test/ui/parser/constraints-before-generic-args-syntactic-pass.stderr
@@ -0,0 +1,24 @@
+warning: associated type bounds are unstable
+  --> $DIR/constraints-before-generic-args-syntactic-pass.rs:5:19
+   |
+LL |     foo::<T = u8, T: Ord, String>();
+   |                   ^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: associated type bounds are unstable
+  --> $DIR/constraints-before-generic-args-syntactic-pass.rs:8:23
+   |
+LL |     foo::<T = u8, 'a, T: Ord>();
+   |                       ^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/parser/fn-defined-using-def.rs b/src/test/ui/parser/fn-defined-using-def.rs
new file mode 100644
index 00000000000..21da34c47c9
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-def.rs
@@ -0,0 +1,10 @@
+// Check what happens when `def` is used to define a function, instead of `fn`
+// edition:2021
+
+#![allow(dead_code)]
+
+def foo() {}
+//~^ ERROR expected one of `!` or `::`, found `foo`
+//~^^ HELP write `fn` instead of `def` to declare a function
+
+fn main() {}
diff --git a/src/test/ui/parser/fn-defined-using-def.stderr b/src/test/ui/parser/fn-defined-using-def.stderr
new file mode 100644
index 00000000000..f34329012a0
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-def.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!` or `::`, found `foo`
+  --> $DIR/fn-defined-using-def.rs:6:5
+   |
+LL | def foo() {}
+   | --- ^^^ expected one of `!` or `::`
+   | |
+   | help: write `fn` instead of `def` to declare a function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/fn-defined-using-fun.rs b/src/test/ui/parser/fn-defined-using-fun.rs
new file mode 100644
index 00000000000..4f74605043e
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-fun.rs
@@ -0,0 +1,10 @@
+// Check what happens when `fun` is used to define a function, instead of `fn`
+// edition:2021
+
+#![allow(dead_code)]
+
+fun foo() {}
+//~^ ERROR expected one of `!` or `::`, found `foo`
+//~^^ HELP write `fn` instead of `fun` to declare a function
+
+fn main() {}
diff --git a/src/test/ui/parser/fn-defined-using-fun.stderr b/src/test/ui/parser/fn-defined-using-fun.stderr
new file mode 100644
index 00000000000..2f6cfff350c
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-fun.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!` or `::`, found `foo`
+  --> $DIR/fn-defined-using-fun.rs:6:5
+   |
+LL | fun foo() {}
+   | --- ^^^ expected one of `!` or `::`
+   | |
+   | help: write `fn` instead of `fun` to declare a function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/fn-defined-using-func.rs b/src/test/ui/parser/fn-defined-using-func.rs
new file mode 100644
index 00000000000..2dce96fdce0
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-func.rs
@@ -0,0 +1,10 @@
+// Check what happens when `func` is used to define a function, instead of `fn`
+// edition:2021
+
+#![allow(dead_code)]
+
+func foo() {}
+//~^ ERROR expected one of `!` or `::`, found `foo`
+//~^^ HELP write `fn` instead of `func` to declare a function
+
+fn main() {}
diff --git a/src/test/ui/parser/fn-defined-using-func.stderr b/src/test/ui/parser/fn-defined-using-func.stderr
new file mode 100644
index 00000000000..355741e8949
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-func.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!` or `::`, found `foo`
+  --> $DIR/fn-defined-using-func.rs:6:6
+   |
+LL | func foo() {}
+   | ---- ^^^ expected one of `!` or `::`
+   | |
+   | help: write `fn` instead of `func` to declare a function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/fn-defined-using-function.rs b/src/test/ui/parser/fn-defined-using-function.rs
new file mode 100644
index 00000000000..fd8782728e2
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-function.rs
@@ -0,0 +1,10 @@
+// Check what happens when `function` is used to define a function, instead of `fn`
+// edition:2021
+
+#![allow(dead_code)]
+
+function foo() {}
+//~^ ERROR expected one of `!` or `::`, found `foo`
+//~^^ HELP write `fn` instead of `function` to declare a function
+
+fn main() {}
diff --git a/src/test/ui/parser/fn-defined-using-function.stderr b/src/test/ui/parser/fn-defined-using-function.stderr
new file mode 100644
index 00000000000..43c33a2cdd7
--- /dev/null
+++ b/src/test/ui/parser/fn-defined-using-function.stderr
@@ -0,0 +1,10 @@
+error: expected one of `!` or `::`, found `foo`
+  --> $DIR/fn-defined-using-function.rs:6:10
+   |
+LL | function foo() {}
+   | -------- ^^^ expected one of `!` or `::`
+   | |
+   | help: write `fn` instead of `function` to declare a function
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
index 85c9fe409db..a00f37ed606 100644
--- a/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
+++ b/src/test/ui/parser/issues/issue-67377-invalid-syntax-in-enum-discriminant.stderr
@@ -107,10 +107,10 @@ LL |         V = [Vec::new; { [0].len() ].len() as isize,
    |             closing delimiter possibly meant for this
 
 error[E0282]: type annotations needed
-  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:29
+  --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:15:26
    |
 LL |         V = [Vec::new; { [].len()  ].len() as isize,
-   |                             ^^^ cannot infer type for type parameter `T`
+   |                          ^^ cannot infer type for type parameter `T`
 
 error[E0282]: type annotations needed
   --> $DIR/issue-67377-invalid-syntax-in-enum-discriminant.rs:26:14
diff --git a/src/test/ui/parser/kw-in-trait-bounds.rs b/src/test/ui/parser/kw-in-trait-bounds.rs
new file mode 100644
index 00000000000..fa037e5937d
--- /dev/null
+++ b/src/test/ui/parser/kw-in-trait-bounds.rs
@@ -0,0 +1,47 @@
+// edition:2018
+
+fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+//~^ ERROR expected identifier, found keyword `fn`
+//~| ERROR expected identifier, found keyword `fn`
+//~| ERROR expected identifier, found keyword `fn`
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| ERROR cannot find trait `r#fn` in this scope
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  escape `fn` to use it as an identifier
+//~| HELP  escape `fn` to use it as an identifier
+//~| HELP  escape `fn` to use it as an identifier
+where
+G: fn(),
+    //~^ ERROR expected identifier, found keyword `fn`
+    //~| ERROR cannot find trait `r#fn` in this scope
+    //~| HELP  a trait with a similar name exists
+    //~| HELP  escape `fn` to use it as an identifier
+{}
+
+fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+//~^ ERROR expected identifier, found keyword `struct`
+//~| ERROR expected identifier, found keyword `struct`
+//~| ERROR expected identifier, found keyword `struct`
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| ERROR cannot find trait `r#struct` in this scope
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  a trait with a similar name exists
+//~| HELP  escape `struct` to use it as an identifier
+//~| HELP  escape `struct` to use it as an identifier
+//~| HELP  escape `struct` to use it as an identifier
+where
+    B: struct,
+    //~^ ERROR expected identifier, found keyword `struct`
+    //~| ERROR cannot find trait `r#struct` in this scope
+    //~| HELP  a trait with a similar name exists
+    //~| HELP  escape `struct` to use it as an identifier
+{}
+
+trait Struct {}
+
+fn main() {}
diff --git a/src/test/ui/parser/kw-in-trait-bounds.stderr b/src/test/ui/parser/kw-in-trait-bounds.stderr
new file mode 100644
index 00000000000..28196c7ce2d
--- /dev/null
+++ b/src/test/ui/parser/kw-in-trait-bounds.stderr
@@ -0,0 +1,171 @@
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:10
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: r#fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:27
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                           ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: fn(), G>(_: impl r#fn(), _: &dyn fn())
+   |                           ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:3:41
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                                         ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn r#fn())
+   |                                         ++
+
+error: expected identifier, found keyword `fn`
+  --> $DIR/kw-in-trait-bounds.rs:17:4
+   |
+LL | G: fn(),
+   |    ^^ expected identifier, found keyword
+   |
+help: escape `fn` to use it as an identifier
+   |
+LL | G: r#fn(),
+   |    ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:10
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |          ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: r#struct, B>(_: impl struct, _: &dyn struct)
+   |          ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:29
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                             ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: struct, B>(_: impl r#struct, _: &dyn struct)
+   |                             ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:24:45
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                                             ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn r#struct)
+   |                                             ++
+
+error: expected identifier, found keyword `struct`
+  --> $DIR/kw-in-trait-bounds.rs:38:8
+   |
+LL |     B: struct,
+   |        ^^^^^^ expected identifier, found keyword
+   |
+help: escape `struct` to use it as an identifier
+   |
+LL |     B: r#struct,
+   |        ++
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:10
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |          ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:17:4
+   |
+LL | G: fn(),
+   |    ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:27
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                           ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#fn` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:3:41
+   |
+LL | fn _f<F: fn(), G>(_: impl fn(), _: &dyn fn())
+   |                                         ^^ help: a trait with a similar name exists (notice the capitalization): `Fn`
+   |
+  ::: $SRC_DIR/core/src/ops/function.rs:LL:COL
+   |
+LL | pub trait Fn<Args>: FnMut<Args> {
+   | ------------------------------- similarly named trait `Fn` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:10
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |          ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:38:8
+   |
+LL |     B: struct,
+   |        ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:29
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error[E0405]: cannot find trait `r#struct` in this scope
+  --> $DIR/kw-in-trait-bounds.rs:24:45
+   |
+LL | fn _g<A: struct, B>(_: impl struct, _: &dyn struct)
+   |                                             ^^^^^^ help: a trait with a similar name exists (notice the capitalization): `Struct`
+...
+LL | trait Struct {}
+   | ------------ similarly named trait `Struct` defined here
+
+error: aborting due to 16 previous errors
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/src/test/ui/parser/struct-literal-in-for.stderr b/src/test/ui/parser/struct-literal-in-for.stderr
index 4b191710c39..1c91eba68e3 100644
--- a/src/test/ui/parser/struct-literal-in-for.stderr
+++ b/src/test/ui/parser/struct-literal-in-for.stderr
@@ -24,7 +24,7 @@ LL | |     }.hi() {
    | |__________^ `bool` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `bool`
-   = note: required because of the requirements on the impl of `IntoIterator` for `bool`
+   = note: required for `bool` to implement `IntoIterator`
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
index d96e863939c..eba65a61803 100644
--- a/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
+++ b/src/test/ui/pattern/move-ref-patterns/move-ref-patterns-closure-captures.stderr
@@ -8,7 +8,15 @@ LL |         drop::<U>(_x1);
    |                   --- closure is `FnOnce` because it moves the variable `_x1` out of its environment
 ...
 LL |     accept_fn_mut(&c1);
-   |     ------------- the requirement to implement `FnMut` derives from here
+   |     ------------- --- the requirement to implement `FnMut` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn_mut`
+  --> $DIR/move-ref-patterns-closure-captures.rs:4:31
+   |
+LL |     fn accept_fn_mut(_: &impl FnMut()) {}
+   |                               ^^^^^^^ required by this bound in `accept_fn_mut`
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnOnce`
   --> $DIR/move-ref-patterns-closure-captures.rs:9:14
@@ -20,7 +28,15 @@ LL |         drop::<U>(_x1);
    |                   --- closure is `FnOnce` because it moves the variable `_x1` out of its environment
 ...
 LL |     accept_fn(&c1);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- --- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn`
+  --> $DIR/move-ref-patterns-closure-captures.rs:5:27
+   |
+LL |     fn accept_fn(_: &impl Fn()) {}
+   |                           ^^^^ required by this bound in `accept_fn`
 
 error[E0525]: expected a closure that implements the `Fn` trait, but this closure only implements `FnMut`
   --> $DIR/move-ref-patterns-closure-captures.rs:20:14
@@ -32,7 +48,15 @@ LL |         drop::<&mut U>(_x2);
    |                        --- closure is `FnMut` because it mutates the variable `_x2` here
 ...
 LL |     accept_fn(&c2);
-   |     --------- the requirement to implement `Fn` derives from here
+   |     --------- --- the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `accept_fn`
+  --> $DIR/move-ref-patterns-closure-captures.rs:5:27
+   |
+LL |     fn accept_fn(_: &impl Fn()) {}
+   |                           ^^^^ required by this bound in `accept_fn`
 
 error: aborting due to 3 previous errors
 
diff --git a/src/test/ui/pattern/rest-pat-syntactic.rs b/src/test/ui/pattern/rest-pat-syntactic.rs
index 9656a0b5de9..4da5a2db767 100644
--- a/src/test/ui/pattern/rest-pat-syntactic.rs
+++ b/src/test/ui/pattern/rest-pat-syntactic.rs
@@ -19,6 +19,8 @@ fn rest_patterns() {
 
     // Box patterns:
     let box ..;
+    //~^ WARN box pattern syntax is experimental
+    //~| WARN unstable syntax
 
     // In or-patterns:
     match x {
@@ -57,7 +59,7 @@ fn rest_patterns() {
         .. |
         [
             (
-                box ..,
+                box .., //~ WARN box pattern syntax is experimental
                 &(..),
                 &mut ..,
                 x @ ..
@@ -67,4 +69,5 @@ fn rest_patterns() {
         ref mut x @ ..
         => {}
     }
+    //~| WARN unstable syntax
 }
diff --git a/src/test/ui/pattern/rest-pat-syntactic.stderr b/src/test/ui/pattern/rest-pat-syntactic.stderr
new file mode 100644
index 00000000000..37019b7d5ba
--- /dev/null
+++ b/src/test/ui/pattern/rest-pat-syntactic.stderr
@@ -0,0 +1,24 @@
+warning: box pattern syntax is experimental
+  --> $DIR/rest-pat-syntactic.rs:21:9
+   |
+LL |     let box ..;
+   |         ^^^^^^
+   |
+   = note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
+   = help: add `#![feature(box_patterns)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: box pattern syntax is experimental
+  --> $DIR/rest-pat-syntactic.rs:62:17
+   |
+LL |                 box ..,
+   |                 ^^^^^^
+   |
+   = note: see issue #29641 <https://github.com/rust-lang/rust/issues/29641> for more information
+   = help: add `#![feature(box_patterns)]` to the crate attributes to enable
+   = warning: unstable syntax can change at any point in the future, causing a hard error!
+   = note: for more information, see issue #65860 <https://github.com/rust-lang/rust/issues/65860>
+
+warning: 2 warnings emitted
+
diff --git a/src/test/ui/phantom-auto-trait.stderr b/src/test/ui/phantom-auto-trait.stderr
index 1cc653c51cf..015c8fa4cd1 100644
--- a/src/test/ui/phantom-auto-trait.stderr
+++ b/src/test/ui/phantom-auto-trait.stderr
@@ -6,7 +6,7 @@ LL |     is_zen(x)
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Zen` for `&T`
+note: required for `&T` to implement `Zen`
   --> $DIR/phantom-auto-trait.rs:10:24
    |
 LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
@@ -35,7 +35,7 @@ LL |     is_zen(x)
    |     |
    |     required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Zen` for `&T`
+note: required for `&T` to implement `Zen`
   --> $DIR/phantom-auto-trait.rs:10:24
    |
 LL | unsafe impl<'a, T: 'a> Zen for &'a T where T: Sync {}
diff --git a/src/test/ui/proc-macro/signature.stderr b/src/test/ui/proc-macro/signature.stderr
index a6bd98ddb19..78b0beff0da 100644
--- a/src/test/ui/proc-macro/signature.stderr
+++ b/src/test/ui/proc-macro/signature.stderr
@@ -5,7 +5,10 @@ LL | / pub unsafe extern "C" fn foo(a: i32, b: u32) -> u32 {
 LL | |
 LL | |     loop {}
 LL | | }
-   | |_^ call the function in a closure: `|| unsafe { /* code */ }`
+   | | ^
+   | | |
+   | |_call the function in a closure: `|| unsafe { /* code */ }`
+   |   required by a bound introduced by this call
    |
    = help: the trait `Fn<(proc_macro::TokenStream,)>` is not implemented for `unsafe extern "C" fn(i32, u32) -> u32 {foo}`
    = note: unsafe function cannot be called generically without an unsafe block
diff --git a/src/test/ui/range/range-1.stderr b/src/test/ui/range/range-1.stderr
index 0bbed870424..aaea91ce0cb 100644
--- a/src/test/ui/range/range-1.stderr
+++ b/src/test/ui/range/range-1.stderr
@@ -20,14 +20,14 @@ LL |     for i in false..true {}
              isize
              u128
            and 5 others
-   = note: required because of the requirements on the impl of `Iterator` for `std::ops::Range<bool>`
-   = note: required because of the requirements on the impl of `IntoIterator` for `std::ops::Range<bool>`
+   = note: required for `std::ops::Range<bool>` to implement `Iterator`
+   = note: required for `std::ops::Range<bool>` to implement `IntoIterator`
 
 error[E0277]: the size for values of type `[{integer}]` cannot be known at compilation time
   --> $DIR/range-1.rs:14:17
    |
 LL |     let range = *arr..;
-   |                 ^^^^^^ doesn't have a size known at compile-time
+   |                 ^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[{integer}]`
 note: required by a bound in `RangeFrom`
diff --git a/src/test/ui/recursion/issue-83150.stderr b/src/test/ui/recursion/issue-83150.stderr
index 89a83298471..32f25faf3e8 100644
--- a/src/test/ui/recursion/issue-83150.stderr
+++ b/src/test/ui/recursion/issue-83150.stderr
@@ -9,10 +9,12 @@ LL |     func(&mut iter.map(|x| x + 1))
    = note: `#[warn(unconditional_recursion)]` on by default
    = help: a `loop` may express intention better if this is on purpose
 
-error[E0275]: overflow evaluating the requirement `Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>: Iterator`
+error[E0275]: overflow evaluating the requirement `<std::ops::Range<u8> as Iterator>::Item`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required because of the requirements on the impl of `Iterator` for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>`
+   = note: required for `Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
+   = note: 64 redundant requirements hidden
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>, [closure@$DIR/issue-83150.rs:11:24: 11:27]>` to implement `Iterator`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/recursion/issue-95134.rs b/src/test/ui/recursion/issue-95134.rs
new file mode 100644
index 00000000000..adc9c6ee2d9
--- /dev/null
+++ b/src/test/ui/recursion/issue-95134.rs
@@ -0,0 +1,28 @@
+// build-fail
+// compile-flags: -Copt-level=0
+//~^^ ERROR overflow evaluating the requirement
+
+pub fn encode_num<Writer: ExampleWriter>(n: u32, mut writer: Writer) -> Result<(), Writer::Error> {
+    if n > 15 {
+        encode_num(n / 16, &mut writer)?;
+    }
+    Ok(())
+}
+
+pub trait ExampleWriter {
+    type Error;
+}
+
+impl<'a, T: ExampleWriter> ExampleWriter for &'a mut T {
+    type Error = T::Error;
+}
+
+struct EmptyWriter;
+
+impl ExampleWriter for EmptyWriter {
+    type Error = ();
+}
+
+fn main() {
+    encode_num(69, &mut EmptyWriter).unwrap();
+}
diff --git a/src/test/ui/recursion/issue-95134.stderr b/src/test/ui/recursion/issue-95134.stderr
new file mode 100644
index 00000000000..57a498694b7
--- /dev/null
+++ b/src/test/ui/recursion/issue-95134.stderr
@@ -0,0 +1,7 @@
+error[E0275]: overflow evaluating the requirement `<EmptyWriter as ExampleWriter>::Error`
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_95134`)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/src/test/ui/regions/outlives-with-missing.rs b/src/test/ui/regions/outlives-with-missing.rs
new file mode 100644
index 00000000000..29d89718b58
--- /dev/null
+++ b/src/test/ui/regions/outlives-with-missing.rs
@@ -0,0 +1,16 @@
+trait HandlerFamily {
+    type Target;
+}
+
+struct HandlerWrapper<H: HandlerFamily>(H);
+
+impl<H: HandlerFamily> HandlerWrapper<H> {
+    pub fn set_handler(&self, handler: &H::Target)
+    where
+        T: Send + Sync + 'static,
+        //~^ ERROR cannot find type `T` in this scope
+    {
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/regions/outlives-with-missing.stderr b/src/test/ui/regions/outlives-with-missing.stderr
new file mode 100644
index 00000000000..e204c918724
--- /dev/null
+++ b/src/test/ui/regions/outlives-with-missing.stderr
@@ -0,0 +1,12 @@
+error[E0412]: cannot find type `T` in this scope
+  --> $DIR/outlives-with-missing.rs:10:9
+   |
+LL | impl<H: HandlerFamily> HandlerWrapper<H> {
+   |      - similarly named type parameter `H` defined here
+...
+LL |         T: Send + Sync + 'static,
+   |         ^ help: a type parameter with a similar name exists: `H`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
index c1dab6086ef..1106352037a 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.rs
@@ -19,7 +19,8 @@ trait Trait2<'a, 'b> {
 // since for it to be WF, we would need to know that `'y: 'x`, but we
 // do not infer that.
 fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
-    //~^ the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+    //~^ ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+    //~| ERROR the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
 {
 }
 
diff --git a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
index 6844e866532..66f592c34dd 100644
--- a/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
+++ b/src/test/ui/regions/regions-implied-bounds-projection-gap-hr-1.stderr
@@ -1,4 +1,19 @@
 error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
+  --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:1
+   |
+LL | / fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+LL | |
+LL | |
+LL | | {
+LL | | }
+   | |_^ the trait `for<'z> Trait2<'y, 'z>` is not implemented for `T`
+   |
+help: consider restricting type parameter `T`
+   |
+LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
+   |                    ++++++++++++++++++++++++
+
+error[E0277]: the trait bound `for<'z> T: Trait2<'y, 'z>` is not satisfied
   --> $DIR/regions-implied-bounds-projection-gap-hr-1.rs:21:49
    |
 LL | fn callee<'x, 'y, T>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
@@ -9,6 +24,6 @@ help: consider restricting type parameter `T`
 LL | fn callee<'x, 'y, T: for<'z> Trait2<'y, 'z>>(t: &'x dyn for<'z> Trait1< <T as Trait2<'y, 'z>>::Foo >)
    |                    ++++++++++++++++++++++++
 
-error: aborting due to previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.rs b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.rs
new file mode 100644
index 00000000000..bd496875e80
--- /dev/null
+++ b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.rs
@@ -0,0 +1,21 @@
+trait Foo<T> {
+    fn foo(&self, name: T) -> usize;
+}
+
+struct Bar {
+    baz: Baz,
+}
+
+struct Baz {
+    num: usize,
+}
+
+impl<Baz> Foo<Baz> for Bar {
+    fn foo(&self, _name: Baz) -> usize {
+        match self.baz {
+            Baz { num } => num, //~ ERROR expected struct, variant or union type, found type parameter `Baz`
+        }
+    }
+}
+
+fn main() {}
diff --git a/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
new file mode 100644
index 00000000000..d9c404e94ac
--- /dev/null
+++ b/src/test/ui/resolve/point-at-type-parameter-shadowing-another-type.stderr
@@ -0,0 +1,12 @@
+error[E0574]: expected struct, variant or union type, found type parameter `Baz`
+  --> $DIR/point-at-type-parameter-shadowing-another-type.rs:16:13
+   |
+LL | impl<Baz> Foo<Baz> for Bar {
+   |      --- found this type pararmeter
+...
+LL |             Baz { num } => num,
+   |             ^^^ not a struct, variant or union type
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0574`.
diff --git a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index 6086723b5c4..7d81de43854 100644
--- a/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/src/test/ui/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -9,7 +9,7 @@ LL | | }
    | |_^ `main` can only return types that implement `Termination`
    |
    = help: the trait `Termination` is not implemented for `f32`
-   = note: required because of the requirements on the impl of `Termination` for `Result<f32, ParseFloatError>`
+   = note: required for `Result<f32, ParseFloatError>` to implement `Termination`
 note: required by a bound in `assert_test_result`
   --> $SRC_DIR/test/src/lib.rs:LL:COL
    |
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index ec724cc9675..fddc8d37f2f 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satisfied
-  --> $DIR/const-default-method-bodies.rs:24:18
+  --> $DIR/const-default-method-bodies.rs:24:5
    |
 LL |     NonConstImpl.a();
-   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
+   |     ^^^^^^^^^^^^ - required by a bound introduced by this call
+   |     |
+   |     the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
 note: the trait `ConstDefaultFn` is implemented for `NonConstImpl`, but that implementation is not `const`
-  --> $DIR/const-default-method-bodies.rs:24:18
+  --> $DIR/const-default-method-bodies.rs:24:5
    |
 LL |     NonConstImpl.a();
-   |                  ^
+   |     ^^^^^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn test() where NonConstImpl: ~const ConstDefaultFn {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
index 9dbaffd4c15..2295a822fa4 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.precise.stderr
@@ -5,7 +5,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     NonTrivialDrop,
-   |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
@@ -52,15 +52,15 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
-note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
   --> $DIR/const-drop-fail.rs:28:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+   = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
 note: required by a bound in `check`
   --> $DIR/const-drop-fail.rs:34:19
    |
diff --git a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
index 9dbaffd4c15..2295a822fa4 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/const-drop-fail.stock.stderr
@@ -5,7 +5,7 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     NonTrivialDrop,
-   |     ^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `NonTrivialDrop`
    |
    = note: the trait bound `NonTrivialDrop: ~const Destruct` is not satisfied
 note: required by a bound in `check`
@@ -52,15 +52,15 @@ LL |         const _: () = check($exp);
    |                       ----- required by a bound introduced by this call
 ...
 LL |     ConstDropImplWithBounds::<NonTrivialDrop>(PhantomData),
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an implementor of trait `~const Destruct`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `ConstDropImplWithBounds<NonTrivialDrop>`
    |
-note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
   --> $DIR/const-drop-fail.rs:28:25
    |
 LL | impl<T: ~const A> const Drop for ConstDropImplWithBounds<T> {
    |                         ^^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `~const Destruct` for `ConstDropImplWithBounds<NonTrivialDrop>`
+   = note: required for `ConstDropImplWithBounds<NonTrivialDrop>` to implement `~const Destruct`
 note: required by a bound in `check`
   --> $DIR/const-drop-fail.rs:34:19
    |
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index 174c62912fc..d4fa44b4bfc 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |     ^^^^^^^^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^
+   |     ^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
index 4619dd1138e..71ecd9b0694 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/cross-crate.stocknc.stderr
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `cross_crate::NonConst: cross_crate::MyTrait` is not satisfied
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |     ^^^^^^^^ ---- required by a bound introduced by this call
+   |     |
+   |     the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
 note: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`, but that implementation is not `const`
-  --> $DIR/cross-crate.rs:17:14
+  --> $DIR/cross-crate.rs:17:5
    |
 LL |     NonConst.func();
-   |              ^^^^
+   |     ^^^^^^^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | const fn const_context() where cross_crate::NonConst: ~const cross_crate::MyTrait {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index b229053eb50..85285ba8497 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -1,14 +1,16 @@
 error[E0277]: the trait bound `(): ~const Tr` is not satisfied
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
    |
 LL |         ().a()
-   |            ^ the trait `~const Tr` is not implemented for `()`
+   |         ^^ - required by a bound introduced by this call
+   |         |
+   |         the trait `~const Tr` is not implemented for `()`
    |
 note: the trait `Tr` is implemented for `()`, but that implementation is not `const`
-  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
+  --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:9
    |
 LL |         ().a()
-   |            ^
+   |         ^^
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | pub trait Tr where (): ~const Tr {
diff --git a/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
new file mode 100644
index 00000000000..1004bb28c59
--- /dev/null
+++ b/src/test/ui/rfc-2632-const-trait-impl/issue-100222.rs
@@ -0,0 +1,29 @@
+// revisions: nn ny yn yy
+// check-pass
+#![feature(const_trait_impl, associated_type_defaults, const_mut_refs)]
+
+#[cfg_attr(any(yn, yy), const_trait)]
+pub trait Index {
+    type Output;
+}
+
+#[cfg_attr(any(ny, yy), const_trait)]
+pub trait IndexMut where Self: Index {
+    const C: <Self as Index>::Output;
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output;
+}
+
+impl Index for () { type Output = (); }
+
+impl const IndexMut for <() as Index>::Output {
+    const C: <Self as Index>::Output = ();
+    type Assoc = <Self as Index>::Output;
+    fn foo(&mut self, x: <Self as Index>::Output) -> <Self as Index>::Output
+        where <Self as Index>::Output:,
+    {}
+}
+
+const C: <() as Index>::Output = ();
+
+fn main() {}
diff --git a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
index d5b2d269730..fd5fe25ddcf 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/trait-where-clause.stderr
@@ -20,16 +20,16 @@ LL | const fn test1<T: ~const Foo + Bar + ~const Bar>() {
    |                                    ++++++++++++
 
 error[E0277]: the trait bound `T: ~const Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:15:5
+  --> $DIR/trait-where-clause.rs:15:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^ the trait `~const Bar` is not implemented for `T`
+   |            ^ the trait `~const Bar` is not implemented for `T`
    |
 note: the trait `Bar` is implemented for `T`, but that implementation is not `const`
-  --> $DIR/trait-where-clause.rs:15:5
+  --> $DIR/trait-where-clause.rs:15:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^
+   |            ^
 note: required by a bound in `Foo::c`
   --> $DIR/trait-where-clause.rs:8:13
    |
@@ -57,10 +57,10 @@ LL | fn test3<T: Foo + Bar>() {
    |                 +++++
 
 error[E0277]: the trait bound `T: Bar` is not satisfied
-  --> $DIR/trait-where-clause.rs:29:5
+  --> $DIR/trait-where-clause.rs:29:12
    |
 LL |     T::c::<T>();
-   |     ^^^^^^^^^ the trait `Bar` is not implemented for `T`
+   |            ^ the trait `Bar` is not implemented for `T`
    |
 note: required by a bound in `Foo::c`
   --> $DIR/trait-where-clause.rs:8:13
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
index e8b26154549..d63381b5f2c 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
+++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.rs
@@ -3,4 +3,4 @@
 #![feature(const_trait_impl)]
 
 struct S<T: const Tr>;
-//~^ ERROR expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path
+//~^ ERROR const bounds must start with `~`
diff --git a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
index b6b77ac4a2f..31300354a57 100644
--- a/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
+++ b/src/test/ui/rfc-2632-const-trait-impl/without-tilde.stderr
@@ -1,8 +1,10 @@
-error: expected one of `!`, `(`, `,`, `=`, `>`, `?`, `for`, `~`, lifetime, or path, found keyword `const`
+error: const bounds must start with `~`
   --> $DIR/without-tilde.rs:5:13
    |
 LL | struct S<T: const Tr>;
-   |             ^^^^^ expected one of 10 possible tokens
+   |             -^^^^
+   |             |
+   |             help: add `~`: `~`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
index 35a65facb57..0ec0d4be5f2 100644
--- a/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.curr.stderr
@@ -31,7 +31,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
-   = note: required because of the requirements on the impl of `CoerceUnsized<Rc<dyn Foo>>` for `Rc<usize>`
+   = note: required for `Rc<usize>` to implement `CoerceUnsized<Rc<dyn Foo>>`
    = note: required by cast to type `Rc<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
index a74752cf840..b494b448e2e 100644
--- a/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
+++ b/src/test/ui/self/arbitrary-self-types-not-object-safe.object_safe_for_dispatch.stderr
@@ -14,7 +14,7 @@ LL | trait Foo {
    |       --- this trait cannot be made into an object...
 LL |     fn foo(self: &Rc<Self>) -> usize;
    |                  ^^^^^^^^^ ...because method `foo`'s `self` parameter cannot be dispatched on
-   = note: required because of the requirements on the impl of `CoerceUnsized<Rc<dyn Foo>>` for `Rc<usize>`
+   = note: required for `Rc<usize>` to implement `CoerceUnsized<Rc<dyn Foo>>`
    = note: required by cast to type `Rc<dyn Foo>`
 
 error: aborting due to previous error
diff --git a/src/test/ui/span/issue-35987.stderr b/src/test/ui/span/issue-35987.stderr
index 2bc3ff4c3b6..ea9c4c82c36 100644
--- a/src/test/ui/span/issue-35987.stderr
+++ b/src/test/ui/span/issue-35987.stderr
@@ -2,7 +2,9 @@ error[E0404]: expected trait, found type parameter `Add`
   --> $DIR/issue-35987.rs:5:21
    |
 LL | impl<T: Clone, Add> Add for Foo<T> {
-   |                     ^^^ not a trait
+   |                ---  ^^^ not a trait
+   |                |
+   |                found this type pararmeter
    |
 help: consider importing this trait instead
    |
diff --git a/src/test/ui/span/lint-unused-unsafe-thir.rs b/src/test/ui/span/lint-unused-unsafe-thir.rs
index 95a537ed282..adb72c26bba 100644
--- a/src/test/ui/span/lint-unused-unsafe-thir.rs
+++ b/src/test/ui/span/lint-unused-unsafe-thir.rs
@@ -22,7 +22,7 @@ fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
 fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
 unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
 fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad5() { unsafe { unsf() } }
 fn bad6() {
     unsafe {                             // don't put the warning here
         unsafe {                         //~ ERROR: unnecessary `unsafe` block
@@ -31,7 +31,7 @@ fn bad6() {
     }
 }
 unsafe fn bad7() {
-    unsafe {                             //~ ERROR: unnecessary `unsafe` block
+    unsafe {
         unsafe {                         //~ ERROR: unnecessary `unsafe` block
             unsf()
         }
diff --git a/src/test/ui/span/lint-unused-unsafe-thir.stderr b/src/test/ui/span/lint-unused-unsafe-thir.stderr
index 6654910c5cd..3bcbb759775 100644
--- a/src/test/ui/span/lint-unused-unsafe-thir.stderr
+++ b/src/test/ui/span/lint-unused-unsafe-thir.stderr
@@ -31,14 +31,6 @@ LL | fn bad4() { unsafe { callback(||{}) } }
    |             ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe-thir.rs:25:20
-   |
-LL | unsafe fn bad5() { unsafe { unsf() } }
-   | ----------------   ^^^^^^ unnecessary `unsafe` block
-   | |
-   | because it's nested under this `unsafe` fn
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe-thir.rs:28:9
    |
 LL |     unsafe {                             // don't put the warning here
@@ -54,13 +46,5 @@ LL |     unsafe {
 LL |         unsafe {
    |         ^^^^^^ unnecessary `unsafe` block
 
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe-thir.rs:34:5
-   |
-LL | unsafe fn bad7() {
-   | ---------------- because it's nested under this `unsafe` fn
-LL |     unsafe {
-   |     ^^^^^^ unnecessary `unsafe` block
-
-error: aborting due to 8 previous errors
+error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/span/lint-unused-unsafe.mir.stderr b/src/test/ui/span/lint-unused-unsafe.mir.stderr
index 850550a1d8f..d8412908c73 100644
--- a/src/test/ui/span/lint-unused-unsafe.mir.stderr
+++ b/src/test/ui/span/lint-unused-unsafe.mir.stderr
@@ -29,17 +29,6 @@ LL | fn bad4() { unsafe { callback(||{}) } }
    |             ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:30:20
-   |
-LL | unsafe fn bad5() { unsafe { unsf() } }
-   | ----------------   ^^^^^^ unnecessary `unsafe` block
-   | |
-   | because it's nested under this `unsafe` fn
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-   = note: `#[allow(unsafe_op_in_unsafe_fn)]` on by default
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:32:5
    |
 LL |     unsafe {
@@ -52,17 +41,6 @@ LL |     unsafe {
    |     ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:40:9
-   |
-LL | unsafe fn bad7() {
-   | ---------------- because it's nested under this `unsafe` fn
-LL |     unsafe {
-LL |         unsafe {
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:74:9
    |
 LL |         unsafe {
@@ -273,90 +251,31 @@ LL |         unsafe {
    |         ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:197:13
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-LL |         unsafe {
-LL |             unsafe { unsf() }
-   |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:194:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:198:13
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             unsafe { unsf() }
-   |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:199:13
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             unsafe { unsf() }
-   |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:205:9
-   |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-LL |         unsafe {
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:203:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:207:13
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-...
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsf();
 LL |             unsafe { unsf() }
    |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:208:13
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
 ...
 LL |             unsafe { unsf() }
    |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:209:13
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         unsafe {
+   |         ------ because it's nested under this `unsafe` block
 ...
 LL |             unsafe { unsf() }
    |             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:220:17
@@ -398,19 +317,12 @@ LL |         unsafe {
    |         ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:254:9
+  --> $DIR/lint-unused-unsafe.rs:255:13
    |
-LL |     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-   |     ----------------------------------------------- because it's nested under this `unsafe` fn
 LL |         unsafe {
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:252:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |         ------ because it's nested under this `unsafe` block
+LL |             unsafe {
+   |             ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:268:13
@@ -631,90 +543,31 @@ LL |         let _ = || unsafe {
    |                    ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:409:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-LL |         let _ = || unsafe {
-LL |             let _ = || unsafe { unsf() };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:406:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:410:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             let _ = || unsafe { unsf() };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:411:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             let _ = || unsafe { unsf() };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:417:20
-   |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-LL |         let _ = || unsafe {
-   |                    ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:415:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:419:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-...
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             unsf();
 LL |             let _ = || unsafe { unsf() };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:420:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
 ...
 LL |             let _ = || unsafe { unsf() };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:421:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
 ...
 LL |             let _ = || unsafe { unsf() };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:432:28
@@ -756,19 +609,12 @@ LL |         let _ = || unsafe {
    |                    ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:466:20
+  --> $DIR/lint-unused-unsafe.rs:467:24
    |
-LL |     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-   |     ----------------------------------------------- because it's nested under this `unsafe` fn
 LL |         let _ = || unsafe {
-   |                    ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:464:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:480:24
@@ -989,90 +835,31 @@ LL |         let _ = || unsafe {
    |                    ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:622:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-LL |         let _ = || unsafe {
-LL |             let _ = || unsafe { let _ = || unsf(); };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:619:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:623:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             let _ = || unsafe { let _ = || unsf(); };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:624:24
-   |
-LL |     unsafe fn granularity_2() {
-   |     ------------------------- because it's nested under this `unsafe` fn
-...
-LL |             let _ = || unsafe { let _ = || unsf(); };
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:630:20
-   |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-LL |         let _ = || unsafe {
-   |                    ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:628:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:632:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
-...
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsf();
 LL |             let _ = || unsafe { let _ = || unsf(); };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:633:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
 ...
 LL |             let _ = || unsafe { let _ = || unsf(); };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:634:24
    |
-LL |     unsafe fn top_level_used_2() {
-   |     ---------------------------- because it's nested under this `unsafe` fn
+LL |         let _ = || unsafe {
+   |                    ------ because it's nested under this `unsafe` block
 ...
 LL |             let _ = || unsafe { let _ = || unsf(); };
    |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:645:28
@@ -1114,19 +901,12 @@ LL |         let _ = || unsafe {
    |                    ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:679:20
+  --> $DIR/lint-unused-unsafe.rs:680:24
    |
-LL |     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-   |     ----------------------------------------------- because it's nested under this `unsafe` fn
 LL |         let _ = || unsafe {
-   |                    ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:677:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
+   |                    ------ because it's nested under this `unsafe` block
+LL |             let _ = || unsafe {
+   |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:693:24
@@ -1257,90 +1037,31 @@ LL |             let _ = || unsafe {
    |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:784:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-LL |             let _ = || unsafe {
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:781:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:785:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-...
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:786:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-...
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:792:24
-   |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
-LL |             let _ = || unsafe {
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:790:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:794:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
-...
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:795:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:796:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:807:32
@@ -1382,19 +1103,12 @@ LL |             let _ = || unsafe {
    |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:841:24
+  --> $DIR/lint-unused-unsafe.rs:842:28
    |
-LL |         unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-   |         ----------------------------------------------- because it's nested under this `unsafe` fn
 LL |             let _ = || unsafe {
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:839:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:855:28
@@ -1525,90 +1239,31 @@ LL |             let _ = || unsafe {
    |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:942:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-LL |             let _ = || unsafe {
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:939:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:943:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-...
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:944:28
-   |
-LL |         unsafe fn granularity_2() {
-   |         ------------------------- because it's nested under this `unsafe` fn
-...
-LL |                 let _ = || unsafe { unsf() };
-   |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:950:24
-   |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
-LL |             let _ = || unsafe {
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:948:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:952:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
-...
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 unsf();
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:953:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:954:28
    |
-LL |         unsafe fn top_level_used_2() {
-   |         ---------------------------- because it's nested under this `unsafe` fn
+LL |             let _ = || unsafe {
+   |                        ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = || unsafe { unsf() };
    |                            ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:965:32
@@ -1650,19 +1305,12 @@ LL |             let _ = || unsafe {
    |                        ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:999:24
+  --> $DIR/lint-unused-unsafe.rs:1000:28
    |
-LL |         unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-   |         ----------------------------------------------- because it's nested under this `unsafe` fn
 LL |             let _ = || unsafe {
-   |                        ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:997:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
+   |                        ------ because it's nested under this `unsafe` block
+LL |                 let _ = || unsafe {
+   |                            ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1013:28
@@ -1673,21 +1321,6 @@ LL |                 let _ = || unsafe {
    |                            ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:1044:9
-   |
-LL |     unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() {
-   |     -------------------------------------------------- because it's nested under this `unsafe` fn
-LL |         unsafe {
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:1045:21
-   |
-LL |             #[allow(unsafe_op_in_unsafe_fn)]
-   |                     ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1059:29
    |
 LL |             let _ = async { unsafe {
@@ -1727,86 +1360,31 @@ LL |             let _ = async { unsafe {
    |                             ^^^^^^ unnecessary `unsafe` block
 
 error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:1074:33
-   |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
-   |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/lint-unused-unsafe.rs:1071:17
-   |
-LL |         #[allow(unsafe_op_in_unsafe_fn)]
-   |                 ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:1075:33
-   |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
-   |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:1076:33
-   |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
-   |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
-  --> $DIR/lint-unused-unsafe.rs:1078:29
-   |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |             let _ = async { unsafe {
-   |                             ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-
-error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1080:33
    |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
-...
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
+LL |                 let _ = async { unsf() };
 LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
    |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1081:33
    |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
    |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1082:33
    |
-LL |     async unsafe fn async_blocks() {
-   |     ------------------------------ because it's nested under this `unsafe` fn
+LL |             let _ = async { unsafe {
+   |                             ------ because it's nested under this `unsafe` block
 ...
 LL |                 let _ = async { unsafe { let _ = async { unsf() }; }};
    |                                 ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
 
 error: unnecessary `unsafe` block
   --> $DIR/lint-unused-unsafe.rs:1092:22
@@ -1820,5 +1398,5 @@ error: unnecessary `unsafe` block
 LL |         let _x: [(); unsafe { unsafe { size() } }] = [];
    |                      ^^^^^^ unnecessary `unsafe` block
 
-error: aborting due to 201 previous errors
+error: aborting due to 174 previous errors
 
diff --git a/src/test/ui/span/lint-unused-unsafe.rs b/src/test/ui/span/lint-unused-unsafe.rs
index f8d1dff3572..5d042768be0 100644
--- a/src/test/ui/span/lint-unused-unsafe.rs
+++ b/src/test/ui/span/lint-unused-unsafe.rs
@@ -27,7 +27,7 @@ fn bad1() { unsafe {} }                  //~ ERROR: unnecessary `unsafe` block
 fn bad2() { unsafe { bad1() } }          //~ ERROR: unnecessary `unsafe` block
 unsafe fn bad3() { unsafe {} }           //~ ERROR: unnecessary `unsafe` block
 fn bad4() { unsafe { callback(||{}) } }  //~ ERROR: unnecessary `unsafe` block
-unsafe fn bad5() { unsafe { unsf() } }   //~ ERROR: unnecessary `unsafe` block
+unsafe fn bad5() { unsafe { unsf() } }
 fn bad6() {
     unsafe {                             //~ ERROR: unnecessary `unsafe` block
         unsafe {                         // don't put the warning here
@@ -37,7 +37,7 @@ fn bad6() {
 }
 unsafe fn bad7() {
     unsafe {                             //~ ERROR: unnecessary `unsafe` block
-        unsafe {                         //~ ERROR: unnecessary `unsafe` block
+        unsafe {
             unsf()
         }
     }
@@ -194,15 +194,15 @@ mod additional_tests {
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granularity_2() {
         unsafe { //~ ERROR: unnecessary `unsafe` block
-            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
-            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
-            unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
+            unsafe { unsf() }
+            unsafe { unsf() }
+            unsafe { unsf() }
         }
     }
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn top_level_used_2() {
-        unsafe { //~ ERROR: unnecessary `unsafe` block
+        unsafe {
             unsf();
             unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
             unsafe { unsf() } //~ ERROR: unnecessary `unsafe` block
@@ -251,8 +251,8 @@ mod additional_tests {
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-        unsafe { //~ ERROR: unnecessary `unsafe` block
-            unsafe {
+        unsafe {
+            unsafe { //~ ERROR: unnecessary `unsafe` block
                 #[deny(unsafe_op_in_unsafe_fn)]
                 {
                     unsf();
@@ -406,15 +406,15 @@ mod additional_tests_closures {
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granularity_2() {
         let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
+            let _ = || unsafe { unsf() };
         };
     }
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn top_level_used_2() {
-        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+        let _ = || unsafe {
             unsf();
             let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
             let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
@@ -463,8 +463,8 @@ mod additional_tests_closures {
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
                 #[deny(unsafe_op_in_unsafe_fn)]
                 {
                     unsf();
@@ -619,15 +619,15 @@ mod additional_tests_even_more_closures {
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granularity_2() {
         let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
+            let _ = || unsafe { let _ = || unsf(); };
         };
     }
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn top_level_used_2() {
-        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+        let _ = || unsafe {
             let _ = || unsf();
             let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
             let _ = || unsafe { let _ = || unsf(); }; //~ ERROR: unnecessary `unsafe` block
@@ -676,8 +676,8 @@ mod additional_tests_even_more_closures {
 
     #[allow(unsafe_op_in_unsafe_fn)]
     unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-        let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-            let _ = || unsafe {
+        let _ = || unsafe {
+            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
                 #[deny(unsafe_op_in_unsafe_fn)]
                 {
                     let _ = || unsf();
@@ -781,15 +781,15 @@ mod item_likes {
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn granularity_2() {
             let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
             };
         }
 
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn top_level_used_2() {
-            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {
                 unsf();
                 let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
                 let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
@@ -838,8 +838,8 @@ mod item_likes {
 
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
                     #[deny(unsafe_op_in_unsafe_fn)]
                     {
                         unsf();
@@ -939,15 +939,15 @@ mod item_likes {
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn granularity_2() {
             let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
+                let _ = || unsafe { unsf() };
             };
         }
 
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn top_level_used_2() {
-            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = || unsafe {
                 unsf();
                 let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
                 let _ = || unsafe { unsf() }; //~ ERROR: unnecessary `unsafe` block
@@ -996,8 +996,8 @@ mod item_likes {
 
         #[allow(unsafe_op_in_unsafe_fn)]
         unsafe fn granular_disallow_op_in_unsafe_fn_3() {
-            let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
-                let _ = || unsafe {
+            let _ = || unsafe {
+                let _ = || unsafe { //~ ERROR: unnecessary `unsafe` block
                     #[deny(unsafe_op_in_unsafe_fn)]
                     {
                         unsf();
@@ -1041,7 +1041,7 @@ mod additional_tests_extra {
 
     #[warn(unsafe_op_in_unsafe_fn)]
     unsafe fn multiple_unsafe_op_in_unsafe_fn_allows() {
-        unsafe { //~ ERROR: unnecessary `unsafe` block
+        unsafe {
             #[allow(unsafe_op_in_unsafe_fn)]
             {
                 unsf();
@@ -1071,11 +1071,11 @@ mod additional_tests_extra {
         #[allow(unsafe_op_in_unsafe_fn)]
         {
             let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block
-                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
-                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
-                let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
+                let _ = async { unsafe { let _ = async { unsf() }; }};
             }};
-            let _ = async { unsafe { //~ ERROR: unnecessary `unsafe` block
+            let _ = async { unsafe {
                 let _ = async { unsf() };
                 let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
                 let _ = async { unsafe { let _ = async { unsf() }; }}; //~ ERROR: unnecessary `unsafe` block
diff --git a/src/test/ui/specialization/default-generic-associated-type-bound.stderr b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
index 58c6667c8c7..6d98763a572 100644
--- a/src/test/ui/specialization/default-generic-associated-type-bound.stderr
+++ b/src/test/ui/specialization/default-generic-associated-type-bound.stderr
@@ -14,7 +14,7 @@ error[E0277]: can't compare `T` with `T`
 LL |     default type U<'a> = &'a T;
    |                          ^^^^^ no implementation for `T == T`
    |
-   = note: required because of the requirements on the impl of `PartialEq` for `&'a T`
+   = note: required for `&'a T` to implement `PartialEq`
 note: required by a bound in `X::U`
   --> $DIR/default-generic-associated-type-bound.rs:8:17
    |
diff --git a/src/test/ui/specialization/issue-38091-2.stderr b/src/test/ui/specialization/issue-38091-2.stderr
index a93f27ff051..146a56358be 100644
--- a/src/test/ui/specialization/issue-38091-2.stderr
+++ b/src/test/ui/specialization/issue-38091-2.stderr
@@ -10,7 +10,7 @@ LL | #![feature(specialization)]
 
 error[E0275]: overflow evaluating the requirement `i32: Check`
    |
-note: required because of the requirements on the impl of `Iterate` for `i32`
+note: required for `i32` to implement `Iterate`
   --> $DIR/issue-38091-2.rs:11:13
    |
 LL | impl<'a, T> Iterate<'a> for T
diff --git a/src/test/ui/specialization/issue-39448.stderr b/src/test/ui/specialization/issue-39448.stderr
index c4fc44c737e..9b74f684b8f 100644
--- a/src/test/ui/specialization/issue-39448.stderr
+++ b/src/test/ui/specialization/issue-39448.stderr
@@ -14,12 +14,12 @@ error[E0275]: overflow evaluating the requirement `T: FromA<U>`
 LL |     x.foo(y.to()).to()
    |             ^^
    |
-note: required because of the requirements on the impl of `FromA<U>` for `T`
+note: required for `T` to implement `FromA<U>`
   --> $DIR/issue-39448.rs:24:29
    |
 LL | impl<T: A, U: A + FromA<T>> FromA<T> for U {
    |                             ^^^^^^^^     ^
-note: required because of the requirements on the impl of `ToA<T>` for `U`
+note: required for `U` to implement `ToA<T>`
   --> $DIR/issue-39448.rs:34:12
    |
 LL | impl<T, U> ToA<U> for T
diff --git a/src/test/ui/specialization/issue-45814.stderr b/src/test/ui/specialization/issue-45814.stderr
index ab6adf477c9..419345addc2 100644
--- a/src/test/ui/specialization/issue-45814.stderr
+++ b/src/test/ui/specialization/issue-45814.stderr
@@ -1,13 +1,13 @@
 error[E0275]: overflow evaluating the requirement `T: Trait<_>`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_45814`)
-note: required because of the requirements on the impl of `Trait<_>` for `T`
+note: required for `T` to implement `Trait<_>`
   --> $DIR/issue-45814.rs:8:20
    |
 LL | default impl<T, U> Trait<T> for U {}
    |                    ^^^^^^^^     ^
    = note: 128 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Trait<_>` for `T`
+   = note: required for `T` to implement `Trait<_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/specialization/min_specialization/issue-79224.stderr b/src/test/ui/specialization/min_specialization/issue-79224.stderr
index cfb9007c7a2..fd34a59d2bd 100644
--- a/src/test/ui/specialization/min_specialization/issue-79224.stderr
+++ b/src/test/ui/specialization/min_specialization/issue-79224.stderr
@@ -1,22 +1,28 @@
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:18:17
+  --> $DIR/issue-79224.rs:18:1
    |
-LL | impl<B: ?Sized> Display for Cow<'_, B> {
-   |                 ^^^^^^^ the trait `Clone` is not implemented for `B`
+LL | / impl<B: ?Sized> Display for Cow<'_, B> {
+LL | |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+LL | |         write!(f, "foo")
+LL | |     }
+LL | | }
+   | |_^ the trait `Clone` is not implemented for `B`
    |
-   = note: required because of the requirements on the impl of `ToOwned` for `B`
+   = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
    |                +++++++++++++++++++
 
 error[E0277]: the trait bound `B: Clone` is not satisfied
-  --> $DIR/issue-79224.rs:19:12
+  --> $DIR/issue-79224.rs:19:5
    |
-LL |     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-   |            ^^^^^ the trait `Clone` is not implemented for `B`
+LL | /     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+LL | |         write!(f, "foo")
+LL | |     }
+   | |_____^ the trait `Clone` is not implemented for `B`
    |
-   = note: required because of the requirements on the impl of `ToOwned` for `B`
+   = note: required for `B` to implement `ToOwned`
 help: consider further restricting this bound
    |
 LL | impl<B: ?Sized + std::clone::Clone> Display for Cow<'_, B> {
diff --git a/src/test/ui/static/static-vec-repeat-not-constant.stderr b/src/test/ui/static/static-vec-repeat-not-constant.stderr
index 84fc638a973..dec0123184d 100644
--- a/src/test/ui/static/static-vec-repeat-not-constant.stderr
+++ b/src/test/ui/static/static-vec-repeat-not-constant.stderr
@@ -5,6 +5,7 @@ LL | static a: [isize; 2] = [foo(); 2];
    |                         ^^^^^
    |
    = note: calls in statics are limited to constant functions, tuple structs and tuple variants
+   = note: consider wrapping this expression in `Lazy::new(|| ...)` from the `once_cell` crate: https://crates.io/crates/once_cell
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/stats/hir-stats.stderr b/src/test/ui/stats/hir-stats.stderr
index 9ea32e8d64e..eb828bb9a2c 100644
--- a/src/test/ui/stats/hir-stats.stderr
+++ b/src/test/ui/stats/hir-stats.stderr
@@ -3,59 +3,59 @@ PRE EXPANSION AST STATS
 
 Name                Accumulated Size         Count     Item Size
 ----------------------------------------------------------------
-ExprField                 48 ( 0.5%)             1            48
-Attribute                 64 ( 0.7%)             2            32
+ExprField                 48 ( 0.6%)             1            48
+Crate                     56 ( 0.7%)             1            56
+Attribute                 64 ( 0.8%)             2            32
 - Normal                    32 ( 0.4%)             1
 - DocComment                32 ( 0.4%)             1
-GenericArgs               64 ( 0.7%)             1            64
-- AngleBracketed            64 ( 0.7%)             1
-Local                     72 ( 0.8%)             1            72
-WherePredicate            72 ( 0.8%)             1            72
-- BoundPredicate            72 ( 0.8%)             1
-Crate                     72 ( 0.8%)             1            72
+GenericArgs               64 ( 0.8%)             1            64
+- AngleBracketed            64 ( 0.8%)             1
+Local                     72 ( 0.9%)             1            72
+WherePredicate            72 ( 0.9%)             1            72
+- BoundPredicate            72 ( 0.9%)             1
 Arm                       96 ( 1.1%)             2            48
-FieldDef                 160 ( 1.8%)             2            80
-ForeignItem              160 ( 1.8%)             1           160
-- Fn                       160 ( 1.8%)             1
-Stmt                     160 ( 1.8%)             5            32
+ForeignItem               96 ( 1.1%)             1            96
+- Fn                        96 ( 1.1%)             1
+FieldDef                 160 ( 1.9%)             2            80
+Stmt                     160 ( 1.9%)             5            32
 - Local                     32 ( 0.4%)             1
 - MacCall                   32 ( 0.4%)             1
 - Expr                      96 ( 1.1%)             3
-Param                    160 ( 1.8%)             4            40
-FnDecl                   200 ( 2.2%)             5            40
-Variant                  240 ( 2.7%)             2           120
-Block                    288 ( 3.2%)             6            48
-GenericBound             352 ( 4.0%)             4            88
-- Trait                    352 ( 4.0%)             4
-GenericParam             520 ( 5.8%)             5           104
-AssocItem                640 ( 7.2%)             4           160
-- TyAlias                  320 ( 3.6%)             2
-- Fn                       320 ( 3.6%)             2
-PathSegment              720 ( 8.1%)            30            24
-Expr                     832 ( 9.3%)             8           104
+Param                    160 ( 1.9%)             4            40
+FnDecl                   200 ( 2.4%)             5            40
+Variant                  240 ( 2.8%)             2           120
+Block                    288 ( 3.4%)             6            48
+GenericBound             352 ( 4.2%)             4            88
+- Trait                    352 ( 4.2%)             4
+AssocItem                416 ( 4.9%)             4           104
+- TyAlias                  208 ( 2.5%)             2
+- Fn                       208 ( 2.5%)             2
+GenericParam             520 ( 6.1%)             5           104
+PathSegment              720 ( 8.5%)            30            24
+Expr                     832 ( 9.8%)             8           104
 - Path                     104 ( 1.2%)             1
 - Match                    104 ( 1.2%)             1
 - Struct                   104 ( 1.2%)             1
-- Lit                      208 ( 2.3%)             2
-- Block                    312 ( 3.5%)             3
-Pat                      840 ( 9.4%)             7           120
-- Struct                   120 ( 1.3%)             1
-- Wild                     120 ( 1.3%)             1
-- Ident                    600 ( 6.7%)             5
-Ty                     1_344 (15.1%)            14            96
+- Lit                      208 ( 2.5%)             2
+- Block                    312 ( 3.7%)             3
+Pat                      840 ( 9.9%)             7           120
+- Struct                   120 ( 1.4%)             1
+- Wild                     120 ( 1.4%)             1
+- Ident                    600 ( 7.1%)             5
+Ty                     1_344 (15.9%)            14            96
 - Rptr                      96 ( 1.1%)             1
 - Ptr                       96 ( 1.1%)             1
-- ImplicitSelf             192 ( 2.2%)             2
-- Path                     960 (10.8%)            10
-Item                   1_800 (20.2%)             9           200
-- Trait                    200 ( 2.2%)             1
-- Enum                     200 ( 2.2%)             1
-- ForeignMod               200 ( 2.2%)             1
-- Impl                     200 ( 2.2%)             1
-- Fn                       400 ( 4.5%)             2
-- Use                      600 ( 6.7%)             3
+- ImplicitSelf             192 ( 2.3%)             2
+- Path                     960 (11.4%)            10
+Item                   1_656 (19.6%)             9           184
+- Trait                    184 ( 2.2%)             1
+- Enum                     184 ( 2.2%)             1
+- ForeignMod               184 ( 2.2%)             1
+- Impl                     184 ( 2.2%)             1
+- Fn                       368 ( 4.4%)             2
+- Use                      552 ( 6.5%)             3
 ----------------------------------------------------------------
-Total                  8_904
+Total                  8_456
 
 
 POST EXPANSION AST STATS
@@ -63,61 +63,61 @@ POST EXPANSION AST STATS
 Name                Accumulated Size         Count     Item Size
 ----------------------------------------------------------------
 ExprField                 48 ( 0.5%)             1            48
+Crate                     56 ( 0.6%)             1            56
 GenericArgs               64 ( 0.7%)             1            64
 - AngleBracketed            64 ( 0.7%)             1
-Local                     72 ( 0.7%)             1            72
-WherePredicate            72 ( 0.7%)             1            72
-- BoundPredicate            72 ( 0.7%)             1
-Crate                     72 ( 0.7%)             1            72
+Local                     72 ( 0.8%)             1            72
+WherePredicate            72 ( 0.8%)             1            72
+- BoundPredicate            72 ( 0.8%)             1
 Arm                       96 ( 1.0%)             2            48
-InlineAsm                120 ( 1.2%)             1           120
-Attribute                128 ( 1.3%)             4            32
+ForeignItem               96 ( 1.0%)             1            96
+- Fn                        96 ( 1.0%)             1
+InlineAsm                120 ( 1.3%)             1           120
+Attribute                128 ( 1.4%)             4            32
 - DocComment                32 ( 0.3%)             1
 - Normal                    96 ( 1.0%)             3
 FieldDef                 160 ( 1.7%)             2            80
-ForeignItem              160 ( 1.7%)             1           160
-- Fn                       160 ( 1.7%)             1
 Stmt                     160 ( 1.7%)             5            32
 - Local                     32 ( 0.3%)             1
 - Semi                      32 ( 0.3%)             1
 - Expr                      96 ( 1.0%)             3
 Param                    160 ( 1.7%)             4            40
-FnDecl                   200 ( 2.1%)             5            40
-Variant                  240 ( 2.5%)             2           120
-Block                    288 ( 3.0%)             6            48
-GenericBound             352 ( 3.6%)             4            88
-- Trait                    352 ( 3.6%)             4
-GenericParam             520 ( 5.4%)             5           104
-AssocItem                640 ( 6.6%)             4           160
-- TyAlias                  320 ( 3.3%)             2
-- Fn                       320 ( 3.3%)             2
-PathSegment              792 ( 8.2%)            33            24
-Pat                      840 ( 8.7%)             7           120
-- Struct                   120 ( 1.2%)             1
-- Wild                     120 ( 1.2%)             1
-- Ident                    600 ( 6.2%)             5
-Expr                     936 ( 9.7%)             9           104
+FnDecl                   200 ( 2.2%)             5            40
+Variant                  240 ( 2.6%)             2           120
+Block                    288 ( 3.1%)             6            48
+GenericBound             352 ( 3.8%)             4            88
+- Trait                    352 ( 3.8%)             4
+AssocItem                416 ( 4.5%)             4           104
+- TyAlias                  208 ( 2.3%)             2
+- Fn                       208 ( 2.3%)             2
+GenericParam             520 ( 5.7%)             5           104
+PathSegment              792 ( 8.6%)            33            24
+Pat                      840 ( 9.1%)             7           120
+- Struct                   120 ( 1.3%)             1
+- Wild                     120 ( 1.3%)             1
+- Ident                    600 ( 6.5%)             5
+Expr                     936 (10.2%)             9           104
 - Path                     104 ( 1.1%)             1
 - Match                    104 ( 1.1%)             1
 - Struct                   104 ( 1.1%)             1
 - InlineAsm                104 ( 1.1%)             1
-- Lit                      208 ( 2.2%)             2
-- Block                    312 ( 3.2%)             3
-Ty                     1_344 (13.9%)            14            96
+- Lit                      208 ( 2.3%)             2
+- Block                    312 ( 3.4%)             3
+Ty                     1_344 (14.6%)            14            96
 - Rptr                      96 ( 1.0%)             1
 - Ptr                       96 ( 1.0%)             1
-- ImplicitSelf             192 ( 2.0%)             2
-- Path                     960 ( 9.9%)            10
-Item                   2_200 (22.8%)            11           200
-- Trait                    200 ( 2.1%)             1
-- Enum                     200 ( 2.1%)             1
-- ExternCrate              200 ( 2.1%)             1
-- ForeignMod               200 ( 2.1%)             1
-- Impl                     200 ( 2.1%)             1
-- Fn                       400 ( 4.1%)             2
-- Use                      800 ( 8.3%)             4
+- ImplicitSelf             192 ( 2.1%)             2
+- Path                     960 (10.5%)            10
+Item                   2_024 (22.0%)            11           184
+- Trait                    184 ( 2.0%)             1
+- Enum                     184 ( 2.0%)             1
+- ExternCrate              184 ( 2.0%)             1
+- ForeignMod               184 ( 2.0%)             1
+- Impl                     184 ( 2.0%)             1
+- Fn                       368 ( 4.0%)             2
+- Use                      736 ( 8.0%)             4
 ----------------------------------------------------------------
-Total                  9_664
+Total                  9_184
 
 
 HIR STATS
diff --git a/src/test/ui/str/str-idx.stderr b/src/test/ui/str/str-idx.stderr
index 9079a18d6a6..019305def29 100644
--- a/src/test/ui/str/str-idx.stderr
+++ b/src/test/ui/str/str-idx.stderr
@@ -8,7 +8,7 @@ LL |     let _: u8 = s[4];
    = note: you can use `.chars().nth()` or `.bytes().nth()`
            for more information, see chapter 8 in The Book: <https://doc.rust-lang.org/book/ch08-02-strings.html#indexing-into-strings>
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<{integer}>` for `str`
+   = note: required for `str` to implement `Index<{integer}>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-idx.rs:4:19
@@ -53,7 +53,7 @@ LL |     let _: u8 = s['c'];
    |                   ^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `char`
-   = note: required because of the requirements on the impl of `Index<char>` for `str`
+   = note: required for `str` to implement `Index<char>`
 
 error: aborting due to 4 previous errors
 
diff --git a/src/test/ui/str/str-mut-idx.stderr b/src/test/ui/str/str-mut-idx.stderr
index 2d062e56a9b..b165c482590 100644
--- a/src/test/ui/str/str-mut-idx.stderr
+++ b/src/test/ui/str/str-mut-idx.stderr
@@ -32,7 +32,7 @@ LL |     s[1usize] = bot();
    |
    = help: the trait `SliceIndex<str>` is not implemented for `usize`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<usize>` for `str`
+   = note: required for `str` to implement `Index<usize>`
 
 error[E0277]: the type `str` cannot be indexed by `{integer}`
   --> $DIR/str-mut-idx.rs:9:15
@@ -77,7 +77,7 @@ LL |     s['c'];
    |       ^^^ string indices are ranges of `usize`
    |
    = help: the trait `SliceIndex<str>` is not implemented for `char`
-   = note: required because of the requirements on the impl of `Index<char>` for `str`
+   = note: required for `str` to implement `Index<char>`
 
 error: aborting due to 6 previous errors
 
diff --git a/src/test/ui/suggestions/as-ref-2.fixed b/src/test/ui/suggestions/as-ref-2.fixed
deleted file mode 100644
index 13bbb233f39..00000000000
--- a/src/test/ui/suggestions/as-ref-2.fixed
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-rustfix
-
-struct Struct;
-
-fn bar(_: &Struct) -> Struct {
-    Struct
-}
-
-fn main() {
-    let foo = Some(Struct);
-    let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
-    let _y = foo; //~ERROR use of moved value: `foo`
-}
diff --git a/src/test/ui/suggestions/as-ref-2.rs b/src/test/ui/suggestions/as-ref-2.rs
index 74d61cdd95f..b22f409b44a 100644
--- a/src/test/ui/suggestions/as-ref-2.rs
+++ b/src/test/ui/suggestions/as-ref-2.rs
@@ -1,5 +1,3 @@
-// run-rustfix
-
 struct Struct;
 
 fn bar(_: &Struct) -> Struct {
diff --git a/src/test/ui/suggestions/as-ref-2.stderr b/src/test/ui/suggestions/as-ref-2.stderr
index 3c9d0f72abe..e15e45d86b9 100644
--- a/src/test/ui/suggestions/as-ref-2.stderr
+++ b/src/test/ui/suggestions/as-ref-2.stderr
@@ -1,10 +1,12 @@
 error[E0382]: use of moved value: `foo`
-  --> $DIR/as-ref-2.rs:12:14
+  --> $DIR/as-ref-2.rs:10:14
    |
 LL |     let foo = Some(Struct);
    |         --- move occurs because `foo` has type `Option<Struct>`, which does not implement the `Copy` trait
 LL |     let _x: Option<Struct> = foo.map(|s| bar(&s));
-   |                                  ---------------- `foo` moved due to this method call
+   |                              --- ---------------- `foo` moved due to this method call
+   |                              |
+   |                              help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
 LL |     let _y = foo;
    |              ^^^ value used here after move
    |
@@ -13,10 +15,6 @@ note: this function takes ownership of the receiver `self`, which moves `foo`
    |
 LL |     pub const fn map<U, F>(self, f: F) -> Option<U>
    |                            ^^^^
-help: consider calling `.as_ref()` to borrow the type's contents
-   |
-LL |     let _x: Option<Struct> = foo.as_ref().map(|s| bar(&s));
-   |                                  +++++++++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/derive-clone-for-eq.stderr b/src/test/ui/suggestions/derive-clone-for-eq.stderr
index 55a23c031d5..0645f0cdde7 100644
--- a/src/test/ui/suggestions/derive-clone-for-eq.stderr
+++ b/src/test/ui/suggestions/derive-clone-for-eq.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Clone` is not satisfied
 LL | #[derive(Clone, Eq)]
    |                 ^^ the trait `Clone` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `PartialEq` for `Struct<T>`
+note: required for `Struct<T>` to implement `PartialEq`
   --> $DIR/derive-clone-for-eq.rs:9:19
    |
 LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
diff --git a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr
index 4186dc7cb35..b9f7739654a 100644
--- a/src/test/ui/suggestions/derive-macro-missing-bounds.stderr
+++ b/src/test/ui/suggestions/derive-macro-missing-bounds.stderr
@@ -26,13 +26,13 @@ LL |     #[derive(Debug)]
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ the trait `c::Trait` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Debug` for `c::Inner<T>`
+note: required for `c::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:34:28
    |
 LL |     impl<T: Debug + Trait> Debug for Inner<T> {
    |                            ^^^^^     ^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Debug` for `&c::Inner<T>`
+   = note: required for `&c::Inner<T>` to implement `Debug`
    = note: required for the cast from `&c::Inner<T>` to the object type `dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
@@ -48,13 +48,13 @@ LL |     #[derive(Debug)]
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ the trait `d::Trait` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Debug` for `d::Inner<T>`
+note: required for `d::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:49:13
    |
 LL |     impl<T> Debug for Inner<T> where T: Debug, T: Trait {
    |             ^^^^^     ^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Debug` for `&d::Inner<T>`
+   = note: required for `&d::Inner<T>` to implement `Debug`
    = note: required for the cast from `&d::Inner<T>` to the object type `dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
@@ -70,13 +70,13 @@ LL |     #[derive(Debug)]
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ the trait `e::Trait` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Debug` for `e::Inner<T>`
+note: required for `e::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:64:13
    |
 LL |     impl<T> Debug for Inner<T> where T: Debug + Trait {
    |             ^^^^^     ^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Debug` for `&e::Inner<T>`
+   = note: required for `&e::Inner<T>` to implement `Debug`
    = note: required for the cast from `&e::Inner<T>` to the object type `dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
@@ -92,13 +92,13 @@ LL |     #[derive(Debug)]
 LL |     struct Outer<T>(Inner<T>);
    |                     ^^^^^^^^ the trait `f::Trait` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `Debug` for `f::Inner<T>`
+note: required for `f::Inner<T>` to implement `Debug`
   --> $DIR/derive-macro-missing-bounds.rs:79:20
    |
 LL |     impl<T: Debug> Debug for Inner<T> where T: Trait {
    |                    ^^^^^     ^^^^^^^^
    = note: 1 redundant requirement hidden
-   = note: required because of the requirements on the impl of `Debug` for `&f::Inner<T>`
+   = note: required for `&f::Inner<T>` to implement `Debug`
    = note: required for the cast from `&f::Inner<T>` to the object type `dyn Debug`
    = note: this error originates in the derive macro `Debug` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider restricting type parameter `T`
diff --git a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
index 71facf57e8d..e43a4e79bfe 100644
--- a/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
+++ b/src/test/ui/suggestions/expected-boxed-future-isnt-pinned.stderr
@@ -46,10 +46,12 @@ LL |     pub const fn new(pointer: P) -> Pin<P> {
    |                  ^^^
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
-  --> $DIR/expected-boxed-future-isnt-pinned.rs:19:5
+  --> $DIR/expected-boxed-future-isnt-pinned.rs:19:14
    |
 LL |     Pin::new(x)
-   |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     -------- ^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
@@ -59,10 +61,12 @@ LL | impl<P: Deref<Target: Unpin>> Pin<P> {
    |                       ^^^^^ required by this bound in `Pin::<P>::new`
 
 error[E0277]: `dyn Future<Output = i32> + Send` cannot be unpinned
-  --> $DIR/expected-boxed-future-isnt-pinned.rs:24:5
+  --> $DIR/expected-boxed-future-isnt-pinned.rs:24:14
    |
 LL |     Pin::new(Box::new(x))
-   |     ^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     -------- ^^^^^^^^^^^ the trait `Unpin` is not implemented for `dyn Future<Output = i32> + Send`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `Pin::<P>::new`
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
index ba6af8f15fa..864ab053520 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal-bound-regions.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `for<'b> &'b S: Trait` is not satisfied
-  --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:5
+  --> $DIR/imm-ref-trait-object-literal-bound-regions.rs:17:14
    |
 LL |     foo::<S>(s);
-   |     ^^^^^^^^ the trait `for<'b> Trait` is not implemented for `&'b S`
+   |     -------- ^ the trait `for<'b> Trait` is not implemented for `&'b S`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Trait` is implemented for `&'a mut S`
    = note: `for<'b> Trait` is implemented for `&'b mut S`, but not for `&'b S`
diff --git a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
index 5f3f62a7b75..e01102e3864 100644
--- a/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
+++ b/src/test/ui/suggestions/imm-ref-trait-object-literal.stderr
@@ -21,7 +21,7 @@ error[E0277]: the trait bound `S: Trait` is not satisfied
   --> $DIR/imm-ref-trait-object-literal.rs:13:7
    |
 LL |   foo(s);
-   |   --- ^ expected an implementor of trait `Trait`
+   |   --- ^ the trait `Trait` is not implemented for `S`
    |   |
    |   required by a bound introduced by this call
    |
diff --git a/src/test/ui/suggestions/into-str.stderr b/src/test/ui/suggestions/into-str.stderr
index 8ae5c847947..a56a2a188cb 100644
--- a/src/test/ui/suggestions/into-str.stderr
+++ b/src/test/ui/suggestions/into-str.stderr
@@ -14,7 +14,7 @@ LL |     foo(String::new());
              <String as From<Box<str>>>
              <String as From<Cow<'a, str>>>
              <String as From<char>>
-   = note: required because of the requirements on the impl of `Into<&str>` for `String`
+   = note: required for `String` to implement `Into<&str>`
 note: required by a bound in `foo`
   --> $DIR/into-str.rs:1:31
    |
diff --git a/src/test/ui/suggestions/issue-62843.stderr b/src/test/ui/suggestions/issue-62843.stderr
index bc1c69406d1..62f0943d4c9 100644
--- a/src/test/ui/suggestions/issue-62843.stderr
+++ b/src/test/ui/suggestions/issue-62843.stderr
@@ -2,12 +2,12 @@ error[E0277]: expected a `FnMut<(char,)>` closure, found `String`
   --> $DIR/issue-62843.rs:4:32
    |
 LL |     println!("{:?}", line.find(pattern));
-   |                           ---- ^^^^^^^ expected an implementor of trait `Pattern<'_>`
+   |                           ---- ^^^^^^^ the trait `Pattern<'_>` is not implemented for `String`
    |                           |
    |                           required by a bound introduced by this call
    |
    = note: the trait bound `String: Pattern<'_>` is not satisfied
-   = note: required because of the requirements on the impl of `Pattern<'_>` for `String`
+   = note: required for `String` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::find`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
    |
diff --git a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
index 383f40d47fa..684db23e135 100644
--- a/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
+++ b/src/test/ui/suggestions/issue-71394-no-from-impl.stderr
@@ -1,13 +1,15 @@
 error[E0277]: the trait bound `&[i8]: From<&[u8]>` is not satisfied
-  --> $DIR/issue-71394-no-from-impl.rs:3:25
+  --> $DIR/issue-71394-no-from-impl.rs:3:20
    |
 LL |     let _: &[i8] = data.into();
-   |                         ^^^^ the trait `From<&[u8]>` is not implemented for `&[i8]`
+   |                    ^^^^ ---- required by a bound introduced by this call
+   |                    |
+   |                    the trait `From<&[u8]>` is not implemented for `&[i8]`
    |
    = help: the following other types implement trait `From<T>`:
              <[T; LANES] as From<Simd<T, LANES>>>
              <[bool; LANES] as From<Mask<T, LANES>>>
-   = note: required because of the requirements on the impl of `Into<&[i8]>` for `&[u8]`
+   = note: required for `&[u8]` to implement `Into<&[i8]>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/issue-84973-2.stderr b/src/test/ui/suggestions/issue-84973-2.stderr
index 2c54ea67245..513bf28fb58 100644
--- a/src/test/ui/suggestions/issue-84973-2.stderr
+++ b/src/test/ui/suggestions/issue-84973-2.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `i32: Tr` is not satisfied
   --> $DIR/issue-84973-2.rs:11:9
    |
 LL |     foo(a);
-   |     --- ^ expected an implementor of trait `Tr`
+   |     --- ^ the trait `Tr` is not implemented for `i32`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/suggestions/issue-84973-blacklist.stderr b/src/test/ui/suggestions/issue-84973-blacklist.stderr
index ae0d3efca47..c20cc816484 100644
--- a/src/test/ui/suggestions/issue-84973-blacklist.stderr
+++ b/src/test/ui/suggestions/issue-84973-blacklist.stderr
@@ -31,10 +31,12 @@ LL | #[derive(Clone)]
    |
 
 error[E0277]: `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]` cannot be unpinned
-  --> $DIR/issue-84973-blacklist.rs:17:5
+  --> $DIR/issue-84973-blacklist.rs:17:13
    |
 LL |     f_unpin(static || { yield; });
-   |     ^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]`
+   |     ------- ^^^^^^^^^^^^^^^^^^^^ the trait `Unpin` is not implemented for `[static generator@$DIR/issue-84973-blacklist.rs:17:13: 17:22]`
+   |     |
+   |     required by a bound introduced by this call
    |
    = note: consider using `Box::pin`
 note: required by a bound in `f_unpin`
diff --git a/src/test/ui/suggestions/issue-84973-negative.stderr b/src/test/ui/suggestions/issue-84973-negative.stderr
index 15559d4ae2c..ce838bce09e 100644
--- a/src/test/ui/suggestions/issue-84973-negative.stderr
+++ b/src/test/ui/suggestions/issue-84973-negative.stderr
@@ -17,7 +17,7 @@ error[E0277]: the trait bound `f32: Tr` is not satisfied
   --> $DIR/issue-84973-negative.rs:11:9
    |
 LL |     bar(b);
-   |     --- ^ expected an implementor of trait `Tr`
+   |     --- ^ the trait `Tr` is not implemented for `f32`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/suggestions/issue-84973.stderr b/src/test/ui/suggestions/issue-84973.stderr
index 24c989ec3e8..ae2bf5aac40 100644
--- a/src/test/ui/suggestions/issue-84973.stderr
+++ b/src/test/ui/suggestions/issue-84973.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `Fancy: SomeTrait` is not satisfied
   --> $DIR/issue-84973.rs:6:24
    |
 LL |     let o = Other::new(f);
-   |             ---------- ^ expected an implementor of trait `SomeTrait`
+   |             ---------- ^ the trait `SomeTrait` is not implemented for `Fancy`
    |             |
    |             required by a bound introduced by this call
    |
diff --git a/src/test/ui/suggestions/issue-96223.stderr b/src/test/ui/suggestions/issue-96223.stderr
index 513725d9962..72a9a739a64 100644
--- a/src/test/ui/suggestions/issue-96223.stderr
+++ b/src/test/ui/suggestions/issue-96223.stderr
@@ -7,12 +7,12 @@ LL |     icey_bounds(&p);
    |     required by a bound introduced by this call
    |
    = help: the trait `Foo<'de>` is implemented for `Baz<T>`
-note: required because of the requirements on the impl of `for<'de> Foo<'de>` for `Baz<EmptyBis<'de>>`
+note: required for `Baz<EmptyBis<'de>>` to implement `for<'de> Foo<'de>`
   --> $DIR/issue-96223.rs:16:14
    |
 LL | impl<'de, T> Foo<'de> for Baz<T> where T: Foo<'de> {}
    |              ^^^^^^^^     ^^^^^^
-note: required because of the requirements on the impl of `Dummy<EmptyMarker>` for `Empty`
+note: required for `Empty` to implement `Dummy<EmptyMarker>`
   --> $DIR/issue-96223.rs:20:9
    |
 LL | impl<M> Dummy<M> for Empty
diff --git a/src/test/ui/suggestions/issue-96555.stderr b/src/test/ui/suggestions/issue-96555.stderr
index a1a603cf246..9a8a183dc2d 100644
--- a/src/test/ui/suggestions/issue-96555.stderr
+++ b/src/test/ui/suggestions/issue-96555.stderr
@@ -8,7 +8,7 @@ LL |     m::f1().await;
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `()`
+   = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     m::f1().await;
@@ -29,7 +29,7 @@ LL |     m::f2().await;
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `()`
+   = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     m::f2().await;
@@ -50,7 +50,7 @@ LL |     m::f3().await;
    |
    = help: the trait `Future` is not implemented for `()`
    = note: () must be a future or must implement `IntoFuture` to be awaited
-   = note: required because of the requirements on the impl of `IntoFuture` for `()`
+   = note: required for `()` to implement `IntoFuture`
 help: remove the `.await`
    |
 LL -     m::f3().await;
diff --git a/src/test/ui/suggestions/many-type-ascription.rs b/src/test/ui/suggestions/many-type-ascription.rs
new file mode 100644
index 00000000000..31ac556b944
--- /dev/null
+++ b/src/test/ui/suggestions/many-type-ascription.rs
@@ -0,0 +1,4 @@
+fn main() {
+    let _ = 0: i32; //~ ERROR: type ascription is experimental
+    let _ = 0: i32; // (error only emitted once)
+}
diff --git a/src/test/ui/suggestions/many-type-ascription.stderr b/src/test/ui/suggestions/many-type-ascription.stderr
new file mode 100644
index 00000000000..3706bbae9df
--- /dev/null
+++ b/src/test/ui/suggestions/many-type-ascription.stderr
@@ -0,0 +1,12 @@
+error[E0658]: type ascription is experimental
+  --> $DIR/many-type-ascription.rs:2:13
+   |
+LL |     let _ = 0: i32;
+   |             ^^^^^^
+   |
+   = note: see issue #23416 <https://github.com/rust-lang/rust/issues/23416> for more information
+   = help: add `#![feature(type_ascription)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/src/test/ui/suggestions/option-content-move.fixed b/src/test/ui/suggestions/option-content-move.fixed
deleted file mode 100644
index ba16bcc8a33..00000000000
--- a/src/test/ui/suggestions/option-content-move.fixed
+++ /dev/null
@@ -1,39 +0,0 @@
-//run-rustfix
-
-pub struct LipogramCorpora {
-    selections: Vec<(char, Option<String>)>,
-}
-
-impl LipogramCorpora {
-    pub fn validate_all(&mut self) -> Result<(), char> {
-        for selection in &self.selections {
-            if selection.1.is_some() {
-                if selection.1.as_ref().unwrap().contains(selection.0) {
-                //~^ ERROR cannot move out of `selection.1`
-                    return Err(selection.0);
-                }
-            }
-        }
-        Ok(())
-    }
-}
-
-pub struct LipogramCorpora2 {
-    selections: Vec<(char, Result<String, String>)>,
-}
-
-impl LipogramCorpora2 {
-    pub fn validate_all(&mut self) -> Result<(), char> {
-        for selection in &self.selections {
-            if selection.1.is_ok() {
-                if selection.1.as_ref().unwrap().contains(selection.0) {
-                //~^ ERROR cannot move out of `selection.1`
-                    return Err(selection.0);
-                }
-            }
-        }
-        Ok(())
-    }
-}
-
-fn main() {}
diff --git a/src/test/ui/suggestions/option-content-move.rs b/src/test/ui/suggestions/option-content-move.rs
index ef38f114eca..46c895b95f5 100644
--- a/src/test/ui/suggestions/option-content-move.rs
+++ b/src/test/ui/suggestions/option-content-move.rs
@@ -1,5 +1,3 @@
-//run-rustfix
-
 pub struct LipogramCorpora {
     selections: Vec<(char, Option<String>)>,
 }
diff --git a/src/test/ui/suggestions/option-content-move.stderr b/src/test/ui/suggestions/option-content-move.stderr
index fccfbe1d744..a6f1ebc975f 100644
--- a/src/test/ui/suggestions/option-content-move.stderr
+++ b/src/test/ui/suggestions/option-content-move.stderr
@@ -1,9 +1,10 @@
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
-  --> $DIR/option-content-move.rs:11:20
+  --> $DIR/option-content-move.rs:9:20
    |
 LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
    |                    |
+   |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Option<String>`, which does not implement the `Copy` trait
    |
 note: this function takes ownership of the receiver `self`, which moves `selection.1`
@@ -11,17 +12,14 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
    |
 LL |     pub const fn unwrap(self) -> T {
    |                         ^^^^
-help: consider calling `.as_ref()` to borrow the type's contents
-   |
-LL |                 if selection.1.as_ref().unwrap().contains(selection.0) {
-   |                                +++++++++
 
 error[E0507]: cannot move out of `selection.1` which is behind a shared reference
-  --> $DIR/option-content-move.rs:29:20
+  --> $DIR/option-content-move.rs:27:20
    |
 LL |                 if selection.1.unwrap().contains(selection.0) {
    |                    ^^^^^^^^^^^ -------- `selection.1` moved due to this method call
    |                    |
+   |                    help: consider calling `.as_ref()` or `.as_mut()` to borrow the type's contents
    |                    move occurs because `selection.1` has type `Result<String, String>`, which does not implement the `Copy` trait
    |
 note: this function takes ownership of the receiver `self`, which moves `selection.1`
@@ -29,10 +27,6 @@ note: this function takes ownership of the receiver `self`, which moves `selecti
    |
 LL |     pub fn unwrap(self) -> T
    |                   ^^^^
-help: consider calling `.as_ref()` to borrow the type's contents
-   |
-LL |                 if selection.1.as_ref().unwrap().contains(selection.0) {
-   |                                +++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/suggestions/slice-issue-87994.stderr b/src/test/ui/suggestions/slice-issue-87994.stderr
index fd2a44f9a82..84ecd749b0d 100644
--- a/src/test/ui/suggestions/slice-issue-87994.stderr
+++ b/src/test/ui/suggestions/slice-issue-87994.stderr
@@ -2,10 +2,10 @@ error[E0277]: the size for values of type `[i32]` cannot be known at compilation
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
-   |            ^^^^^^ expected an implementor of trait `IntoIterator`
+   |            ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
    |
    = note: the trait bound `[i32]: IntoIterator` is not satisfied
-   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+   = note: required for `[i32]` to implement `IntoIterator`
 help: consider borrowing here
    |
 LL |   for _ in &v[1..] {
@@ -17,10 +17,10 @@ error[E0277]: `[i32]` is not an iterator
   --> $DIR/slice-issue-87994.rs:3:12
    |
 LL |   for _ in v[1..] {
-   |            ^^^^^^ expected an implementor of trait `IntoIterator`
+   |            ^^^^^^ the trait `IntoIterator` is not implemented for `[i32]`
    |
    = note: the trait bound `[i32]: IntoIterator` is not satisfied
-   = note: required because of the requirements on the impl of `IntoIterator` for `[i32]`
+   = note: required for `[i32]` to implement `IntoIterator`
 help: consider borrowing here
    |
 LL |   for _ in &v[1..] {
@@ -32,10 +32,10 @@ error[E0277]: the size for values of type `[K]` cannot be known at compilation t
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
-   |             ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |             ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
    |
    = note: the trait bound `[K]: IntoIterator` is not satisfied
-   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+   = note: required for `[K]` to implement `IntoIterator`
 help: consider borrowing here
    |
 LL |   for i2 in &v2[1..] {
@@ -47,10 +47,10 @@ error[E0277]: `[K]` is not an iterator
   --> $DIR/slice-issue-87994.rs:11:13
    |
 LL |   for i2 in v2[1..] {
-   |             ^^^^^^^ expected an implementor of trait `IntoIterator`
+   |             ^^^^^^^ the trait `IntoIterator` is not implemented for `[K]`
    |
    = note: the trait bound `[K]: IntoIterator` is not satisfied
-   = note: required because of the requirements on the impl of `IntoIterator` for `[K]`
+   = note: required for `[K]` to implement `IntoIterator`
 help: consider borrowing here
    |
 LL |   for i2 in &v2[1..] {
diff --git a/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed
new file mode 100644
index 00000000000..e9b8a9caa48
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.fixed
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn foo(foo: &mut usize) {
+    todo!()
+}
+
+fn bar(bar: &usize) {
+    todo!()
+}
+
+fn main() {
+    foo(&mut Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
+    bar(&Default::default()); //~ the trait bound `&usize: Default` is not satisfied
+}
diff --git a/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs
new file mode 100644
index 00000000000..5fae21cccef
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.rs
@@ -0,0 +1,15 @@
+// run-rustfix
+#![allow(unused_variables)]
+
+fn foo(foo: &mut usize) {
+    todo!()
+}
+
+fn bar(bar: &usize) {
+    todo!()
+}
+
+fn main() {
+    foo(Default::default()); //~ the trait bound `&mut usize: Default` is not satisfied
+    bar(Default::default()); //~ the trait bound `&usize: Default` is not satisfied
+}
diff --git a/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr
new file mode 100644
index 00000000000..125a8b44f2f
--- /dev/null
+++ b/src/test/ui/suggestions/suggest-adding-reference-to-trait-assoc-item.stderr
@@ -0,0 +1,25 @@
+error[E0277]: the trait bound `&mut usize: Default` is not satisfied
+  --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:13:9
+   |
+LL |     foo(Default::default());
+   |         ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&mut usize`
+   |
+help: consider mutably borrowing here
+   |
+LL |     foo(&mut Default::default());
+   |         ++++
+
+error[E0277]: the trait bound `&usize: Default` is not satisfied
+  --> $DIR/suggest-adding-reference-to-trait-assoc-item.rs:14:9
+   |
+LL |     bar(Default::default());
+   |         ^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `&usize`
+   |
+help: consider borrowing here
+   |
+LL |     bar(&Default::default());
+   |         +
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
index 6b6e406130e..6ce9bfd9dca 100644
--- a/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
+++ b/src/test/ui/suggestions/suggest-borrow-to-dyn-object.stderr
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/suggest-borrow-to-dyn-object.rs:12:11
    |
 LL |     check(s);
-   |     ----- ^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^ doesn't have a size known at compile-time
    |
    = help: within `OsStr`, the trait `Sized` is not implemented for `[u8]`
    = note: required because it appears within the type `OsStr`
diff --git a/src/test/ui/suggestions/suggest-dereferencing-index.stderr b/src/test/ui/suggestions/suggest-dereferencing-index.stderr
index c8b87af7bd8..147dc9234c5 100644
--- a/src/test/ui/suggestions/suggest-dereferencing-index.stderr
+++ b/src/test/ui/suggestions/suggest-dereferencing-index.stderr
@@ -6,7 +6,7 @@ LL |     let one_item_please: i32 = [1, 2, 3][i];
    |
    = help: the trait `SliceIndex<[{integer}]>` is not implemented for `&usize`
    = help: the trait `SliceIndex<[T]>` is implemented for `usize`
-   = note: required because of the requirements on the impl of `Index<&usize>` for `[{integer}]`
+   = note: required for `[{integer}]` to implement `Index<&usize>`
 help: dereference this index
    |
 LL |     let one_item_please: i32 = [1, 2, 3][*i];
diff --git a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
index 6583cabe184..f2eb651eaa4 100644
--- a/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
+++ b/src/test/ui/suggestions/suggest-imm-mut-trait-implementations.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `A: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:20:9
    |
 LL |     foo(a);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `A`
    |     |
    |     required by a bound introduced by this call
    |
@@ -22,7 +22,7 @@ error[E0277]: the trait bound `B: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:21:9
    |
 LL |     foo(b);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `B`
    |     |
    |     required by a bound introduced by this call
    |
@@ -40,7 +40,7 @@ error[E0277]: the trait bound `C: Trait` is not satisfied
   --> $DIR/suggest-imm-mut-trait-implementations.rs:22:9
    |
 LL |     foo(c);
-   |     --- ^ expected an implementor of trait `Trait`
+   |     --- ^ the trait `Trait` is not implemented for `C`
    |     |
    |     required by a bound introduced by this call
    |
diff --git a/src/test/ui/suggestions/suggest-remove-refs-1.stderr b/src/test/ui/suggestions/suggest-remove-refs-1.stderr
index 1083b2f9713..1a843f3f509 100644
--- a/src/test/ui/suggestions/suggest-remove-refs-1.stderr
+++ b/src/test/ui/suggestions/suggest-remove-refs-1.stderr
@@ -8,7 +8,7 @@ LL |     for (i, _) in &v.iter().enumerate() {
    |                   help: consider removing the leading `&`-reference
    |
    = help: the trait `Iterator` is not implemented for `&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required for `&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/suggest-remove-refs-2.stderr b/src/test/ui/suggestions/suggest-remove-refs-2.stderr
index 197b19a1bff..f39361d529f 100644
--- a/src/test/ui/suggestions/suggest-remove-refs-2.stderr
+++ b/src/test/ui/suggestions/suggest-remove-refs-2.stderr
@@ -8,7 +8,7 @@ LL |     for (i, _) in & & & & &v.iter().enumerate() {
    |                   help: consider removing 5 leading `&`-references
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/suggest-remove-refs-3.stderr b/src/test/ui/suggestions/suggest-remove-refs-3.stderr
index bb0cceac1db..4d07324273c 100644
--- a/src/test/ui/suggestions/suggest-remove-refs-3.stderr
+++ b/src/test/ui/suggestions/suggest-remove-refs-3.stderr
@@ -12,7 +12,7 @@ LL | |          .enumerate() {
    | |_____________________^ `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` is not an iterator
    |
    = help: the trait `Iterator` is not implemented for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>`
+   = note: required for `&&&&&Enumerate<std::slice::Iter<'_, {integer}>>` to implement `IntoIterator`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/suggestions/type-ascription-and-other-error.rs b/src/test/ui/suggestions/type-ascription-and-other-error.rs
new file mode 100644
index 00000000000..99ab2f3c858
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-and-other-error.rs
@@ -0,0 +1,6 @@
+fn main() {
+    not rust; //~ ERROR
+    let _ = 0: i32; // (error hidden by existing error)
+    #[cfg(FALSE)]
+    let _ = 0: i32; // (warning hidden by existing error)
+}
diff --git a/src/test/ui/suggestions/type-ascription-and-other-error.stderr b/src/test/ui/suggestions/type-ascription-and-other-error.stderr
new file mode 100644
index 00000000000..eadf634bb14
--- /dev/null
+++ b/src/test/ui/suggestions/type-ascription-and-other-error.stderr
@@ -0,0 +1,8 @@
+error: expected one of `!`, `.`, `::`, `;`, `?`, `{`, `}`, or an operator, found `rust`
+  --> $DIR/type-ascription-and-other-error.rs:2:9
+   |
+LL |     not rust;
+   |         ^^^^ expected one of 8 possible tokens
+
+error: aborting due to previous error
+
diff --git a/src/test/ui/traits/alias/cross-crate.stderr b/src/test/ui/traits/alias/cross-crate.stderr
index d0d00c97e83..ae9d7d0a9b4 100644
--- a/src/test/ui/traits/alias/cross-crate.stderr
+++ b/src/test/ui/traits/alias/cross-crate.stderr
@@ -5,7 +5,7 @@ LL |     use_alias::<Rc<u32>>();
    |                 ^^^^^^^ `Rc<u32>` cannot be sent between threads safely
    |
    = help: the trait `Send` is not implemented for `Rc<u32>`
-   = note: required because of the requirements on the impl of `SendSync` for `Rc<u32>`
+   = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
    |
@@ -19,7 +19,7 @@ LL |     use_alias::<Rc<u32>>();
    |                 ^^^^^^^ `Rc<u32>` cannot be shared between threads safely
    |
    = help: the trait `Sync` is not implemented for `Rc<u32>`
-   = note: required because of the requirements on the impl of `SendSync` for `Rc<u32>`
+   = note: required for `Rc<u32>` to implement `SendSync`
 note: required by a bound in `use_alias`
   --> $DIR/cross-crate.rs:10:17
    |
diff --git a/src/test/ui/traits/alias/self-in-const-generics.rs b/src/test/ui/traits/alias/self-in-const-generics.rs
new file mode 100644
index 00000000000..b0de8ccd678
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-const-generics.rs
@@ -0,0 +1,12 @@
+#![allow(incomplete_features)]
+#![feature(generic_const_exprs)]
+#![feature(trait_alias)]
+
+trait Bar<const N: usize> {}
+
+trait BB = Bar<{ 2 + 1 }>;
+
+fn foo(x: &dyn BB) {}
+//~^ ERROR the trait alias `BB` cannot be made into an object [E0038]
+
+fn main() {}
diff --git a/src/test/ui/traits/alias/self-in-const-generics.stderr b/src/test/ui/traits/alias/self-in-const-generics.stderr
new file mode 100644
index 00000000000..61cc217cfbc
--- /dev/null
+++ b/src/test/ui/traits/alias/self-in-const-generics.stderr
@@ -0,0 +1,11 @@
+error[E0038]: the trait alias `BB` cannot be made into an object
+  --> $DIR/self-in-const-generics.rs:9:16
+   |
+LL | fn foo(x: &dyn BB) {}
+   |                ^^
+   |
+   = note: it cannot use `Self` as a type parameter in a supertrait or `where`-clause
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/src/test/ui/traits/alias/self-in-generics.rs b/src/test/ui/traits/alias/self-in-generics.rs
index 6b99431f5bb..0bb6335f91e 100644
--- a/src/test/ui/traits/alias/self-in-generics.rs
+++ b/src/test/ui/traits/alias/self-in-generics.rs
@@ -1,3 +1,10 @@
+// astconv uses `FreshTy(0)` as a dummy `Self` type when instanciating trait objects.
+// This `FreshTy(0)` can leak into substs, causing ICEs in several places.
+// Using `save-analysis` triggers type-checking `f` that would be normally skipped
+// as `type_of` emitted an error.
+//
+// compile-flags: -Zsave-analysis
+
 #![feature(trait_alias)]
 
 pub trait SelfInput = Fn(&mut Self);
diff --git a/src/test/ui/traits/alias/self-in-generics.stderr b/src/test/ui/traits/alias/self-in-generics.stderr
index a1056872ea6..110d60e6e91 100644
--- a/src/test/ui/traits/alias/self-in-generics.stderr
+++ b/src/test/ui/traits/alias/self-in-generics.stderr
@@ -1,5 +1,5 @@
 error[E0038]: the trait alias `SelfInput` cannot be made into an object
-  --> $DIR/self-in-generics.rs:5:19
+  --> $DIR/self-in-generics.rs:12:19
    |
 LL | pub fn f(_f: &dyn SelfInput) {}
    |                   ^^^^^^^^^
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
index bfbbe7fd257..fa7a8a2a093 100644
--- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
+++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-1.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/check-trait-object-bounds-1.rs:12:5
+  --> $DIR/check-trait-object-bounds-1.rs:12:9
    |
 LL |     f::<dyn X<Y = str>>();
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+   |         ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `f`
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
index 46e8ce78874..4084f69a6f0 100644
--- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
+++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-2.stderr
@@ -1,8 +1,8 @@
 error[E0277]: expected a `FnOnce<(&i32,)>` closure, found `i32`
-  --> $DIR/check-trait-object-bounds-2.rs:13:5
+  --> $DIR/check-trait-object-bounds-2.rs:13:9
    |
 LL |     f::<dyn for<'x> X<'x, F = i32>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ expected an `FnOnce<(&i32,)>` closure, found `i32`
    |
    = help: the trait `for<'r> FnOnce<(&'r i32,)>` is not implemented for `i32`
 note: required by a bound in `f`
diff --git a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
index 3ca36d5d2ff..4891ee9c29f 100644
--- a/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
+++ b/src/test/ui/traits/associated_type_bound/check-trait-object-bounds-4.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `str: Clone` is not satisfied
-  --> $DIR/check-trait-object-bounds-4.rs:15:5
+  --> $DIR/check-trait-object-bounds-4.rs:15:9
    |
 LL |     f::<dyn X<Y = str>>();
-   |     ^^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
+   |         ^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `str`
    |
    = help: the trait `Clone` is implemented for `String`
 note: required by a bound in `f`
diff --git a/src/test/ui/traits/bad-method-typaram-kind.stderr b/src/test/ui/traits/bad-method-typaram-kind.stderr
index 8befa4c5f73..56acfbe80d0 100644
--- a/src/test/ui/traits/bad-method-typaram-kind.stderr
+++ b/src/test/ui/traits/bad-method-typaram-kind.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `T` cannot be sent between threads safely
-  --> $DIR/bad-method-typaram-kind.rs:2:7
+  --> $DIR/bad-method-typaram-kind.rs:2:13
    |
 LL |     1.bar::<T>();
-   |       ^^^ `T` cannot be sent between threads safely
+   |             ^ `T` cannot be sent between threads safely
    |
 note: required by a bound in `Bar::bar`
   --> $DIR/bad-method-typaram-kind.rs:6:14
diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
index 1d234518056..f9a93476411 100644
--- a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
+++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.rs
@@ -2,10 +2,9 @@ fn strip_lf(s: &str) -> &str {
     s.strip_suffix(b'\n').unwrap_or(s)
     //~^ ERROR expected a `FnMut<(char,)>` closure, found `u8`
     //~| NOTE expected an `FnMut<(char,)>` closure, found `u8`
-    //~| NOTE required by a bound introduced by this call
     //~| HELP the trait `FnMut<(char,)>` is not implemented for `u8`
     //~| HELP the following other types implement trait `Pattern<'a>`:
-    //~| NOTE required because of the requirements on the impl of `Pattern<'_>` for `u8`
+    //~| NOTE required for `u8` to implement `Pattern<'_>`
 
 }
 
diff --git a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
index 6ce57b6263e..ce9ab2d811a 100644
--- a/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
+++ b/src/test/ui/traits/bound/assoc-fn-bound-root-obligation.stderr
@@ -1,10 +1,8 @@
 error[E0277]: expected a `FnMut<(char,)>` closure, found `u8`
-  --> $DIR/assoc-fn-bound-root-obligation.rs:2:20
+  --> $DIR/assoc-fn-bound-root-obligation.rs:2:7
    |
 LL |     s.strip_suffix(b'\n').unwrap_or(s)
-   |       ------------ ^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
-   |       |
-   |       required by a bound introduced by this call
+   |       ^^^^^^^^^^^^ expected an `FnMut<(char,)>` closure, found `u8`
    |
    = help: the trait `FnMut<(char,)>` is not implemented for `u8`
    = help: the following other types implement trait `Pattern<'a>`:
@@ -15,7 +13,7 @@ LL |     s.strip_suffix(b'\n').unwrap_or(s)
              &'c &'b str
              [char; N]
              char
-   = note: required because of the requirements on the impl of `Pattern<'_>` for `u8`
+   = note: required for `u8` to implement `Pattern<'_>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/bound/on-structs-and-enums-locals.rs b/src/test/ui/traits/bound/on-structs-and-enums-locals.rs
index 21c0ce80f8a..60ba343bb0a 100644
--- a/src/test/ui/traits/bound/on-structs-and-enums-locals.rs
+++ b/src/test/ui/traits/bound/on-structs-and-enums-locals.rs
@@ -8,8 +8,8 @@ struct Foo<T:Trait> {
 
 fn main() {
     let foo = Foo {
-    //~^ ERROR E0277
         x: 3
+    //~^ ERROR E0277
     };
 
     let baz: Foo<usize> = loop { };
diff --git a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr
index c9068a27002..20bbe69c059 100644
--- a/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr
+++ b/src/test/ui/traits/bound/on-structs-and-enums-locals.stderr
@@ -11,10 +11,10 @@ LL | struct Foo<T:Trait> {
    |              ^^^^^ required by this bound in `Foo`
 
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-locals.rs:10:15
+  --> $DIR/on-structs-and-enums-locals.rs:11:12
    |
-LL |     let foo = Foo {
-   |               ^^^ the trait `Trait` is not implemented for `{integer}`
+LL |         x: 3
+   |            ^ the trait `Trait` is not implemented for `{integer}`
    |
 note: required by a bound in `Foo`
   --> $DIR/on-structs-and-enums-locals.rs:5:14
diff --git a/src/test/ui/traits/bound/on-structs-and-enums-xc1.rs b/src/test/ui/traits/bound/on-structs-and-enums-xc1.rs
index 8156868e048..5ef35b513e0 100644
--- a/src/test/ui/traits/bound/on-structs-and-enums-xc1.rs
+++ b/src/test/ui/traits/bound/on-structs-and-enums-xc1.rs
@@ -6,8 +6,8 @@ use on_structs_and_enums_xc::{Bar, Foo, Trait};
 
 fn main() {
     let foo = Foo {
-    //~^ ERROR E0277
         x: 3
+    //~^ ERROR E0277
     };
     let bar: Bar<f64> = return;
     //~^ ERROR E0277
diff --git a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr
index f4cc64af94f..3fb5decb723 100644
--- a/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr
+++ b/src/test/ui/traits/bound/on-structs-and-enums-xc1.stderr
@@ -11,10 +11,10 @@ LL | pub enum Bar<T:Trait> {
    |                ^^^^^ required by this bound in `Bar`
 
 error[E0277]: the trait bound `{integer}: Trait` is not satisfied
-  --> $DIR/on-structs-and-enums-xc1.rs:8:15
+  --> $DIR/on-structs-and-enums-xc1.rs:9:12
    |
-LL |     let foo = Foo {
-   |               ^^^ the trait `Trait` is not implemented for `{integer}`
+LL |         x: 3
+   |            ^ the trait `Trait` is not implemented for `{integer}`
    |
 note: required by a bound in `Foo`
   --> $DIR/auxiliary/on_structs_and_enums_xc.rs:5:18
diff --git a/src/test/ui/traits/cycle-cache-err-60010.stderr b/src/test/ui/traits/cycle-cache-err-60010.stderr
index 859403f202f..2478eb35422 100644
--- a/src/test/ui/traits/cycle-cache-err-60010.stderr
+++ b/src/test/ui/traits/cycle-cache-err-60010.stderr
@@ -17,12 +17,12 @@ note: required because it appears within the type `RootDatabase`
    |
 LL | struct RootDatabase {
    |        ^^^^^^^^^^^^
-note: required because of the requirements on the impl of `SourceDatabase` for `RootDatabase`
+note: required for `RootDatabase` to implement `SourceDatabase`
   --> $DIR/cycle-cache-err-60010.rs:44:9
    |
 LL | impl<T> SourceDatabase for T
    |         ^^^^^^^^^^^^^^     ^
-note: required because of the requirements on the impl of `Query<RootDatabase>` for `ParseQuery`
+note: required for `ParseQuery` to implement `Query<RootDatabase>`
   --> $DIR/cycle-cache-err-60010.rs:37:10
    |
 LL | impl<DB> Query<DB> for ParseQuery
diff --git a/src/test/ui/traits/inductive-overflow/lifetime.rs b/src/test/ui/traits/inductive-overflow/lifetime.rs
index c36c17d3d24..004e477374a 100644
--- a/src/test/ui/traits/inductive-overflow/lifetime.rs
+++ b/src/test/ui/traits/inductive-overflow/lifetime.rs
@@ -28,5 +28,5 @@ fn main() {
     is_send::<X<C<'static>>>();
     //~^ ERROR overflow evaluating
     //~| 3 redundant requirements hidden
-    //~| required because of
+    //~| required for
 }
diff --git a/src/test/ui/traits/inductive-overflow/lifetime.stderr b/src/test/ui/traits/inductive-overflow/lifetime.stderr
index 9ca615aacee..b72d53bddbc 100644
--- a/src/test/ui/traits/inductive-overflow/lifetime.stderr
+++ b/src/test/ui/traits/inductive-overflow/lifetime.stderr
@@ -4,13 +4,13 @@ error[E0275]: overflow evaluating the requirement `X<C<'_>>: NotAuto`
 LL |     is_send::<X<C<'static>>>();
    |     ^^^^^^^^^^^^^^^^^^^^^^^^
    |
-note: required because of the requirements on the impl of `NotAuto` for `Box<X<C<'_>>>`
+note: required for `Box<X<C<'_>>>` to implement `NotAuto`
   --> $DIR/lifetime.rs:18:18
    |
 LL | impl<T: NotAuto> NotAuto for Box<T> {}
    |                  ^^^^^^^     ^^^^^^
    = note: 3 redundant requirements hidden
-   = note: required because of the requirements on the impl of `NotAuto` for `X<C<'static>>`
+   = note: required for `X<C<'static>>` to implement `NotAuto`
 note: required by a bound in `is_send`
   --> $DIR/lifetime.rs:22:15
    |
diff --git a/src/test/ui/traits/inductive-overflow/simultaneous.stderr b/src/test/ui/traits/inductive-overflow/simultaneous.stderr
index 230c2638c50..09930e60efe 100644
--- a/src/test/ui/traits/inductive-overflow/simultaneous.stderr
+++ b/src/test/ui/traits/inductive-overflow/simultaneous.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `{integer}: Tweedledum`
 LL |     is_ee(4);
    |     ^^^^^
    |
-note: required because of the requirements on the impl of `Combo` for `{integer}`
+note: required for `{integer}` to implement `Combo`
   --> $DIR/simultaneous.rs:11:34
    |
 LL | impl<T: Tweedledee + Tweedledum> Combo for T {}
diff --git a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
index d7697dcc640..3ec288d1382 100644
--- a/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
+++ b/src/test/ui/traits/inductive-overflow/supertrait-auto-trait.stderr
@@ -14,7 +14,7 @@ LL |     let (a, b) = copy(NoClone);
    |                  |
    |                  required by a bound introduced by this call
    |
-note: required because of the requirements on the impl of `Magic` for `NoClone`
+note: required for `NoClone` to implement `Magic`
   --> $DIR/supertrait-auto-trait.rs:8:12
    |
 LL | auto trait Magic: Copy {}
diff --git a/src/test/ui/traits/inductive-overflow/supertrait.stderr b/src/test/ui/traits/inductive-overflow/supertrait.stderr
index 95325a534f5..4b862cf79ce 100644
--- a/src/test/ui/traits/inductive-overflow/supertrait.stderr
+++ b/src/test/ui/traits/inductive-overflow/supertrait.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `NoClone: Magic`
 LL |     let (a, b) = copy(NoClone);
    |                  ^^^^
    |
-note: required because of the requirements on the impl of `Magic` for `NoClone`
+note: required for `NoClone` to implement `Magic`
   --> $DIR/supertrait.rs:5:16
    |
 LL | impl<T: Magic> Magic for T {}
diff --git a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
index cab0ccdf710..656e0d0bf26 100644
--- a/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
+++ b/src/test/ui/traits/inheritance/repeated-supertrait-ambig.stderr
@@ -1,18 +1,22 @@
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:26:7
+  --> $DIR/repeated-supertrait-ambig.rs:26:15
    |
 LL |     c.same_as(22)
-   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |       ------- ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |       |
+   |       required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
              <i64 as CompareTo<u64>>
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:30:7
+  --> $DIR/repeated-supertrait-ambig.rs:30:15
    |
 LL |     c.same_as(22)
-   |       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |       ------- ^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |       |
+   |       required by a bound introduced by this call
    |
 help: consider further restricting this bound
    |
@@ -20,20 +24,24 @@ LL | fn with_trait<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
 
 error[E0277]: the trait bound `dyn CompareToInts: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:34:5
+  --> $DIR/repeated-supertrait-ambig.rs:34:37
    |
 LL |     <dyn CompareToInts>::same_as(c, 22)
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |     ----------------------------    ^^ the trait `CompareTo<i32>` is not implemented for `dyn CompareToInts`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
              <i64 as CompareTo<u64>>
 
 error[E0277]: the trait bound `C: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:38:5
+  --> $DIR/repeated-supertrait-ambig.rs:38:27
    |
 LL |     CompareTo::same_as(c, 22)
-   |     ^^^^^^^^^^^^^^^^^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |     ------------------    ^^ the trait `CompareTo<i32>` is not implemented for `C`
+   |     |
+   |     required by a bound introduced by this call
    |
 help: consider further restricting this bound
    |
@@ -41,10 +49,12 @@ LL | fn with_ufcs2<C:CompareToInts + CompareTo<i32>>(c: &C) -> bool {
    |                               ++++++++++++++++
 
 error[E0277]: the trait bound `i64: CompareTo<i32>` is not satisfied
-  --> $DIR/repeated-supertrait-ambig.rs:42:23
+  --> $DIR/repeated-supertrait-ambig.rs:42:31
    |
 LL |     assert_eq!(22_i64.same_as(22), true);
-   |                       ^^^^^^^ the trait `CompareTo<i32>` is not implemented for `i64`
+   |                       ------- ^^ the trait `CompareTo<i32>` is not implemented for `i64`
+   |                       |
+   |                       required by a bound introduced by this call
    |
    = help: the following other types implement trait `CompareTo<T>`:
              <i64 as CompareTo<i64>>
diff --git a/src/test/ui/traits/issue-18400.stderr b/src/test/ui/traits/issue-18400.stderr
index 92e0f60079f..4394e6f7e05 100644
--- a/src/test/ui/traits/issue-18400.stderr
+++ b/src/test/ui/traits/issue-18400.stderr
@@ -5,13 +5,13 @@ LL |     0.contains(bits);
    |       ^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_18400`)
-note: required because of the requirements on the impl of `Set<&[_]>` for `{integer}`
+note: required for `{integer}` to implement `Set<&[_]>`
   --> $DIR/issue-18400.rs:6:16
    |
 LL | impl<'a, T, S> Set<&'a [T]> for S where
    |                ^^^^^^^^^^^^     ^
    = note: 128 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>` for `{integer}`
+   = note: required for `{integer}` to implement `Set<&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[&[_]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]]>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-20692.stderr b/src/test/ui/traits/issue-20692.stderr
index 1d7f252e556..2028994cdaa 100644
--- a/src/test/ui/traits/issue-20692.stderr
+++ b/src/test/ui/traits/issue-20692.stderr
@@ -27,7 +27,7 @@ LL | trait Array: Sized + Copy {}
    |       |      |
    |       |      ...because it requires `Self: Sized`
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Array>` for `&T`
+   = note: required for `&T` to implement `CoerceUnsized<&dyn Array>`
    = note: required by cast to type `&dyn Array`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/traits/issue-38604.stderr b/src/test/ui/traits/issue-38604.stderr
index d41488c15f7..50d6fb05465 100644
--- a/src/test/ui/traits/issue-38604.stderr
+++ b/src/test/ui/traits/issue-38604.stderr
@@ -25,7 +25,7 @@ LL | trait Foo where u32: Q<Self> {
    |       ---            ^^^^^^^ ...because it uses `Self` as a type parameter
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Foo>>` for `Box<()>`
+   = note: required for `Box<()>` to implement `CoerceUnsized<Box<dyn Foo>>`
    = note: required by cast to type `Box<dyn Foo>`
 
 error: aborting due to 2 previous errors
diff --git a/src/test/ui/traits/issue-71036.rs b/src/test/ui/traits/issue-71036.rs
index 3d2df6fe997..69eed0c0462 100644
--- a/src/test/ui/traits/issue-71036.rs
+++ b/src/test/ui/traits/issue-71036.rs
@@ -12,6 +12,6 @@ impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for Foo<'
 //~^ ERROR the trait bound `&'a T: Unsize<&'a U>` is not satisfied
 //~| NOTE the trait `Unsize<&'a U>` is not implemented for `&'a T`
 //~| NOTE all implementations of `Unsize` are provided automatically by the compiler
-//~| NOTE required because of the requirements on the impl
+//~| NOTE required for
 
 fn main() {}
diff --git a/src/test/ui/traits/issue-71036.stderr b/src/test/ui/traits/issue-71036.stderr
index 3ee6db40e87..79eb7a2ae8b 100644
--- a/src/test/ui/traits/issue-71036.stderr
+++ b/src/test/ui/traits/issue-71036.stderr
@@ -5,7 +5,7 @@ LL | impl<'a, T: ?Sized + Unsize<U>, U: ?Sized> DispatchFromDyn<Foo<'a, U>> for
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Unsize<&'a U>` is not implemented for `&'a T`
    |
    = note: all implementations of `Unsize` are provided automatically by the compiler, see <https://doc.rust-lang.org/stable/std/marker/trait.Unsize.html> for more information
-   = note: required because of the requirements on the impl of `DispatchFromDyn<&'a &'a U>` for `&'a &'a T`
+   = note: required for `&'a &'a T` to implement `DispatchFromDyn<&'a &'a U>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/issue-71136.stderr b/src/test/ui/traits/issue-71136.stderr
index 62a2a64ed14..f541733929d 100644
--- a/src/test/ui/traits/issue-71136.stderr
+++ b/src/test/ui/traits/issue-71136.stderr
@@ -7,7 +7,7 @@ LL | struct FooHolster {
 LL |     the_foos: Vec<Foo>,
    |     ^^^^^^^^^^^^^^^^^^ the trait `Clone` is not implemented for `Foo`
    |
-   = note: required because of the requirements on the impl of `Clone` for `Vec<Foo>`
+   = note: required for `Vec<Foo>` to implement `Clone`
    = note: this error originates in the derive macro `Clone` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: consider annotating `Foo` with `#[derive(Clone)]`
    |
diff --git a/src/test/ui/traits/issue-77982.stderr b/src/test/ui/traits/issue-77982.stderr
index 2b832e27c52..e210f11b3e0 100644
--- a/src/test/ui/traits/issue-77982.stderr
+++ b/src/test/ui/traits/issue-77982.stderr
@@ -2,7 +2,9 @@ error[E0283]: type annotations needed
   --> $DIR/issue-77982.rs:8:10
    |
 LL |     opts.get(opt.as_ref());
-   |          ^^^ cannot infer type of the type parameter `Q` declared on the associated function `get`
+   |          ^^^ ------------ type must be known at this point
+   |          |
+   |          cannot infer type of the type parameter `Q` declared on the associated function `get`
    |
    = note: multiple `impl`s satisfying `String: Borrow<_>` found in the following crates: `alloc`, `core`:
            - impl Borrow<str> for String;
@@ -13,7 +15,7 @@ note: required by a bound in `HashMap::<K, V, S>::get`
    |
 LL |         K: Borrow<Q>,
    |            ^^^^^^^^^ required by this bound in `HashMap::<K, V, S>::get`
-help: consider specifying the type argument in the function call
+help: consider specifying the generic argument
    |
 LL |     opts.get::<Q>(opt.as_ref());
    |             +++++
@@ -42,7 +44,7 @@ error[E0283]: type annotations needed
 LL |     let ips: Vec<_> = (0..100_000).map(|_| u32::from(0u32.into())).collect();
    |                                            ---------      ^^^^
    |                                            |
-   |                                            type must be known at this point
+   |                                            required by a bound introduced by this call
    |
    = note: multiple `impl`s satisfying `u32: From<_>` found in the following crates: `core`, `std`:
            - impl From<Ipv4Addr> for u32;
diff --git a/src/test/ui/traits/issue-82830.stderr b/src/test/ui/traits/issue-82830.stderr
index f863143c738..6a597a40215 100644
--- a/src/test/ui/traits/issue-82830.stderr
+++ b/src/test/ui/traits/issue-82830.stderr
@@ -4,7 +4,7 @@ error[E0275]: overflow evaluating the requirement `P: Sized`
 LL |     t: MaybeBox<P>,
    |        ^^^^^^^^^^^
    |
-note: required because of the requirements on the impl of `A<P, Box<P>>` for `P`
+note: required for `P` to implement `A<P, Box<P>>`
   --> $DIR/issue-82830.rs:10:12
    |
 LL | impl<Y, N> A<Y, N> for P {
diff --git a/src/test/ui/traits/issue-91594.stderr b/src/test/ui/traits/issue-91594.stderr
index f2b3de13beb..5fcd090a834 100644
--- a/src/test/ui/traits/issue-91594.stderr
+++ b/src/test/ui/traits/issue-91594.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `Foo: HasComponent<()>` is not satisfied
-  --> $DIR/issue-91594.rs:10:6
+  --> $DIR/issue-91594.rs:10:1
    |
 LL | impl HasComponent<<Foo as Component<Foo>>::Interface> for Foo {}
-   |      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `HasComponent<()>` is not implemented for `Foo`
    |
    = help: the trait `HasComponent<<Foo as Component<Foo>>::Interface>` is implemented for `Foo`
-note: required because of the requirements on the impl of `Component<Foo>` for `Foo`
+note: required for `Foo` to implement `Component<Foo>`
   --> $DIR/issue-91594.rs:13:27
    |
 LL | impl<M: HasComponent<()>> Component<M> for Foo {
diff --git a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
index f5d6d72afc2..6acf2fe65ce 100644
--- a/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/src/test/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -15,9 +15,9 @@ LL |       recurse(IteratorOfWrapped(elements).map(|t| t.0))
 error[E0275]: overflow evaluating the requirement `(): Sized`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "512"]` attribute to your crate (`issue_91949_hangs_on_recursion`)
-   = note: required because of the requirements on the impl of `Iterator` for `std::iter::Empty<()>`
+   = note: required for `std::iter::Empty<()>` to implement `Iterator`
    = note: 171 redundant requirements hidden
-   = note: required because of the requirements on the impl of `Iterator` for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>, [closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48]>>` to implement `Iterator`
 
 error: aborting due to previous error; 1 warning emitted
 
diff --git a/src/test/ui/traits/issue-97576.stderr b/src/test/ui/traits/issue-97576.stderr
index bdee073d6e3..146d38d076a 100644
--- a/src/test/ui/traits/issue-97576.stderr
+++ b/src/test/ui/traits/issue-97576.stderr
@@ -1,10 +1,12 @@
 error[E0277]: the trait bound `String: From<impl ToString>` is not satisfied
-  --> $DIR/issue-97576.rs:8:22
+  --> $DIR/issue-97576.rs:8:18
    |
 LL |             bar: bar.into(),
-   |                      ^^^^ the trait `From<impl ToString>` is not implemented for `String`
+   |                  ^^^ ---- required by a bound introduced by this call
+   |                  |
+   |                  the trait `From<impl ToString>` is not implemented for `String`
    |
-   = note: required because of the requirements on the impl of `Into<String>` for `impl ToString`
+   = note: required for `impl ToString` to implement `Into<String>`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
index cbec3593421..6e6172eea47 100644
--- a/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
+++ b/src/test/ui/traits/multidispatch-convert-ambig-dest.stderr
@@ -13,7 +13,9 @@ error[E0283]: type annotations needed
   --> $DIR/multidispatch-convert-ambig-dest.rs:26:5
    |
 LL |     test(22, std::default::Default::default());
-   |     ^^^^ cannot infer type of the type parameter `U` declared on the function `test`
+   |     ^^^^     -------------------------------- type must be known at this point
+   |     |
+   |     cannot infer type of the type parameter `U` declared on the function `test`
    |
 note: multiple `impl`s satisfying `i32: Convert<_>` found
   --> $DIR/multidispatch-convert-ambig-dest.rs:8:1
@@ -30,10 +32,10 @@ LL | fn test<T,U>(_: T, _: U)
    |    ---- required by a bound in this
 LL | where T : Convert<U>
    |           ^^^^^^^^^^ required by this bound in `test`
-help: consider specifying the type arguments in the function call
+help: consider specifying the generic arguments
    |
-LL |     test::<T, U>(22, std::default::Default::default());
-   |         ++++++++
+LL |     test::<i32, U>(22, std::default::Default::default());
+   |         ++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
index c5d4ccc2fcd..41fc3600fcd 100644
--- a/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
+++ b/src/test/ui/traits/negative-impls/negated-auto-traits-error.stderr
@@ -61,12 +61,12 @@ error[E0277]: `dummy2::TestType` cannot be sent between threads safely
   --> $DIR/negated-auto-traits-error.rs:48:13
    |
 LL |     is_send(Box::new(TestType));
-   |     ------- ^^^^^^^^^^^^^^^^^^ expected an implementor of trait `Send`
+   |     ------- ^^^^^^^^^^^^^^^^^^ the trait `Send` is not implemented for `Unique<dummy2::TestType>`
    |     |
    |     required by a bound introduced by this call
    |
    = note: the trait bound `Unique<dummy2::TestType>: Send` is not satisfied
-   = note: required because of the requirements on the impl of `Send` for `Unique<dummy2::TestType>`
+   = note: required for `Unique<dummy2::TestType>` to implement `Send`
    = note: required because it appears within the type `Box<dummy2::TestType>`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -92,7 +92,7 @@ note: required because it appears within the type `Outer2<dummy3::TestType>`
    |
 LL | struct Outer2<T>(T);
    |        ^^^^^^
-   = note: required because of the requirements on the impl of `Send` for `Unique<Outer2<dummy3::TestType>>`
+   = note: required for `Unique<Outer2<dummy3::TestType>>` to implement `Send`
    = note: required because it appears within the type `Box<Outer2<dummy3::TestType>>`
 note: required by a bound in `is_send`
   --> $DIR/negated-auto-traits-error.rs:16:15
@@ -109,7 +109,7 @@ LL |     is_sync(Outer2(TestType));
    |     required by a bound introduced by this call
    |
    = help: the trait `Send` is not implemented for `main::TestType`
-note: required because of the requirements on the impl of `Sync` for `Outer2<main::TestType>`
+note: required for `Outer2<main::TestType>` to implement `Sync`
   --> $DIR/negated-auto-traits-error.rs:14:22
    |
 LL | unsafe impl<T: Send> Sync for Outer2<T> {}
diff --git a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
index 75d45d9052b..53178328c56 100644
--- a/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
+++ b/src/test/ui/traits/not-suggest-non-existing-fully-qualified-path.stderr
@@ -22,7 +22,7 @@ LL | impl I<i32> for B {}
    | ^^^^^^^^^^^^^^^^^
 LL | impl I<u32> for B {}
    | ^^^^^^^^^^^^^^^^^
-note: required because of the requirements on the impl of `V<_>` for `A<B>`
+note: required for `A<B>` to implement `V<_>`
   --> $DIR/not-suggest-non-existing-fully-qualified-path.rs:12:12
    |
 LL | impl<T, U> V<U> for A<T>
diff --git a/src/test/ui/traits/object/safety.stderr b/src/test/ui/traits/object/safety.stderr
index cf534d984c2..dc18adeafc7 100644
--- a/src/test/ui/traits/object/safety.stderr
+++ b/src/test/ui/traits/object/safety.stderr
@@ -11,7 +11,7 @@ LL | trait Tr {
    |       -- this trait cannot be made into an object...
 LL |     fn foo();
    |        ^^^ ...because associated function `foo` has no `self` parameter
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Tr>` for `&St`
+   = note: required for `&St` to implement `CoerceUnsized<&dyn Tr>`
    = note: required by cast to type `&dyn Tr`
 help: consider turning `foo` into a method by giving it a `&self` argument
    |
diff --git a/src/test/ui/traits/suggest-deferences/issue-39029.stderr b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
index 5c324cd38a3..eb2b88059d4 100644
--- a/src/test/ui/traits/suggest-deferences/issue-39029.stderr
+++ b/src/test/ui/traits/suggest-deferences/issue-39029.stderr
@@ -2,18 +2,20 @@ error[E0277]: the trait bound `NoToSocketAddrs: ToSocketAddrs` is not satisfied
   --> $DIR/issue-39029.rs:16:37
    |
 LL |     let _errors = TcpListener::bind(&bad);
-   |                   ----------------- ^^^^
-   |                   |                 |
-   |                   |                 the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
-   |                   |                 help: consider dereferencing here: `&*bad`
+   |                   ----------------- ^^^^ the trait `ToSocketAddrs` is not implemented for `NoToSocketAddrs`
+   |                   |
    |                   required by a bound introduced by this call
    |
-   = note: required because of the requirements on the impl of `ToSocketAddrs` for `&NoToSocketAddrs`
+   = note: required for `&NoToSocketAddrs` to implement `ToSocketAddrs`
 note: required by a bound in `TcpListener::bind`
   --> $SRC_DIR/std/src/net/tcp.rs:LL:COL
    |
 LL |     pub fn bind<A: ToSocketAddrs>(addr: A) -> io::Result<TcpListener> {
    |                    ^^^^^^^^^^^^^ required by this bound in `TcpListener::bind`
+help: consider dereferencing here
+   |
+LL |     let _errors = TcpListener::bind(&*bad);
+   |                                      +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/suggest-deferences/issue-62530.stderr b/src/test/ui/traits/suggest-deferences/issue-62530.stderr
index d129328dae8..e47ae0b65af 100644
--- a/src/test/ui/traits/suggest-deferences/issue-62530.stderr
+++ b/src/test/ui/traits/suggest-deferences/issue-62530.stderr
@@ -2,10 +2,8 @@ error[E0277]: the trait bound `&String: SomeTrait` is not satisfied
   --> $DIR/issue-62530.rs:13:26
    |
 LL |     takes_type_parameter(&string);  // Error
-   |     -------------------- ^^^^^^^
-   |     |                    |
-   |     |                    the trait `SomeTrait` is not implemented for `&String`
-   |     |                    help: consider dereferencing here: `&*string`
+   |     -------------------- ^^^^^^^ the trait `SomeTrait` is not implemented for `&String`
+   |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `takes_type_parameter`
@@ -13,6 +11,10 @@ note: required by a bound in `takes_type_parameter`
    |
 LL | fn takes_type_parameter<T>(_x: T) where T: SomeTrait {}
    |                                            ^^^^^^^^^ required by this bound in `takes_type_parameter`
+help: consider dereferencing here
+   |
+LL |     takes_type_parameter(&*string);  // Error
+   |                           +
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/suggest-deferences/multiple-0.stderr b/src/test/ui/traits/suggest-deferences/multiple-0.stderr
index efb3c7d123f..6a4d4b8d521 100644
--- a/src/test/ui/traits/suggest-deferences/multiple-0.stderr
+++ b/src/test/ui/traits/suggest-deferences/multiple-0.stderr
@@ -2,10 +2,8 @@ error[E0277]: the trait bound `&Baz: Happy` is not satisfied
   --> $DIR/multiple-0.rs:34:9
    |
 LL |     foo(&baz);
-   |     --- ^^^^
-   |     |   |
-   |     |   the trait `Happy` is not implemented for `&Baz`
-   |     |   help: consider dereferencing here: `&***baz`
+   |     --- ^^^^ the trait `Happy` is not implemented for `&Baz`
+   |     |
    |     required by a bound introduced by this call
    |
 note: required by a bound in `foo`
@@ -13,6 +11,10 @@ note: required by a bound in `foo`
    |
 LL | fn foo<T>(_: T) where T: Happy {}
    |                          ^^^^^ required by this bound in `foo`
+help: consider dereferencing here
+   |
+LL |     foo(&***baz);
+   |          +++
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/traits/suggest-deferences/root-obligation.stderr b/src/test/ui/traits/suggest-deferences/root-obligation.stderr
index 16e03e79c75..76663ace7ed 100644
--- a/src/test/ui/traits/suggest-deferences/root-obligation.stderr
+++ b/src/test/ui/traits/suggest-deferences/root-obligation.stderr
@@ -7,8 +7,8 @@ LL |         .filter(|c| "aeiou".contains(c))
    |                             required by a bound introduced by this call
    |
    = help: the trait `Fn<(char,)>` is not implemented for `char`
-   = note: required because of the requirements on the impl of `FnOnce<(char,)>` for `&char`
-   = note: required because of the requirements on the impl of `Pattern<'_>` for `&char`
+   = note: required for `&char` to implement `FnOnce<(char,)>`
+   = note: required for `&char` to implement `Pattern<'_>`
 note: required by a bound in `core::str::<impl str>::contains`
   --> $SRC_DIR/core/src/str/mod.rs:LL:COL
    |
diff --git a/src/test/ui/traits/suggest-where-clause.stderr b/src/test/ui/traits/suggest-where-clause.stderr
index d4d9b496747..747e2477b9c 100644
--- a/src/test/ui/traits/suggest-where-clause.stderr
+++ b/src/test/ui/traits/suggest-where-clause.stderr
@@ -19,13 +19,13 @@ LL + fn check<T: Iterator, U>() {
    |
 
 error[E0277]: the size for values of type `U` cannot be known at compilation time
-  --> $DIR/suggest-where-clause.rs:10:5
+  --> $DIR/suggest-where-clause.rs:10:20
    |
 LL | fn check<T: Iterator, U: ?Sized>() {
    |                       - this type parameter needs to be `std::marker::Sized`
 ...
 LL |     mem::size_of::<Misc<U>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |                    ^^^^^^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `Misc<U>`
   --> $DIR/suggest-where-clause.rs:3:8
diff --git a/src/test/ui/traits/test-2.stderr b/src/test/ui/traits/test-2.stderr
index 77ea4e4e974..eaa20b0b4f4 100644
--- a/src/test/ui/traits/test-2.stderr
+++ b/src/test/ui/traits/test-2.stderr
@@ -76,7 +76,7 @@ LL | trait bar { fn dup(&self) -> Self; fn blah<X>(&self); }
    |       this trait cannot be made into an object...
    = help: consider moving `dup` to another trait
    = help: consider moving `blah` to another trait
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn bar>>` for `Box<{integer}>`
+   = note: required for `Box<{integer}>` to implement `CoerceUnsized<Box<dyn bar>>`
    = note: required by cast to type `Box<dyn bar>`
 
 error: aborting due to 5 previous errors
diff --git a/src/test/ui/transmutability/references.stderr b/src/test/ui/transmutability/references.stderr
index b1359ea5865..17ffcf64177 100644
--- a/src/test/ui/transmutability/references.stderr
+++ b/src/test/ui/transmutability/references.stderr
@@ -1,8 +1,8 @@
 error[E0277]: `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
-  --> $DIR/references.rs:19:37
+  --> $DIR/references.rs:19:52
    |
 LL |     assert::is_maybe_transmutable::<&'static Unit, &'static Unit>();
-   |                                     ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
+   |                                                    ^^^^^^^^^^^^^ `&'static Unit` cannot be safely transmuted into `&'static Unit` in the defining scope of `assert::Context`.
    |
    = help: the trait `BikeshedIntrinsicFrom<&'static Unit, assert::Context, true, true, true, true>` is not implemented for `&'static Unit`
 note: required by a bound in `is_maybe_transmutable`
diff --git a/src/test/ui/try-block/try-block-bad-type.stderr b/src/test/ui/try-block/try-block-bad-type.stderr
index f9906713f84..e11c3f81003 100644
--- a/src/test/ui/try-block/try-block-bad-type.stderr
+++ b/src/test/ui/try-block/try-block-bad-type.stderr
@@ -6,7 +6,7 @@ LL |         Err("")?;
    |
    = note: the question mark operation (`?`) implicitly performs a conversion on the error value using the `From` trait
    = help: the trait `From<Infallible>` is implemented for `TryFromSliceError`
-   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, &str>>` for `Result<u32, TryFromSliceError>`
+   = note: required for `Result<u32, TryFromSliceError>` to implement `FromResidual<Result<Infallible, &str>>`
 
 error[E0271]: type mismatch resolving `<Result<i32, i32> as Try>::Output == &str`
   --> $DIR/try-block-bad-type.rs:12:9
diff --git a/src/test/ui/try-trait/bad-interconversion.stderr b/src/test/ui/try-trait/bad-interconversion.stderr
index 1dbf3ebdf82..529f5f16c8f 100644
--- a/src/test/ui/try-trait/bad-interconversion.stderr
+++ b/src/test/ui/try-trait/bad-interconversion.stderr
@@ -17,7 +17,7 @@ LL |     Ok(Err(123_i32)?)
              <f64 as From<i32>>
              <f64 as From<i8>>
            and 67 others
-   = note: required because of the requirements on the impl of `FromResidual<Result<Infallible, i32>>` for `Result<u64, u8>`
+   = note: required for `Result<u64, u8>` to implement `FromResidual<Result<Infallible, i32>>`
 
 error[E0277]: the `?` operator can only be used on `Result`s, not `Option`s, in a function that returns `Result`
   --> $DIR/bad-interconversion.rs:11:12
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
index 2768f0c3ab7..586ea82342a 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
@@ -4,7 +4,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (t, u)
    |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+   = note: required for `(T, U)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
@@ -16,7 +16,7 @@ error[E0277]: `U` doesn't implement `Debug`
 LL |     (t, u)
    |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, U)`
+   = note: required for `(T, U)` to implement `Debug`
 help: consider restricting type parameter `U`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
@@ -28,7 +28,7 @@ error[E0277]: `U` doesn't implement `Debug`
 LL |     (u, t)
    |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(U, T)`
+   = note: required for `(U, T)` to implement `Debug`
 help: consider restricting type parameter `U`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
@@ -40,7 +40,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (u, t)
    |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(U, T)`
+   = note: required for `(U, T)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
index c1712ca2efb..cb162d382b6 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
@@ -4,7 +4,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (t, t)
    |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, T)`
+   = note: required for `(T, T)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
@@ -16,7 +16,7 @@ error[E0277]: `U` doesn't implement `Debug`
 LL |     (u, t)
    |     ^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(U, T)`
+   = note: required for `(U, T)` to implement `Debug`
 help: consider restricting type parameter `U`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
@@ -28,7 +28,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (u, t)
    |     ^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(U, T)`
+   = note: required for `(U, T)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
index b83105c45f2..14cbfb3806f 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
@@ -4,7 +4,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (t, 4u32)
    |     ^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, u32)`
+   = note: required for `(T, u32)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
@@ -16,7 +16,7 @@ error[E0277]: `U` doesn't implement `Debug`
 LL |     (u, 4u32)
    |     ^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(U, u32)`
+   = note: required for `(U, u32)` to implement `Debug`
 help: consider restricting type parameter `U`
    |
 LL | type Two<T, U: std::fmt::Debug> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
index 50cf982733b..722693e4266 100644
--- a/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
+++ b/src/test/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
@@ -15,7 +15,7 @@ error[E0277]: `A` doesn't implement `Debug`
 LL |     (t, u, T::BAR)
    |     ^^^^^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, _)`
+   = note: required for `(A, B, _)` to implement `Debug`
 help: consider restricting type parameter `A`
    |
 LL | type Two<A: std::fmt::Debug, B> = impl Debug;
@@ -27,7 +27,7 @@ error[E0277]: `B` doesn't implement `Debug`
 LL |     (t, u, T::BAR)
    |     ^^^^^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, _)`
+   = note: required for `(A, B, _)` to implement `Debug`
 help: consider restricting type parameter `B`
    |
 LL | type Two<A, B: std::fmt::Debug> = impl Debug;
@@ -39,7 +39,7 @@ error[E0277]: `A` doesn't implement `Debug`
 LL |     (t, u, 42)
    |     ^^^^^^^^^^ `A` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, i32)`
+   = note: required for `(A, B, i32)` to implement `Debug`
 help: consider restricting type parameter `A`
    |
 LL | type Two<A: std::fmt::Debug, B> = impl Debug;
@@ -51,7 +51,7 @@ error[E0277]: `B` doesn't implement `Debug`
 LL |     (t, u, 42)
    |     ^^^^^^^^^^ `B` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(A, B, i32)`
+   = note: required for `(A, B, i32)` to implement `Debug`
 help: consider restricting type parameter `B`
    |
 LL | type Two<A, B: std::fmt::Debug> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr b/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr
index 5da05a4390f..f84ec0cdc27 100644
--- a/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr
+++ b/src/test/ui/type-alias-impl-trait/issue-90400-2.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `B: Bar` is not satisfied
 LL |         MyBaz(bar)
    |         ^^^^^^^^^^ the trait `Bar` is not implemented for `B`
    |
-note: required because of the requirements on the impl of `Baz` for `MyBaz<B>`
+note: required for `MyBaz<B>` to implement `Baz`
   --> $DIR/issue-90400-2.rs:31:14
    |
 LL | impl<B: Bar> Baz for MyBaz<B> {
diff --git a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index cdaae99e286..66a6b0bbf74 100644
--- a/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/src/test/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
    |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
    |
-   = note: required because of the requirements on the impl of `Into<&'static B>` for `&A`
+   = note: required for `&A` to implement `Into<&'static B>`
 help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
    |
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) where &'static B: From<&A> {
diff --git a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
index a5ac38c38d4..b11198c584c 100644
--- a/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
+++ b/src/test/ui/type-alias-impl-trait/not_a_defining_use.stderr
@@ -4,7 +4,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (t, 5i8)
    |     ^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, i8)`
+   = note: required for `(T, i8)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
@@ -27,7 +27,7 @@ error[E0277]: `T` doesn't implement `Debug`
 LL |     (t, <U as Bar>::FOO)
    |     ^^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
-   = note: required because of the requirements on the impl of `Debug` for `(T, _)`
+   = note: required for `(T, _)` to implement `Debug`
 help: consider restricting type parameter `T`
    |
 LL | type Two<T: std::fmt::Debug, U> = impl Debug;
diff --git a/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr
index e70916573f6..95fb6f6a55a 100644
--- a/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr
+++ b/src/test/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `T: Trait` is not satisfied
 LL |     ()
    |     ^^ the trait `Trait` is not implemented for `T`
    |
-note: required because of the requirements on the impl of `ProofForConversion<T>` for `()`
+note: required for `()` to implement `ProofForConversion<T>`
   --> $DIR/underconstrained_generic.rs:13:16
    |
 LL | impl<X: Trait> ProofForConversion<X> for () {
diff --git a/src/test/ui/type/type-params-in-different-spaces-2.stderr b/src/test/ui/type/type-params-in-different-spaces-2.stderr
index 53610985f31..220b3929c88 100644
--- a/src/test/ui/type/type-params-in-different-spaces-2.stderr
+++ b/src/test/ui/type/type-params-in-different-spaces-2.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
-  --> $DIR/type-params-in-different-spaces-2.rs:10:9
+  --> $DIR/type-params-in-different-spaces-2.rs:10:16
    |
 LL |         Tr::op(u)
-   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |         ------ ^ the trait `Tr<U>` is not implemented for `Self`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: consider further restricting `Self`
    |
@@ -10,10 +12,12 @@ LL |     fn test<U>(u: U) -> Self where Self: Tr<U> {
    |                              +++++++++++++++++
 
 error[E0277]: the trait bound `Self: Tr<U>` is not satisfied
-  --> $DIR/type-params-in-different-spaces-2.rs:16:9
+  --> $DIR/type-params-in-different-spaces-2.rs:16:16
    |
 LL |         Tr::op(u)
-   |         ^^^^^^ the trait `Tr<U>` is not implemented for `Self`
+   |         ------ ^ the trait `Tr<U>` is not implemented for `Self`
+   |         |
+   |         required by a bound introduced by this call
    |
 help: consider further restricting `Self`
    |
diff --git a/src/test/ui/typeck/issue-90101.stderr b/src/test/ui/typeck/issue-90101.stderr
index ab9a72edfe9..d2729d85354 100644
--- a/src/test/ui/typeck/issue-90101.stderr
+++ b/src/test/ui/typeck/issue-90101.stderr
@@ -12,7 +12,7 @@ LL |     func(Path::new("hello").to_path_buf().to_string_lossy(), "world")
              <PathBuf as From<Cow<'a, Path>>>
              <PathBuf as From<OsString>>
              <PathBuf as From<String>>
-   = note: required because of the requirements on the impl of `Into<PathBuf>` for `Cow<'_, str>`
+   = note: required for `Cow<'_, str>` to implement `Into<PathBuf>`
 note: required by a bound in `func`
   --> $DIR/issue-90101.rs:3:20
    |
diff --git a/src/test/ui/typeck/issue-91633.rs b/src/test/ui/typeck/issue-91633.rs
new file mode 100644
index 00000000000..331a798dd7a
--- /dev/null
+++ b/src/test/ui/typeck/issue-91633.rs
@@ -0,0 +1,8 @@
+// check-pass
+fn f<T> (it: &[T])
+where
+    [T] : std::ops::Index<usize>,
+{
+    let _ = &it[0];
+}
+fn main(){}
diff --git a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
index 6bb5e1f5427..b9fca1a1b54 100644
--- a/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
+++ b/src/test/ui/typeck/typeck-default-trait-impl-negation-sync.stderr
@@ -12,10 +12,10 @@ LL | fn is_sync<T: Sync>() {}
    |               ^^^^ required by this bound in `is_sync`
 
 error[E0277]: `UnsafeCell<u8>` cannot be shared between threads safely
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:5
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:36:15
    |
 LL |     is_sync::<MyTypeWUnsafe>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^ `UnsafeCell<u8>` cannot be shared between threads safely
    |
    = help: within `MyTypeWUnsafe`, the trait `Sync` is not implemented for `UnsafeCell<u8>`
 note: required because it appears within the type `MyTypeWUnsafe`
@@ -30,10 +30,10 @@ LL | fn is_sync<T: Sync>() {}
    |               ^^^^ required by this bound in `is_sync`
 
 error[E0277]: `Managed` cannot be shared between threads safely
-  --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:5
+  --> $DIR/typeck-default-trait-impl-negation-sync.rs:39:15
    |
 LL |     is_sync::<MyTypeManaged>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
+   |               ^^^^^^^^^^^^^ `Managed` cannot be shared between threads safely
    |
    = help: within `MyTypeManaged`, the trait `Sync` is not implemented for `Managed`
 note: required because it appears within the type `MyTypeManaged`
diff --git a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
index c6f9b3661a2..f08c81bc1e9 100644
--- a/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
+++ b/src/test/ui/ufcs/ufcs-qpath-self-mismatch.stderr
@@ -1,8 +1,10 @@
 error[E0277]: cannot add `u32` to `i32`
-  --> $DIR/ufcs-qpath-self-mismatch.rs:4:5
+  --> $DIR/ufcs-qpath-self-mismatch.rs:4:31
    |
 LL |     <i32 as Add<u32>>::add(1, 2);
-   |     ^^^^^^^^^^^^^^^^^^^^^^ no implementation for `i32 + u32`
+   |     ----------------------    ^ no implementation for `i32 + u32`
+   |     |
+   |     required by a bound introduced by this call
    |
    = help: the trait `Add<u32>` is not implemented for `i32`
    = help: the following other types implement trait `Add<Rhs>`:
diff --git a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
index 85ff49d61a3..635ebbb71d0 100644
--- a/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
+++ b/src/test/ui/unboxed-closures/unboxed-closures-infer-fn-once-move-from-projection.stderr
@@ -6,7 +6,17 @@ LL |     let c = || drop(y.0);
    |             |
    |             this closure implements `FnOnce`, not `Fn`
 LL |     foo(c);
-   |     --- the requirement to implement `Fn` derives from here
+   |     --- - the requirement to implement `Fn` derives from here
+   |     |
+   |     required by a bound introduced by this call
+   |
+note: required by a bound in `foo`
+  --> $DIR/unboxed-closures-infer-fn-once-move-from-projection.rs:4:14
+   |
+LL | fn foo<F>(f: F)
+   |    --- required by a bound in this
+LL |     where F: Fn()
+   |              ^^^^ required by this bound in `foo`
 
 error: aborting due to previous error
 
diff --git a/src/test/ui/union/union-generic.mirunsafeck.stderr b/src/test/ui/union/union-generic.mirunsafeck.stderr
index a4f0c400d73..037022a91fc 100644
--- a/src/test/ui/union/union-generic.mirunsafeck.stderr
+++ b/src/test/ui/union/union-generic.mirunsafeck.stderr
@@ -11,10 +11,10 @@ LL | union U<T: Copy> {
    |            ^^^^ required by this bound in `U`
 
 error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:13:13
+  --> $DIR/union-generic.rs:13:17
    |
 LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |                 ^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
    |
 note: required by a bound in `U`
   --> $DIR/union-generic.rs:6:12
diff --git a/src/test/ui/union/union-generic.thirunsafeck.stderr b/src/test/ui/union/union-generic.thirunsafeck.stderr
index a4f0c400d73..037022a91fc 100644
--- a/src/test/ui/union/union-generic.thirunsafeck.stderr
+++ b/src/test/ui/union/union-generic.thirunsafeck.stderr
@@ -11,10 +11,10 @@ LL | union U<T: Copy> {
    |            ^^^^ required by this bound in `U`
 
 error[E0277]: the trait bound `Rc<u32>: Copy` is not satisfied
-  --> $DIR/union-generic.rs:13:13
+  --> $DIR/union-generic.rs:13:17
    |
 LL |     let u = U::<Rc<u32>> { a: Default::default() };
-   |             ^^^^^^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
+   |                 ^^^^^^^ the trait `Copy` is not implemented for `Rc<u32>`
    |
 note: required by a bound in `U`
   --> $DIR/union-generic.rs:6:12
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
index fd58e1b1ebe..b968174dd2d 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.mir.stderr
@@ -81,40 +81,8 @@ error: unnecessary `unsafe` block
 LL |     unsafe { unsafe { unsf() } }
    |     ^^^^^^ unnecessary `unsafe` block
 
-error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5
-   |
-LL | unsafe fn allow_level() {
-   | ----------------------- because it's nested under this `unsafe` fn
-...
-LL |     unsafe { unsf() }
-   |     ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:53:9
-   |
-LL | #[allow(unsafe_op_in_unsafe_fn)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^
-
-error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9
-   |
-LL | unsafe fn nested_allow_level() {
-   | ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |         unsafe { unsf() }
-   |         ^^^^^^ unnecessary `unsafe` block
-   |
-   = note: this `unsafe` block does contain unsafe operations, but those are already allowed in an `unsafe fn`
-note: the lint level is defined here
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:65:13
-   |
-LL |     #[allow(unsafe_op_in_unsafe_fn)]
-   |             ^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0133]: call to unsafe function is unsafe and requires unsafe block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
@@ -122,13 +90,13 @@ LL |     unsf();
    = 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:83:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81: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 13 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
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
index 30b07234034..db1e916a36c 100644
--- 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
@@ -58,7 +58,6 @@ unsafe fn allow_level() {
     VOID = ();
 
     unsafe { unsf() }
-    //~^ ERROR unnecessary `unsafe` block
 }
 
 unsafe fn nested_allow_level() {
@@ -70,7 +69,6 @@ unsafe fn nested_allow_level() {
         VOID = ();
 
         unsafe { unsf() }
-        //~^ ERROR unnecessary `unsafe` block
     }
 }
 
diff --git a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
index 2ba6a72930d..e365293657e 100644
--- a/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
+++ b/src/test/ui/unsafe/rfc-2585-unsafe_op_in_unsafe_fn.thir.stderr
@@ -83,26 +83,8 @@ LL |     unsafe { unsafe { unsf() } }
    |     |
    |     because it's nested under this `unsafe` block
 
-error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:60:5
-   |
-LL | unsafe fn allow_level() {
-   | ----------------------- because it's nested under this `unsafe` fn
-...
-LL |     unsafe { unsf() }
-   |     ^^^^^^ unnecessary `unsafe` block
-
-error: unnecessary `unsafe` block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:72:9
-   |
-LL | unsafe fn nested_allow_level() {
-   | ------------------------------ because it's nested under this `unsafe` fn
-...
-LL |         unsafe { unsf() }
-   |         ^^^^^^ unnecessary `unsafe` block
-
 error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:78:5
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:76:5
    |
 LL |     unsf();
    |     ^^^^^^ call to unsafe function
@@ -110,13 +92,13 @@ LL |     unsf();
    = note: consult the function's documentation for information on how to avoid undefined behavior
 
 error[E0133]: call to unsafe function `unsf` is unsafe and requires unsafe function or block
-  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:83:9
+  --> $DIR/rfc-2585-unsafe_op_in_unsafe_fn.rs:81: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 13 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0133`.
diff --git a/src/test/ui/unsized-locals/unsized-exprs.stderr b/src/test/ui/unsized-locals/unsized-exprs.stderr
index 6960255d987..a7f57e3fd15 100644
--- a/src/test/ui/unsized-locals/unsized-exprs.stderr
+++ b/src/test/ui/unsized-locals/unsized-exprs.stderr
@@ -12,9 +12,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/unsized-exprs.rs:24:22
    |
 LL |     udrop::<A<[u8]>>(A { 0: *foo() });
-   |     ---------------- ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                      ^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
    |
    = help: within `A<[u8]>`, the trait `Sized` is not implemented for `[u8]`
 note: required because it appears within the type `A<[u8]>`
diff --git a/src/test/ui/unsized/issue-30355.stderr b/src/test/ui/unsized/issue-30355.stderr
index d7af558eef4..f5491552a45 100644
--- a/src/test/ui/unsized/issue-30355.stderr
+++ b/src/test/ui/unsized/issue-30355.stderr
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `[u8]` cannot be known at compilation
   --> $DIR/issue-30355.rs:5:8
    |
 LL |     &X(*Y)
-   |      - ^^ doesn't have a size known at compile-time
-   |      |
-   |      required by a bound introduced by this call
+   |        ^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `[u8]`
    = help: unsized fn params are gated as an unstable feature
diff --git a/src/test/ui/unsized/issue-71659.stderr b/src/test/ui/unsized/issue-71659.stderr
index d7b95f55769..50060e53a49 100644
--- a/src/test/ui/unsized/issue-71659.stderr
+++ b/src/test/ui/unsized/issue-71659.stderr
@@ -1,8 +1,10 @@
 error[E0277]: the trait bound `dyn Foo: CastTo<[i32]>` is not satisfied
-  --> $DIR/issue-71659.rs:30:15
+  --> $DIR/issue-71659.rs:30:13
    |
 LL |     let x = x.cast::<[i32]>();
-   |               ^^^^ the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
+   |             ^ ---- required by a bound introduced by this call
+   |             |
+   |             the trait `CastTo<[i32]>` is not implemented for `dyn Foo`
    |
 note: required by a bound in `Cast::cast`
   --> $DIR/issue-71659.rs:19:15
diff --git a/src/test/ui/unsized/issue-75707.stderr b/src/test/ui/unsized/issue-75707.stderr
index 7d0a2cb85b6..97618ed05ed 100644
--- a/src/test/ui/unsized/issue-75707.stderr
+++ b/src/test/ui/unsized/issue-75707.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `MyCall: Callback` is not satisfied
-  --> $DIR/issue-75707.rs:15:5
+  --> $DIR/issue-75707.rs:15:9
    |
 LL |     f::<dyn Processing<Call = MyCall>>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Callback` is not implemented for `MyCall`
    |
 note: required by a bound in `f`
   --> $DIR/issue-75707.rs:9:9
diff --git a/src/test/ui/unsized/unsized-fn-param.stderr b/src/test/ui/unsized/unsized-fn-param.stderr
index 0221ef16b49..b4772605432 100644
--- a/src/test/ui/unsized/unsized-fn-param.stderr
+++ b/src/test/ui/unsized/unsized-fn-param.stderr
@@ -2,9 +2,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:11:11
    |
 LL |     foo11("bar", &"baz");
-   |     ----- ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
@@ -17,9 +15,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:13:19
    |
 LL |     foo12(&"bar", "baz");
-   |     -----         ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<Path>`
@@ -32,9 +28,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:16:11
    |
 LL |     foo21("bar", &"baz");
-   |     ----- ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |           ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<str>`
@@ -47,9 +41,7 @@ error[E0277]: the size for values of type `str` cannot be known at compilation t
   --> $DIR/unsized-fn-param.rs:18:19
    |
 LL |     foo22(&"bar", "baz");
-   |     -----         ^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |                   ^^^^^ doesn't have a size known at compile-time
    |
    = help: the trait `Sized` is not implemented for `str`
    = note: required for the cast from `str` to the object type `dyn AsRef<str>`
diff --git a/src/test/ui/unsized/unsized-struct.stderr b/src/test/ui/unsized/unsized-struct.stderr
index c9510e92fec..dff1b0a5112 100644
--- a/src/test/ui/unsized/unsized-struct.stderr
+++ b/src/test/ui/unsized/unsized-struct.stderr
@@ -25,10 +25,10 @@ LL + fn foo2<T>() { not_sized::<Foo<T>>() }
    |
 
 error[E0277]: the size for values of type `T` cannot be known at compilation time
-  --> $DIR/unsized-struct.rs:13:24
+  --> $DIR/unsized-struct.rs:13:35
    |
 LL | fn bar2<T: ?Sized>() { is_sized::<Bar<T>>() }
-   |         -              ^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |         -                         ^^^^^^ doesn't have a size known at compile-time
    |         |
    |         this type parameter needs to be `std::marker::Sized`
    |
diff --git a/src/test/ui/unsized/unsized3.stderr b/src/test/ui/unsized/unsized3.stderr
index d64091b15eb..9ad1ac6b4df 100644
--- a/src/test/ui/unsized/unsized3.stderr
+++ b/src/test/ui/unsized/unsized3.stderr
@@ -79,14 +79,12 @@ LL | fn f5<Y: ?Sized>(x: &Y) {}
    |        ++++++++
 
 error[E0277]: the size for values of type `X` cannot be known at compilation time
-  --> $DIR/unsized3.rs:40:8
+  --> $DIR/unsized3.rs:40:5
    |
 LL | fn f9<X: ?Sized>(x1: Box<S<X>>) {
    |       - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(*x1, 34));
-   |     -- ^^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |     ^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
@@ -106,9 +104,7 @@ error[E0277]: the size for values of type `X` cannot be known at compilation tim
 LL | fn f10<X: ?Sized>(x1: Box<S<X>>) {
    |        - this type parameter needs to be `std::marker::Sized`
 LL |     f5(&(32, *x1));
-   |     --  ^^^^^^^^^ doesn't have a size known at compile-time
-   |     |
-   |     required by a bound introduced by this call
+   |         ^^^^^^^^^ doesn't have a size known at compile-time
    |
 note: required because it appears within the type `S<X>`
   --> $DIR/unsized3.rs:28:8
diff --git a/src/test/ui/wf/hir-wf-check-erase-regions.stderr b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
index 037f8b9f337..b04588c5716 100644
--- a/src/test/ui/wf/hir-wf-check-erase-regions.stderr
+++ b/src/test/ui/wf/hir-wf-check-erase-regions.stderr
@@ -6,7 +6,7 @@ LL |     type IntoIter = std::iter::Flatten<std::slice::Iter<'a, T>>;
    |
    = help: the trait `Iterator` is not implemented for `&T`
    = help: the trait `Iterator` is implemented for `&mut I`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+   = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
    |
@@ -21,7 +21,7 @@ LL |     fn into_iter(self) -> Self::IntoIter {
    |
    = help: the trait `Iterator` is not implemented for `&T`
    = help: the trait `Iterator` is implemented for `&mut I`
-   = note: required because of the requirements on the impl of `IntoIterator` for `&T`
+   = note: required for `&T` to implement `IntoIterator`
 note: required by a bound in `Flatten`
   --> $SRC_DIR/core/src/iter/adapters/flatten.rs:LL:COL
    |
diff --git a/src/test/ui/wf/wf-const-type.stderr b/src/test/ui/wf/wf-const-type.stderr
index e47920d3dfc..85938364ede 100644
--- a/src/test/ui/wf/wf-const-type.stderr
+++ b/src/test/ui/wf/wf-const-type.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
 LL | const FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
    |            ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<NotCopy>`
+   = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
   --> $DIR/wf-const-type.rs:7:17
    |
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
index 29dfb585ac6..6cf4f33f947 100644
--- a/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj-box.stderr
@@ -11,7 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Trait>>` for `Box<S>`
+   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
    = note: required by cast to type `Box<dyn Trait>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -27,7 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Trait>>` for `Box<S>`
+   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
    = note: required by cast to type `Box<(dyn Trait + 'static)>`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -43,7 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<Box<dyn Trait>>` for `Box<S>`
+   = note: required for `Box<S>` to implement `CoerceUnsized<Box<dyn Trait>>`
    = note: required by cast to type `Box<dyn Trait>`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
index 02169f26f90..c9bd4549aaf 100644
--- a/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
+++ b/src/test/ui/wf/wf-convert-unsafe-trait-obj.stderr
@@ -11,7 +11,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
    = note: required by cast to type `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -27,7 +27,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
    = note: required by cast to type `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -43,7 +43,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
    = note: required by cast to type `&dyn Trait`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
index b03023b5fd1..78312a09105 100644
--- a/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
+++ b/src/test/ui/wf/wf-foreign-fn-decl-ret.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/wf-foreign-fn-decl-ret.rs:11:25
+  --> $DIR/wf-foreign-fn-decl-ret.rs:11:5
    |
 LL |     pub fn lint_me() -> <() as Foo>::Assoc;
-   |                         ^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
 
 error[E0277]: the trait bound `u32: Unsatisfied` is not satisfied
   --> $DIR/wf-foreign-fn-decl-ret.rs:14:32
diff --git a/src/test/ui/wf/wf-static-type.stderr b/src/test/ui/wf/wf-static-type.stderr
index 4ae69cf2e1f..16c6124b652 100644
--- a/src/test/ui/wf/wf-static-type.stderr
+++ b/src/test/ui/wf/wf-static-type.stderr
@@ -4,7 +4,7 @@ error[E0277]: the trait bound `NotCopy: Copy` is not satisfied
 LL | static FOO: IsCopy<Option<NotCopy>> = IsCopy { t: None };
    |             ^^^^^^^^^^^^^^^^^^^^^^^ the trait `Copy` is not implemented for `NotCopy`
    |
-   = note: required because of the requirements on the impl of `Copy` for `Option<NotCopy>`
+   = note: required for `Option<NotCopy>` to implement `Copy`
 note: required by a bound in `IsCopy`
   --> $DIR/wf-static-type.rs:7:17
    |
diff --git a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
index 6d141a58ef9..96fc1d36b9c 100644
--- a/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
+++ b/src/test/ui/wf/wf-unsafe-trait-obj-match.stderr
@@ -25,7 +25,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Trait>` for `&S`
+   = note: required for `&S` to implement `CoerceUnsized<&dyn Trait>`
    = note: required by cast to type `&dyn Trait`
 
 error[E0038]: the trait `Trait` cannot be made into an object
@@ -45,7 +45,7 @@ LL | trait Trait: Sized {}
    |       -----  ^^^^^ ...because it requires `Self: Sized`
    |       |
    |       this trait cannot be made into an object...
-   = note: required because of the requirements on the impl of `CoerceUnsized<&dyn Trait>` for `&R`
+   = note: required for `&R` to implement `CoerceUnsized<&dyn Trait>`
    = note: required by cast to type `&dyn Trait`
 
 error: aborting due to 3 previous errors
diff --git a/src/test/ui/where-clauses/where-clause-method-substituion.stderr b/src/test/ui/where-clauses/where-clause-method-substituion.stderr
index f431deee73f..8c47ed6d431 100644
--- a/src/test/ui/where-clauses/where-clause-method-substituion.stderr
+++ b/src/test/ui/where-clauses/where-clause-method-substituion.stderr
@@ -1,8 +1,8 @@
 error[E0277]: the trait bound `X: Foo<X>` is not satisfied
-  --> $DIR/where-clause-method-substituion.rs:20:7
+  --> $DIR/where-clause-method-substituion.rs:20:16
    |
 LL |     1.method::<X>();
-   |       ^^^^^^ the trait `Foo<X>` is not implemented for `X`
+   |                ^ the trait `Foo<X>` is not implemented for `X`
    |
 note: required by a bound in `Bar::method`
   --> $DIR/where-clause-method-substituion.rs:6:34
diff --git a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
index c13552bc26e..e90502977ff 100644
--- a/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
+++ b/src/test/ui/where-clauses/where-clauses-method-unsatisfied.stderr
@@ -1,10 +1,8 @@
 error[E0277]: the trait bound `Bar: Eq` is not satisfied
-  --> $DIR/where-clauses-method-unsatisfied.rs:18:14
+  --> $DIR/where-clauses-method-unsatisfied.rs:18:7
    |
 LL |     x.equals(&x);
-   |       ------ ^^ the trait `Eq` is not implemented for `Bar`
-   |       |
-   |       required by a bound introduced by this call
+   |       ^^^^^^ the trait `Eq` is not implemented for `Bar`
    |
 note: required by a bound in `Foo::<T>::equals`
   --> $DIR/where-clauses-method-unsatisfied.rs:11:52
diff --git a/src/tools/miri b/src/tools/miri
-Subproject 50ef22af522f2545295090cc1ad3e4bd4aa8632
+Subproject ab88e64b152d3704c35db96dbbc6efaaed67773
diff --git a/src/tools/rust-analyzer/bench_data/glorious_old_parser b/src/tools/rust-analyzer/bench_data/glorious_old_parser
index 7e900dfeb1e..764893daa12 100644
--- a/src/tools/rust-analyzer/bench_data/glorious_old_parser
+++ b/src/tools/rust-analyzer/bench_data/glorious_old_parser
@@ -1988,7 +1988,7 @@ impl<'a> Parser<'a> {
                     err.span_suggestion(
                         span,
                         "declare the type after the parameter binding",
-                        String::from("<identifier>: <type>"),
+                        "<identifier>: <type>",
                         Applicability::HasPlaceholders,
                     );
                 } else if require_name && is_trait_item {
diff --git a/src/tools/rustfmt/src/attr.rs b/src/tools/rustfmt/src/attr.rs
index 41ba9a847e6..f5c1ee5fdd1 100644
--- a/src/tools/rustfmt/src/attr.rs
+++ b/src/tools/rustfmt/src/attr.rs
@@ -49,10 +49,7 @@ pub(crate) fn get_span_without_attrs(stmt: &ast::Stmt) -> Span {
 }
 
 /// Returns attributes that are within `outer_span`.
-pub(crate) fn filter_inline_attrs(
-    attrs: &[ast::Attribute],
-    outer_span: Span,
-) -> Vec<ast::Attribute> {
+pub(crate) fn filter_inline_attrs(attrs: &[ast::Attribute], outer_span: Span) -> ast::AttrVec {
     attrs
         .iter()
         .filter(|a| outer_span.lo() <= a.span.lo() && a.span.hi() <= outer_span.hi())
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index 8d41c881589..b6530c69243 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -116,7 +116,7 @@ pub(crate) struct UseTree {
     // Additional fields for top level use items.
     // Should we have another struct for top-level use items rather than reusing this?
     visibility: Option<ast::Visibility>,
-    attrs: Option<Vec<ast::Attribute>>,
+    attrs: Option<ast::AttrVec>,
 }
 
 impl PartialEq for UseTree {
@@ -417,7 +417,7 @@ impl UseTree {
         list_item: Option<ListItem>,
         visibility: Option<ast::Visibility>,
         opt_lo: Option<BytePos>,
-        attrs: Option<Vec<ast::Attribute>>,
+        attrs: Option<ast::AttrVec>,
     ) -> UseTree {
         let span = if let Some(lo) = opt_lo {
             mk_sp(lo, a.span.hi())
diff --git a/src/tools/rustfmt/src/modules.rs b/src/tools/rustfmt/src/modules.rs
index 81da724329f..7a0d1736c59 100644
--- a/src/tools/rustfmt/src/modules.rs
+++ b/src/tools/rustfmt/src/modules.rs
@@ -26,7 +26,7 @@ type FileModMap<'ast> = BTreeMap<FileName, Module<'ast>>;
 pub(crate) struct Module<'a> {
     ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
     pub(crate) items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-    inner_attr: Vec<ast::Attribute>,
+    inner_attr: ast::AttrVec,
     pub(crate) span: Span,
 }
 
@@ -35,7 +35,7 @@ impl<'a> Module<'a> {
         mod_span: Span,
         ast_mod_kind: Option<Cow<'a, ast::ModKind>>,
         mod_items: Cow<'a, Vec<rustc_ast::ptr::P<ast::Item>>>,
-        mod_attrs: Cow<'a, Vec<ast::Attribute>>,
+        mod_attrs: Cow<'a, ast::AttrVec>,
     ) -> Self {
         let inner_attr = mod_attrs
             .iter()
@@ -158,7 +158,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                         module_item.item.span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
                         Cow::Owned(vec![]),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
             }
@@ -185,7 +185,7 @@ impl<'ast, 'sess, 'c> ModResolver<'ast, 'sess> {
                         span,
                         Some(Cow::Owned(sub_mod_kind.clone())),
                         Cow::Owned(vec![]),
-                        Cow::Owned(vec![]),
+                        Cow::Owned(ast::AttrVec::new()),
                     ),
                 )?;
             }
diff --git a/src/tools/rustfmt/src/parse/parser.rs b/src/tools/rustfmt/src/parse/parser.rs
index 268c72649a6..e0bd065518b 100644
--- a/src/tools/rustfmt/src/parse/parser.rs
+++ b/src/tools/rustfmt/src/parse/parser.rs
@@ -109,7 +109,7 @@ impl<'a> Parser<'a> {
         sess: &'a ParseSess,
         path: &Path,
         span: Span,
-    ) -> Result<(Vec<ast::Attribute>, Vec<ptr::P<ast::Item>>, Span), ParserError> {
+    ) -> Result<(ast::AttrVec, Vec<ptr::P<ast::Item>>, Span), ParserError> {
         let result = catch_unwind(AssertUnwindSafe(|| {
             let mut parser = new_parser_from_file(sess.inner(), path, Some(span));
             match parser.parse_mod(&TokenKind::Eof) {
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 3cf44a2d7d1..dee58ff2fb5 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -125,16 +125,13 @@ fn should_ignore(line: &str) -> bool {
 
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
 fn long_line_is_ok(extension: &str, is_error_code: bool, max_columns: usize, line: &str) -> bool {
-    if extension != "md" || is_error_code {
-        if line_is_url(is_error_code, max_columns, line) || should_ignore(line) {
-            return true;
-        }
-    } else if extension == "md" {
+    match extension {
+        // fluent files are allowed to be any length
+        "ftl" => true,
         // non-error code markdown is allowed to be any length
-        return true;
+        "md" if !is_error_code => true,
+        _ => line_is_url(is_error_code, max_columns, line) || should_ignore(line),
     }
-
-    false
 }
 
 enum Directive {
@@ -230,7 +227,7 @@ pub fn check(path: &Path, bad: &mut bool) {
     super::walk(path, &mut skip, &mut |entry, contents| {
         let file = entry.path();
         let filename = file.file_name().unwrap().to_string_lossy();
-        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css"];
+        let extensions = [".rs", ".py", ".js", ".sh", ".c", ".cpp", ".h", ".md", ".css", ".ftl"];
         if extensions.iter().all(|e| !filename.ends_with(e)) || filename.starts_with(".#") {
             return;
         }
diff --git a/triagebot.toml b/triagebot.toml
index b7532e016b6..8a90bc0e3c1 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -129,6 +129,7 @@ trigger_files = [
 
     # Internal tooling
     "src/etc/htmldocck.py",
+    "src/etc/check_missing_items.py",
     "src/tools/jsondocck",
     "src/tools/rustdoc-gui",
     "src/tools/rustdoc-js",
@@ -138,6 +139,15 @@ exclude_labels = [
     "T-*",
 ]
 
+[autolabel."A-rustdoc-json"]
+trigger_files = [
+    "src/etc/check_missing_items.py",
+    "src/librustdoc/json/",
+    "src/rustdoc-json-types",
+    "src/test/rustdoc-json",
+    "src/tools/jsondocck",
+]
+
 [autolabel."T-compiler"]
 trigger_files = [
     # Source code
@@ -352,12 +362,12 @@ cc = ["@oli-obk", "@RalfJung", "@JakobDegen", "@davidtwco", "@celinval", "@vakar
 
 [mentions."compiler/rustc_error_messages"]
 message = "`rustc_error_messages` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
 
 [mentions."compiler/rustc_errors/src/translation.rs"]
 message = "`rustc_errors::translation` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]
 
 [mentions."compiler/rustc_macros/src/diagnostics"]
 message = "`rustc_macros::diagnostics` was changed"
-cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank"]
+cc = ["@davidtwco", "@compiler-errors", "@JohnTitor", "@estebank", "@TaKO8Ki"]