about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-12-12 07:09:19 +0000
committerbors <bors@rust-lang.org>2023-12-12 07:09:19 +0000
commitfda521a988749458326ecef2e92e979077727a4e (patch)
tree73ec9f26b38eb86b5676735f79e577c12fe0024a
parentaaeb4dd3a93a6be4cba5eb173f35453803994773 (diff)
parent03b7ed06c88ae869daa4f2a30ef341918cc76ac7 (diff)
downloadrust-fda521a988749458326ecef2e92e979077727a4e.tar.gz
rust-fda521a988749458326ecef2e92e979077727a4e.zip
Auto merge of #3223 - rust-lang:rustup-2023-12-12, r=RalfJung
Automatic Rustup
-rw-r--r--compiler/rustc_ast/src/ast.rs13
-rw-r--r--compiler/rustc_ast/src/attr/mod.rs6
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs6
-rw-r--r--compiler/rustc_ast/src/token.rs2
-rw-r--r--compiler/rustc_ast/src/tokenstream.rs137
-rw-r--r--compiler/rustc_ast/src/visit.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs8
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/index.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs8
-rw-r--r--compiler/rustc_ast_passes/messages.ftl4
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs4
-rw-r--r--compiler/rustc_ast_passes/src/errors.rs9
-rw-r--r--compiler/rustc_ast_passes/src/feature_gate.rs29
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs106
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/expr.rs152
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs5
-rw-r--r--compiler/rustc_borrowck/src/dataflow.rs2
-rw-r--r--compiler/rustc_borrowck/src/region_infer/graphviz.rs1
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/assert/context.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/env.rs14
-rw-r--r--compiler/rustc_builtin_macros/src/source_util.rs4
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/comments.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/abi/mod.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/analyze.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs3
-rw-r--r--compiler/rustc_codegen_cranelift/src/inline_asm.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs2
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs2
-rw-r--r--compiler/rustc_codegen_gcc/example/mini_core.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/abi.rs1
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/intrinsic.rs9
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs18
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/operand.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/statement.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs2
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs2
-rw-r--r--compiler/rustc_data_structures/src/fingerprint/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/graph/implementation/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/intern/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/tests.rs1
-rw-r--r--compiler/rustc_data_structures/src/sip128/tests.rs2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0705.md4
-rw-r--r--compiler/rustc_errors/src/json/tests.rs9
-rw-r--r--compiler/rustc_errors/src/markdown/tests/term.rs1
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/base.rs2
-rw-r--r--compiler/rustc_expand/src/config.rs110
-rw-r--r--compiler/rustc_expand/src/errors.rs10
-rw-r--r--compiler/rustc_expand/src/mbe.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs18
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs7
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs42
-rw-r--r--compiler/rustc_expand/src/parse/tests.rs35
-rw-r--r--compiler/rustc_expand/src/proc_macro_server.rs44
-rw-r--r--compiler/rustc_feature/src/accepted.rs325
-rw-r--r--compiler/rustc_feature/src/lib.rs3
-rw-r--r--compiler/rustc_feature/src/removed.rs145
-rw-r--r--compiler/rustc_feature/src/unstable.rs399
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs12
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/callee.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/diverges.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/expectation.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/inherited.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/op.rs2
-rw-r--r--compiler/rustc_incremental/src/persist/dirty_clean.rs1
-rw-r--r--compiler/rustc_infer/src/errors/note_and_explain.rs2
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_lint/messages.ftl4
-rw-r--r--compiler/rustc_lint/src/builtin.rs3
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs70
-rw-r--r--compiler/rustc_lint/src/types.rs180
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp4
-rw-r--r--compiler/rustc_macros/src/hash_stable.rs4
-rw-r--r--compiler/rustc_macros/src/lift.rs2
-rw-r--r--compiler/rustc_metadata/src/locator.rs8
-rw-r--r--compiler/rustc_metadata/src/rmeta/decoder.rs53
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs34
-rw-r--r--compiler/rustc_metadata/src/rmeta/mod.rs4
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs7
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs18
-rw-r--r--compiler/rustc_middle/src/middle/limits.rs1
-rw-r--r--compiler/rustc_middle/src/mir/consts.rs1
-rw-r--r--compiler/rustc_middle/src/mir/generic_graph.rs2
-rw-r--r--compiler/rustc_middle/src/mir/graphviz.rs3
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs3
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs11
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs4
-rw-r--r--compiler/rustc_middle/src/mir/tcx.rs2
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs3
-rw-r--r--compiler/rustc_middle/src/mir/type_foldable.rs1
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs4
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generics.rs4
-rw-r--r--compiler/rustc_middle/src/ty/layout.rs2
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs50
-rw-r--r--compiler/rustc_middle/src/ty/util.rs12
-rw-r--r--compiler/rustc_mir_build/src/build/expr/as_rvalue.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs2
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs2
-rw-r--r--compiler/rustc_mir_dataflow/src/framework/tests.rs2
-rw-r--r--compiler/rustc_mir_transform/src/abort_unwinding_calls.rs1
-rw-r--r--compiler/rustc_mir_transform/src/add_call_guards.rs1
-rw-r--r--compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs1
-rw-r--r--compiler/rustc_mir_transform/src/add_retag.rs1
-rw-r--r--compiler/rustc_mir_transform/src/add_subtyping_projections.rs1
-rw-r--r--compiler/rustc_mir_transform/src/check_alignment.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_goto.rs1
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/copy_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/coroutine.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/query.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs2
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/deduplicate_blocks.rs2
-rw-r--r--compiler/rustc_mir_transform/src/deref_separator.rs1
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_box_derefs.rs1
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs1
-rw-r--r--compiler/rustc_mir_transform/src/gvn.rs1
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs1
-rw-r--r--compiler/rustc_mir_transform/src/instsimplify.rs2
-rw-r--r--compiler/rustc_mir_transform/src/jump_threading.rs1
-rw-r--r--compiler/rustc_mir_transform/src/large_enums.rs1
-rw-r--r--compiler/rustc_mir_transform/src/lower_intrinsics.rs1
-rw-r--r--compiler/rustc_mir_transform/src/lower_slice_len.rs1
-rw-r--r--compiler/rustc_mir_transform/src/match_branches.rs1
-rw-r--r--compiler/rustc_mir_transform/src/multiple_return_terminators.rs2
-rw-r--r--compiler/rustc_mir_transform/src/normalize_array_len.rs1
-rw-r--r--compiler/rustc_mir_transform/src/prettify.rs1
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_place_mention.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_storage_markers.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_uninit_drops.rs4
-rw-r--r--compiler/rustc_mir_transform/src/remove_unneeded_drops.rs1
-rw-r--r--compiler/rustc_mir_transform/src/remove_zsts.rs1
-rw-r--r--compiler/rustc_mir_transform/src/reveal_all.rs1
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs1
-rw-r--r--compiler/rustc_mir_transform/src/simplify.rs1
-rw-r--r--compiler/rustc_mir_transform/src/simplify_branches.rs1
-rw-r--r--compiler/rustc_mir_transform/src/sroa.rs1
-rw-r--r--compiler/rustc_mir_transform/src/unreachable_prop.rs1
-rw-r--r--compiler/rustc_parse/src/lexer/mod.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/tokentrees.rs82
-rw-r--r--compiler/rustc_parse/src/parser/attr.rs1
-rw-r--r--compiler/rustc_parse/src/parser/attr_wrapper.rs14
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs12
-rw-r--r--compiler/rustc_parse/src/parser/item.rs8
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs44
-rw-r--r--compiler/rustc_query_system/src/dep_graph/edges.rs1
-rw-r--r--compiler/rustc_query_system/src/query/job.rs1
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs70
-rw-r--r--compiler/rustc_session/src/config.rs369
-rw-r--r--compiler/rustc_session/src/options.rs4
-rw-r--r--compiler/rustc_smir/src/rustc_smir/context.rs2
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs2
-rw-r--r--compiler/rustc_span/src/edition.rs10
-rw-r--r--compiler/rustc_span/src/source_map.rs6
-rw-r--r--compiler/rustc_span/src/source_map/tests.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs6
-rw-r--r--compiler/rustc_trait_selection/src/traits/auto_trait.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs7
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs22
-rw-r--r--compiler/stable_mir/src/error.rs1
-rw-r--r--config.example.toml10
-rw-r--r--library/alloc/benches/btree/map.rs1
-rw-r--r--library/alloc/benches/str.rs1
-rw-r--r--library/alloc/benches/vec_deque.rs1
-rw-r--r--library/alloc/src/collections/binary_heap/tests.rs2
-rw-r--r--library/alloc/src/collections/btree/map/tests.rs7
-rw-r--r--library/alloc/src/collections/btree/set/tests.rs3
-rw-r--r--library/alloc/src/ffi/c_str/tests.rs2
-rw-r--r--library/alloc/src/rc/tests.rs5
-rw-r--r--library/alloc/src/sync/tests.rs13
-rw-r--r--library/alloc/src/tests.rs2
-rw-r--r--library/alloc/tests/arc.rs1
-rw-r--r--library/alloc/tests/borrow.rs2
-rw-r--r--library/alloc/tests/rc.rs1
-rw-r--r--library/alloc/tests/vec.rs4
-rw-r--r--library/core/benches/num/flt2dec/mod.rs1
-rw-r--r--library/core/benches/num/flt2dec/strategy/dragon.rs1
-rw-r--r--library/core/benches/num/flt2dec/strategy/grisu.rs1
-rw-r--r--library/core/src/array/iter.rs2
-rw-r--r--library/core/src/char/methods.rs1
-rw-r--r--library/core/src/clone.rs2
-rw-r--r--library/core/src/cmp.rs14
-rw-r--r--library/core/src/convert/num.rs2
-rw-r--r--library/core/src/future/future.rs1
-rw-r--r--library/core/src/iter/adapters/array_chunks.rs2
-rw-r--r--library/core/src/iter/adapters/chain.rs2
-rw-r--r--library/core/src/iter/adapters/flatten.rs4
-rw-r--r--library/core/src/iter/adapters/fuse.rs3
-rw-r--r--library/core/src/iter/adapters/map_windows.rs2
-rw-r--r--library/core/src/iter/adapters/mod.rs2
-rw-r--r--library/core/src/iter/adapters/zip.rs2
-rw-r--r--library/core/src/mem/mod.rs2
-rw-r--r--library/core/src/ops/coroutine.rs1
-rw-r--r--library/core/src/pin.rs3
-rw-r--r--library/core/src/primitive_docs.rs9
-rw-r--r--library/core/src/ptr/const_ptr.rs12
-rw-r--r--library/core/src/ptr/mod.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs10
-rw-r--r--library/core/src/ptr/non_null.rs2
-rw-r--r--library/core/src/ptr/unique.rs1
-rw-r--r--library/core/src/slice/iter.rs2
-rw-r--r--library/core/src/slice/mod.rs7
-rw-r--r--library/core/src/task/poll.rs1
-rw-r--r--library/core/src/task/wake.rs2
-rw-r--r--library/core/tests/array.rs1
-rw-r--r--library/core/tests/cell.rs2
-rw-r--r--library/core/tests/char.rs1
-rw-r--r--library/core/tests/hash/mod.rs1
-rw-r--r--library/core/tests/iter/adapters/array_chunks.rs3
-rw-r--r--library/core/tests/iter/mod.rs1
-rw-r--r--library/core/tests/nonzero.rs3
-rw-r--r--library/core/tests/num/mod.rs5
-rw-r--r--library/core/tests/option.rs1
-rw-r--r--library/core/tests/slice.rs1
-rw-r--r--library/proc_macro/src/lib.rs26
-rw-r--r--library/std/src/backtrace.rs1
-rw-r--r--library/std/src/backtrace/tests.rs2
-rw-r--r--library/std/src/env/tests.rs2
-rw-r--r--library/std/src/ffi/os_str/tests.rs4
-rw-r--r--library/std/src/io/error/repr_bitpacked.rs1
-rw-r--r--library/std/src/io/error/repr_unpacked.rs1
-rw-r--r--library/std/src/net/tcp/tests.rs2
-rw-r--r--library/std/src/net/udp/tests.rs1
-rw-r--r--library/std/src/path/tests.rs4
-rw-r--r--library/std/src/sync/mpsc/sync_tests.rs1
-rw-r--r--library/std/src/sync/mpsc/tests.rs1
-rw-r--r--library/std/src/sync/mutex.rs2
-rw-r--r--library/std/src/sys_common/thread.rs2
-rw-r--r--library/std/src/sys_common/wtf8/tests.rs1
-rw-r--r--library/test/src/term/terminfo/parm/tests.rs2
-rw-r--r--library/test/src/tests.rs17
-rw-r--r--src/bootstrap/src/bin/main.rs31
-rw-r--r--src/bootstrap/src/bin/rustc.rs6
-rw-r--r--src/bootstrap/src/bin/rustdoc.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/clean.rs1
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs6
-rw-r--r--src/bootstrap/src/core/build_steps/llvm.rs14
-rw-r--r--src/bootstrap/src/core/build_steps/test.rs19
-rw-r--r--src/bootstrap/src/core/build_steps/tool.rs2
-rw-r--r--src/bootstrap/src/core/builder.rs44
-rw-r--r--src/bootstrap/src/core/config/config.rs558
-rw-r--r--src/bootstrap/src/core/config/flags.rs3
-rw-r--r--src/bootstrap/src/core/sanity.rs2
-rw-r--r--src/bootstrap/src/lib.rs59
-rw-r--r--src/bootstrap/src/tests/config.rs11
-rw-r--r--src/bootstrap/src/utils/bin_helpers.rs31
-rw-r--r--src/bootstrap/src/utils/cc_detect.rs4
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs10
-rw-r--r--src/bootstrap/src/utils/helpers.rs93
-rw-r--r--src/doc/rustc/src/linker-plugin-lto.md8
-rw-r--r--src/doc/rustc/src/platform-support/TEMPLATE.md2
-rw-r--r--src/doc/unstable-book/src/compiler-flags/env.md26
-rw-r--r--src/etc/completions/x.py.fish15
-rw-r--r--src/etc/completions/x.py.ps115
-rw-r--r--src/etc/completions/x.py.sh30
-rw-r--r--src/etc/completions/x.py.zsh15
-rw-r--r--src/librustdoc/clean/auto_trait.rs4
-rw-r--r--src/librustdoc/clean/cfg/tests.rs4
-rw-r--r--src/librustdoc/clean/render_macro_matchers.rs6
-rw-r--r--src/librustdoc/clean/types.rs2
-rw-r--r--src/librustdoc/clean/types/tests.rs5
-rw-r--r--src/librustdoc/docfs.rs1
-rw-r--r--src/librustdoc/html/render/mod.rs1
-rw-r--r--src/librustdoc/html/static/js/search.js35
-rw-r--r--src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/derive.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/escape.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/never_loop.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/same_item_push.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/loops/utils.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/missing_inline.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/unnamed_address.rs68
-rw-r--r--src/tools/clippy/clippy_utils/src/ty.rs34
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr120
-rw-r--r--src/tools/clippy/tests/ui/vtable_address_comparisons.rs52
-rw-r--r--src/tools/clippy/tests/ui/vtable_address_comparisons.stderr68
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs5
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs1
-rw-r--r--src/tools/miri/src/concurrency/weak_memory.rs1
-rw-r--r--src/tools/miri/src/eval.rs1
-rw-r--r--src/tools/miri/src/shims/env.rs1
-rw-r--r--src/tools/miri/src/shims/unix/fs.rs1
-rw-r--r--src/tools/miri/src/shims/unix/linux/sync.rs2
-rw-r--r--src/tools/miri/src/shims/unix/sync.rs2
-rw-r--r--src/tools/miri/tests/pass-dep/shims/libc-fs.rs1
-rw-r--r--src/tools/miri/tests/pass/arrays.rs2
-rw-r--r--src/tools/miri/tests/pass/binary-heap.rs1
-rw-r--r--src/tools/miri/tests/pass/enum-nullable-const-null-with-fields.rs3
-rw-r--r--src/tools/miri/tests/pass/function_calls/abi_compat.rs6
-rw-r--r--src/tools/miri/tests/pass/pointers.rs1
-rw-r--r--src/tools/miri/tests/pass/rc.rs1
-rw-r--r--src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs31
-rw-r--r--src/tools/rust-analyzer/crates/stdx/src/anymap.rs1
-rw-r--r--src/tools/rustfmt/src/comment.rs3
-rw-r--r--src/tools/rustfmt/src/config/file_lines.rs2
-rw-r--r--src/tools/rustfmt/src/config/mod.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/checkstyle.rs1
-rw-r--r--src/tools/rustfmt/src/emitter/diff.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/json.rs2
-rw-r--r--src/tools/rustfmt/src/emitter/modified_lines.rs1
-rw-r--r--src/tools/rustfmt/src/emitter/stdout.rs1
-rw-r--r--src/tools/rustfmt/src/ignore_path.rs2
-rw-r--r--src/tools/rustfmt/src/imports.rs1
-rw-r--r--src/tools/rustfmt/src/macros.rs6
-rw-r--r--src/tools/rustfmt/src/reorder.rs2
-rw-r--r--src/tools/rustfmt/src/types.rs1
-rw-r--r--src/tools/rustfmt/tests/source/issue-2927-2.rs2
-rw-r--r--src/tools/rustfmt/tests/source/issue-2927.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2927-2.rs2
-rw-r--r--src/tools/rustfmt/tests/target/issue-2927.rs2
-rw-r--r--tests/pretty/cast-lt.pp2
-rw-r--r--tests/run-make/rustc-macro-dep-files/foo.rs2
-rw-r--r--tests/rustdoc-js/assoc-type.js11
-rw-r--r--tests/rustdoc-js/enum-variant-not-type.js70
-rw-r--r--tests/rustdoc-js/enum-variant-not-type.rs14
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--tests/ui/abi/compatibility.rs7
-rw-r--r--tests/ui/async-await/issues/issue-60674.stdout6
-rw-r--r--tests/ui/bare-fn-implements-fn-mut.rs2
-rw-r--r--tests/ui/box/alloc-unstable.rs3
-rw-r--r--tests/ui/box/into-boxed-slice.rs2
-rw-r--r--tests/ui/box/new-box-syntax.rs2
-rw-r--r--tests/ui/box/unit/unique-kinds.rs1
-rw-r--r--tests/ui/check-cfg/allow-same-level.stderr2
-rw-r--r--tests/ui/check-cfg/compact-names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.feature.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names-values.full.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr2
-rw-r--r--tests/ui/check-cfg/exhaustive-names.stderr2
-rw-r--r--tests/ui/check-cfg/mix.cfg.stderr2
-rw-r--r--tests/ui/check-cfg/mix.stderr2
-rw-r--r--tests/ui/check-cfg/stmt-no-ice.stderr2
-rw-r--r--tests/ui/check-cfg/well-known-names.stderr2
-rw-r--r--tests/ui/cleanup-rvalue-for-scope.rs3
-rw-r--r--tests/ui/cleanup-rvalue-scopes.rs2
-rw-r--r--tests/ui/codegen/const-bool-bitcast.rs15
-rw-r--r--tests/ui/coherence/coherence-negative-impls-safe-rpass.rs2
-rw-r--r--tests/ui/coherence/coherence-where-clause.rs2
-rw-r--r--tests/ui/consts/const-block.rs2
-rw-r--r--tests/ui/consts/fn_trait_refs.stderr8
-rw-r--r--tests/ui/coroutine/control-flow.rs1
-rw-r--r--tests/ui/coroutine/discriminant.rs2
-rw-r--r--tests/ui/coroutine/iterator-count.rs1
-rw-r--r--tests/ui/coroutine/non-static-is-unpin.rs2
-rw-r--r--tests/ui/coroutine/smoke-resume-args.rs1
-rw-r--r--tests/ui/editions/edition-feature-ok.rs5
-rw-r--r--tests/ui/editions/edition-feature-redundant.rs7
-rw-r--r--tests/ui/editions/edition-feature-redundant.stderr9
-rw-r--r--tests/ui/editions/epoch-gate-feature.rs15
-rw-r--r--tests/ui/error-codes/E0705.rs10
-rw-r--r--tests/ui/error-codes/E0705.stderr9
-rw-r--r--tests/ui/extenv/extenv-env-overload.rs9
-rw-r--r--tests/ui/extenv/extenv-env.rs5
-rw-r--r--tests/ui/extenv/extenv-not-env.rs7
-rw-r--r--tests/ui/extern/issue-13655.rs2
-rw-r--r--tests/ui/feature-gates/env-flag.rs3
-rw-r--r--tests/ui/feature-gates/env-flag.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.rs6
-rw-r--r--tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr18
-rw-r--r--tests/ui/feature-gates/feature-gate-never_patterns.rs61
-rw-r--r--tests/ui/feature-gates/feature-gate-never_patterns.stderr82
-rw-r--r--tests/ui/for-loop-while/while-prelude-drop.rs3
-rw-r--r--tests/ui/hygiene/unpretty-debug.stdout2
-rw-r--r--tests/ui/impl-trait/implicit-capture-late.rs14
-rw-r--r--tests/ui/impl-trait/implicit-capture-late.stderr9
-rw-r--r--tests/ui/impl-trait/variance.e2024.stderr26
-rw-r--r--tests/ui/impl-trait/variance.new.stderr26
-rw-r--r--tests/ui/impl-trait/variance.old.stderr (renamed from tests/ui/impl-trait/variance.stderr)8
-rw-r--r--tests/ui/impl-trait/variance.rs16
-rw-r--r--tests/ui/infinite/issue-41731-infinite-macro-print.stderr8
-rw-r--r--tests/ui/infinite/issue-41731-infinite-macro-println.stderr8
-rw-r--r--tests/ui/issues/issue-17336.rs3
-rw-r--r--tests/ui/issues/issue-20847.rs2
-rw-r--r--tests/ui/issues/issue-5554.rs1
-rw-r--r--tests/ui/issues/issue-8783.rs2
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.rs138
-rw-r--r--tests/ui/lint/wide_pointer_comparisons.stderr452
-rw-r--r--tests/ui/macros/stringify.rs373
-rw-r--r--tests/ui/macros/syntax-extension-source-utils.rs4
-rw-r--r--tests/ui/macros/trace-macro.stderr2
-rw-r--r--tests/ui/macros/trace_faulty_macros.stderr14
-rw-r--r--tests/ui/mir/mir_raw_fat_ptr.rs2
-rw-r--r--tests/ui/moves/move-out-of-field.rs2
-rw-r--r--tests/ui/overloaded/overloaded-calls-param-vtables.rs1
-rw-r--r--tests/ui/overloaded/overloaded-calls-simple.rs2
-rw-r--r--tests/ui/overloaded/overloaded-calls-zero-args.rs2
-rw-r--r--tests/ui/overloaded/overloaded-deref-count.rs1
-rw-r--r--tests/ui/overloaded/overloaded-deref.rs1
-rw-r--r--tests/ui/parser/match-arm-without-body.rs2
-rw-r--r--tests/ui/parser/match-arm-without-body.stderr16
-rw-r--r--tests/ui/proc-macro/allowed-attr-stmt-expr.stdout15
-rw-r--r--tests/ui/proc-macro/attr-complex-fn.stdout7
-rw-r--r--tests/ui/proc-macro/attr-stmt-expr.stdout9
-rw-r--r--tests/ui/proc-macro/attribute-after-derive.stdout6
-rw-r--r--tests/ui/proc-macro/attribute-spans-preserved.stdout2
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs7
-rw-r--r--tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-a.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-atob.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-b-rpass.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-ctod.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-same-struct.rs4
-rw-r--r--tests/ui/proc-macro/auxiliary/derive-union.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs2
-rw-r--r--tests/ui/proc-macro/auxiliary/issue-79825.rs2
-rw-r--r--tests/ui/proc-macro/capture-macro-rules-invoke.stdout2
-rw-r--r--tests/ui/proc-macro/capture-unglued-token.stdout2
-rw-r--r--tests/ui/proc-macro/cfg-eval-inner.stdout20
-rw-r--r--tests/ui/proc-macro/cfg-eval.stdout3
-rw-r--r--tests/ui/proc-macro/custom-attr-only-one-derive.rs2
-rw-r--r--tests/ui/proc-macro/derive-same-struct.stdout2
-rw-r--r--tests/ui/proc-macro/doc-comment-preserved.stdout2
-rw-r--r--tests/ui/proc-macro/dollar-crate-issue-57089.stdout6
-rw-r--r--tests/ui/proc-macro/dollar-crate-issue-62325.stdout6
-rw-r--r--tests/ui/proc-macro/dollar-crate.stdout18
-rw-r--r--tests/ui/proc-macro/expand-to-derive.stdout5
-rw-r--r--tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout11
-rw-r--r--tests/ui/proc-macro/inert-attribute-order.stdout12
-rw-r--r--tests/ui/proc-macro/inner-attr-non-inline-mod.stdout3
-rw-r--r--tests/ui/proc-macro/inner-attrs.stdout26
-rw-r--r--tests/ui/proc-macro/issue-75734-pp-paren.stdout3
-rw-r--r--tests/ui/proc-macro/issue-75930-derive-cfg.stdout65
-rw-r--r--tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout2
-rw-r--r--tests/ui/proc-macro/keep-expr-tokens.stdout3
-rw-r--r--tests/ui/proc-macro/macro-rules-derive-cfg.stdout11
-rw-r--r--tests/ui/proc-macro/meta-macro-hygiene.stdout4
-rw-r--r--tests/ui/proc-macro/nested-derive-cfg.stdout2
-rw-r--r--tests/ui/proc-macro/nonterminal-expansion.stdout2
-rw-r--r--tests/ui/proc-macro/nonterminal-token-hygiene.stdout8
-rw-r--r--tests/ui/proc-macro/pretty-print-tts.stdout3
-rw-r--r--tests/ui/proc-macro/trailing-plus.stdout3
-rw-r--r--tests/ui/proc-macro/weird-braces.stdout34
-rw-r--r--tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs3
-rw-r--r--tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs39
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr14
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs5
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr12
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs3
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr8
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs1
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr49
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs3
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr31
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr10
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr2
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr2
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed1
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs1
-rw-r--r--tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr8
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed1
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-empty-paths.rs1
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr12
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-paths.fixed1
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-paths.rs1
-rw-r--r--tests/ui/rust-2018/edition-lint-nested-paths.stderr10
-rw-r--r--tests/ui/rust-2018/edition-lint-paths.fixed1
-rw-r--r--tests/ui/rust-2018/edition-lint-paths.rs1
-rw-r--r--tests/ui/rust-2018/edition-lint-paths.stderr20
-rw-r--r--tests/ui/rust-2018/extern-crate-idiomatic.fixed1
-rw-r--r--tests/ui/rust-2018/extern-crate-idiomatic.rs1
-rw-r--r--tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed1
-rw-r--r--tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs1
-rw-r--r--tests/ui/rust-2018/extern-crate-rename.fixed1
-rw-r--r--tests/ui/rust-2018/extern-crate-rename.rs1
-rw-r--r--tests/ui/rust-2018/extern-crate-rename.stderr4
-rw-r--r--tests/ui/rust-2018/extern-crate-submod.fixed1
-rw-r--r--tests/ui/rust-2018/extern-crate-submod.rs1
-rw-r--r--tests/ui/rust-2018/extern-crate-submod.stderr4
-rw-r--r--tests/ui/rust-2018/issue-51008-1.rs2
-rw-r--r--tests/ui/rust-2018/issue-51008.rs2
-rw-r--r--tests/ui/rust-2018/proc-macro-crate-in-paths.rs1
-rw-r--r--tests/ui/rust-2018/suggestions-not-always-applicable.fixed1
-rw-r--r--tests/ui/rust-2018/suggestions-not-always-applicable.rs1
-rw-r--r--tests/ui/simd/repr_packed.rs59
-rw-r--r--tests/ui/specialization/specialization-translate-projections.rs1
-rw-r--r--tests/ui/stdlib-unit-tests/istr.rs2
-rw-r--r--tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs2
-rw-r--r--tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs1
-rw-r--r--tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs3
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.fixed2
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.rs2
-rw-r--r--tests/ui/suggestions/derive-clone-for-eq.stderr4
-rw-r--r--tests/ui/suggestions/invalid-bin-op.stderr4
-rw-r--r--tests/ui/tool_lints_2018_preview.rs1
-rw-r--r--tests/ui/traits/inheritance/num0.rs2
-rw-r--r--tests/ui/traits/inheritance/overloading-simple.rs1
-rw-r--r--tests/ui/traits/inheritance/overloading.rs1
-rw-r--r--tests/ui/traits/issue-22019.rs2
-rw-r--r--tests/ui/traits/multidispatch2.rs1
-rw-r--r--tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs2
-rw-r--r--tests/ui/traits/wf-object/reverse-order.rs2
-rw-r--r--tests/ui/ufcs/ufcs-polymorphic-paths.rs3
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-boxed.rs1
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs1
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs2
-rw-r--r--tests/ui/unboxed-closures/unboxed-closures-generic.rs2
-rw-r--r--tests/ui/zero-sized/zero-sized-binary-heap-push.rs1
-rw-r--r--tests/ui/zero-sized/zero-sized-linkedlist-push.rs1
549 files changed, 4315 insertions, 2831 deletions
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 190fae95652..5755ae8a8bc 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -676,6 +676,19 @@ impl Pat {
         });
         could_be_never_pattern
     }
+
+    /// Whether this contains a `!` pattern. This in particular means that a feature gate error will
+    /// be raised if the feature is off. Used to avoid gating the feature twice.
+    pub fn contains_never_pattern(&self) -> bool {
+        let mut contains_never_pattern = false;
+        self.walk(&mut |pat| {
+            if matches!(pat.kind, PatKind::Never) {
+                contains_never_pattern = true;
+            }
+            true
+        });
+        contains_never_pattern
+    }
 }
 
 /// A single field in a struct pattern.
diff --git a/compiler/rustc_ast/src/attr/mod.rs b/compiler/rustc_ast/src/attr/mod.rs
index 851ab46345f..98138cedb24 100644
--- a/compiler/rustc_ast/src/attr/mod.rs
+++ b/compiler/rustc_ast/src/attr/mod.rs
@@ -387,7 +387,7 @@ impl MetaItemKind {
         tokens: &mut impl Iterator<Item = &'a TokenTree>,
     ) -> Option<MetaItemKind> {
         match tokens.next() {
-            Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
+            Some(TokenTree::Delimited(.., Delimiter::Invisible, inner_tokens)) => {
                 MetaItemKind::name_value_from_tokens(&mut inner_tokens.trees())
             }
             Some(TokenTree::Token(token, _)) => {
@@ -401,7 +401,7 @@ impl MetaItemKind {
         tokens: &mut iter::Peekable<impl Iterator<Item = &'a TokenTree>>,
     ) -> Option<MetaItemKind> {
         match tokens.peek() {
-            Some(TokenTree::Delimited(_, Delimiter::Parenthesis, inner_tokens)) => {
+            Some(TokenTree::Delimited(.., Delimiter::Parenthesis, inner_tokens)) => {
                 let inner_tokens = inner_tokens.clone();
                 tokens.next();
                 MetaItemKind::list_from_tokens(inner_tokens).map(MetaItemKind::List)
@@ -524,7 +524,7 @@ impl NestedMetaItem {
                 tokens.next();
                 return Some(NestedMetaItem::Lit(lit));
             }
-            Some(TokenTree::Delimited(_, Delimiter::Invisible, inner_tokens)) => {
+            Some(TokenTree::Delimited(.., Delimiter::Invisible, inner_tokens)) => {
                 tokens.next();
                 return NestedMetaItem::from_tokens(&mut inner_tokens.trees().peekable());
             }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index 41c4e024447..10b2025f937 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -7,10 +7,10 @@
 //! a `MutVisitor` renaming item names in a module will miss all of those
 //! that are created by the expansion of a macro.
 
+use crate::ast::*;
 use crate::ptr::P;
 use crate::token::{self, Token};
 use crate::tokenstream::*;
-use crate::{ast::*, StaticItem};
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -682,7 +682,7 @@ pub fn visit_attr_tt<T: MutVisitor>(tt: &mut AttrTokenTree, vis: &mut T) {
         AttrTokenTree::Token(token, _) => {
             visit_token(token, vis);
         }
-        AttrTokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
+        AttrTokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => {
             vis.visit_span(open);
             vis.visit_span(close);
             visit_attr_tts(tts, vis);
@@ -709,7 +709,7 @@ pub fn visit_tt<T: MutVisitor>(tt: &mut TokenTree, vis: &mut T) {
         TokenTree::Token(token, _) => {
             visit_token(token, vis);
         }
-        TokenTree::Delimited(DelimSpan { open, close }, _delim, tts) => {
+        TokenTree::Delimited(DelimSpan { open, close }, _spacing, _delim, tts) => {
             vis.visit_span(open);
             vis.visit_span(close);
             visit_tts(tts, vis);
diff --git a/compiler/rustc_ast/src/token.rs b/compiler/rustc_ast/src/token.rs
index a7c6f8c5d8c..b0cd2ec9815 100644
--- a/compiler/rustc_ast/src/token.rs
+++ b/compiler/rustc_ast/src/token.rs
@@ -13,7 +13,7 @@ use rustc_macros::HashStable_Generic;
 use rustc_span::symbol::{kw, sym};
 #[allow(hidden_glob_reexports)]
 use rustc_span::symbol::{Ident, Symbol};
-use rustc_span::{self, edition::Edition, Span, DUMMY_SP};
+use rustc_span::{edition::Edition, Span, DUMMY_SP};
 use std::borrow::Cow;
 use std::fmt;
 
diff --git a/compiler/rustc_ast/src/tokenstream.rs b/compiler/rustc_ast/src/tokenstream.rs
index 48854bbae24..4c0c496584e 100644
--- a/compiler/rustc_ast/src/tokenstream.rs
+++ b/compiler/rustc_ast/src/tokenstream.rs
@@ -46,7 +46,7 @@ pub enum TokenTree {
     /// delimiters are implicitly represented by `Delimited`.
     Token(Token, Spacing),
     /// A delimited sequence of token trees.
-    Delimited(DelimSpan, Delimiter, TokenStream),
+    Delimited(DelimSpan, DelimSpacing, Delimiter, TokenStream),
 }
 
 // Ensure all fields of `TokenTree` are `DynSend` and `DynSync`.
@@ -62,11 +62,11 @@ where
 }
 
 impl TokenTree {
-    /// Checks if this `TokenTree` is equal to the other, regardless of span information.
+    /// Checks if this `TokenTree` is equal to the other, regardless of span/spacing information.
     pub fn eq_unspanned(&self, other: &TokenTree) -> bool {
         match (self, other) {
             (TokenTree::Token(token, _), TokenTree::Token(token2, _)) => token.kind == token2.kind,
-            (TokenTree::Delimited(_, delim, tts), TokenTree::Delimited(_, delim2, tts2)) => {
+            (TokenTree::Delimited(.., delim, tts), TokenTree::Delimited(.., delim2, tts2)) => {
                 delim == delim2 && tts.eq_unspanned(tts2)
             }
             _ => false,
@@ -99,6 +99,11 @@ impl TokenTree {
         TokenTree::Token(Token::new(kind, span), Spacing::Joint)
     }
 
+    /// Create a `TokenTree::Token` with joint-hidden spacing.
+    pub fn token_joint_hidden(kind: TokenKind, span: Span) -> TokenTree {
+        TokenTree::Token(Token::new(kind, span), Spacing::JointHidden)
+    }
+
     pub fn uninterpolate(&self) -> Cow<'_, TokenTree> {
         match self {
             TokenTree::Token(token, spacing) => match token.uninterpolate() {
@@ -183,7 +188,7 @@ pub struct AttrTokenStream(pub Lrc<Vec<AttrTokenTree>>);
 #[derive(Clone, Debug, Encodable, Decodable)]
 pub enum AttrTokenTree {
     Token(Token, Spacing),
-    Delimited(DelimSpan, Delimiter, AttrTokenStream),
+    Delimited(DelimSpan, DelimSpacing, Delimiter, AttrTokenStream),
     /// Stores the attributes for an attribute target,
     /// along with the tokens for that attribute target.
     /// See `AttributesData` for more information
@@ -208,9 +213,14 @@ impl AttrTokenStream {
                 AttrTokenTree::Token(inner, spacing) => {
                     smallvec![TokenTree::Token(inner.clone(), *spacing)].into_iter()
                 }
-                AttrTokenTree::Delimited(span, delim, stream) => {
-                    smallvec![TokenTree::Delimited(*span, *delim, stream.to_tokenstream()),]
-                        .into_iter()
+                AttrTokenTree::Delimited(span, spacing, delim, stream) => {
+                    smallvec![TokenTree::Delimited(
+                        *span,
+                        *spacing,
+                        *delim,
+                        stream.to_tokenstream()
+                    ),]
+                    .into_iter()
                 }
                 AttrTokenTree::Attributes(data) => {
                     let idx = data
@@ -230,7 +240,7 @@ impl AttrTokenStream {
                         let mut found = false;
                         // Check the last two trees (to account for a trailing semi)
                         for tree in target_tokens.iter_mut().rev().take(2) {
-                            if let TokenTree::Delimited(span, delim, delim_tokens) = tree {
+                            if let TokenTree::Delimited(span, spacing, delim, delim_tokens) = tree {
                                 // Inner attributes are only supported on extern blocks, functions,
                                 // impls, and modules. All of these have their inner attributes
                                 // placed at the beginning of the rightmost outermost braced group:
@@ -250,7 +260,7 @@ impl AttrTokenStream {
                                     stream.push_stream(inner_attr.tokens());
                                 }
                                 stream.push_stream(delim_tokens.clone());
-                                *tree = TokenTree::Delimited(*span, *delim, stream);
+                                *tree = TokenTree::Delimited(*span, *spacing, *delim, stream);
                                 found = true;
                                 break;
                             }
@@ -303,21 +313,64 @@ pub struct AttributesData {
 #[derive(Clone, Debug, Default, Encodable, Decodable)]
 pub struct TokenStream(pub(crate) Lrc<Vec<TokenTree>>);
 
-/// Similar to `proc_macro::Spacing`, but for tokens.
-///
-/// Note that all `ast::TokenTree::Token` instances have a `Spacing`, but when
-/// we convert to `proc_macro::TokenTree` for proc macros only `Punct`
-/// `TokenTree`s have a `proc_macro::Spacing`.
+/// Indicates whether a token can join with the following token to form a
+/// compound token. Used for conversions to `proc_macro::Spacing`. Also used to
+/// guide pretty-printing, which is where the `JointHidden` value (which isn't
+/// part of `proc_macro::Spacing`) comes in useful.
 #[derive(Clone, Copy, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
 pub enum Spacing {
-    /// The token is not immediately followed by an operator token (as
-    /// determined by `Token::is_op`). E.g. a `+` token is `Alone` in `+ =`,
-    /// `+/*foo*/=`, `+ident`, and `+()`.
+    /// The token cannot join with the following token to form a compound
+    /// token.
+    ///
+    /// In token streams parsed from source code, the compiler will use `Alone`
+    /// for any token immediately followed by whitespace, a non-doc comment, or
+    /// EOF.
+    ///
+    /// When constructing token streams within the compiler, use this for each
+    /// token that (a) should be pretty-printed with a space after it, or (b)
+    /// is the last token in the stream. (In the latter case the choice of
+    /// spacing doesn't matter because it is never used for the last token. We
+    /// arbitrarily use `Alone`.)
+    ///
+    /// Converts to `proc_macro::Spacing::Alone`, and
+    /// `proc_macro::Spacing::Alone` converts back to this.
     Alone,
 
-    /// The token is immediately followed by an operator token. E.g. a `+`
-    /// token is `Joint` in `+=` and `++`.
+    /// The token can join with the following token to form a compound token.
+    ///
+    /// In token streams parsed from source code, the compiler will use `Joint`
+    /// for any token immediately followed by punctuation (as determined by
+    /// `Token::is_punct`).
+    ///
+    /// When constructing token streams within the compiler, use this for each
+    /// token that (a) should be pretty-printed without a space after it, and
+    /// (b) is followed by a punctuation token.
+    ///
+    /// Converts to `proc_macro::Spacing::Joint`, and
+    /// `proc_macro::Spacing::Joint` converts back to this.
     Joint,
+
+    /// The token can join with the following token to form a compound token,
+    /// but this will not be visible at the proc macro level. (This is what the
+    /// `Hidden` means; see below.)
+    ///
+    /// In token streams parsed from source code, the compiler will use
+    /// `JointHidden` for any token immediately followed by anything not
+    /// covered by the `Alone` and `Joint` cases: an identifier, lifetime,
+    /// literal, delimiter, doc comment.
+    ///
+    /// When constructing token streams, use this for each token that (a)
+    /// should be pretty-printed without a space after it, and (b) is followed
+    /// by a non-punctuation token.
+    ///
+    /// Converts to `proc_macro::Spacing::Alone`, but
+    /// `proc_macro::Spacing::Alone` converts back to `token::Spacing::Alone`.
+    /// Because of that, pretty-printing of `TokenStream`s produced by proc
+    /// macros is unavoidably uglier (with more whitespace between tokens) than
+    /// pretty-printing of `TokenStream`'s produced by other means (i.e. parsed
+    /// source code, internally constructed token streams, and token streams
+    /// produced by declarative macros).
+    JointHidden,
 }
 
 impl TokenStream {
@@ -421,21 +474,14 @@ impl TokenStream {
         self
     }
 
-    /// Create a token stream containing a single token with alone spacing.
+    /// Create a token stream containing a single token with alone spacing. The
+    /// spacing used for the final token in a constructed stream doesn't matter
+    /// because it's never used. In practice we arbitrarily use
+    /// `Spacing::Alone`.
     pub fn token_alone(kind: TokenKind, span: Span) -> TokenStream {
         TokenStream::new(vec![TokenTree::token_alone(kind, span)])
     }
 
-    /// Create a token stream containing a single token with joint spacing.
-    pub fn token_joint(kind: TokenKind, span: Span) -> TokenStream {
-        TokenStream::new(vec![TokenTree::token_joint(kind, span)])
-    }
-
-    /// Create a token stream containing a single `Delimited`.
-    pub fn delimited(span: DelimSpan, delim: Delimiter, tts: TokenStream) -> TokenStream {
-        TokenStream::new(vec![TokenTree::Delimited(span, delim, tts)])
-    }
-
     pub fn from_ast(node: &(impl HasAttrs + HasSpan + HasTokens + fmt::Debug)) -> TokenStream {
         let Some(tokens) = node.tokens() else {
             panic!("missing tokens for node at {:?}: {:?}", node.span(), node);
@@ -482,6 +528,7 @@ impl TokenStream {
             }
             token::Interpolated(nt) => TokenTree::Delimited(
                 DelimSpan::from_single(token.span),
+                DelimSpacing::new(Spacing::JointHidden, spacing),
                 Delimiter::Invisible,
                 TokenStream::from_nonterminal_ast(&nt.0).flattened(),
             ),
@@ -492,8 +539,8 @@ impl TokenStream {
     fn flatten_token_tree(tree: &TokenTree) -> TokenTree {
         match tree {
             TokenTree::Token(token, spacing) => TokenStream::flatten_token(token, *spacing),
-            TokenTree::Delimited(span, delim, tts) => {
-                TokenTree::Delimited(*span, *delim, tts.flattened())
+            TokenTree::Delimited(span, spacing, delim, tts) => {
+                TokenTree::Delimited(*span, *spacing, *delim, tts.flattened())
             }
         }
     }
@@ -503,7 +550,7 @@ impl TokenStream {
         fn can_skip(stream: &TokenStream) -> bool {
             stream.trees().all(|tree| match tree {
                 TokenTree::Token(token, _) => !matches!(token.kind, token::Interpolated(_)),
-                TokenTree::Delimited(_, _, inner) => can_skip(inner),
+                TokenTree::Delimited(.., inner) => can_skip(inner),
             })
         }
 
@@ -517,7 +564,7 @@ impl TokenStream {
     // If `vec` is not empty, try to glue `tt` onto its last token. The return
     // value indicates if gluing took place.
     fn try_glue_to_last(vec: &mut Vec<TokenTree>, tt: &TokenTree) -> bool {
-        if let Some(TokenTree::Token(last_tok, Spacing::Joint)) = vec.last()
+        if let Some(TokenTree::Token(last_tok, Spacing::Joint | Spacing::JointHidden)) = vec.last()
             && let TokenTree::Token(tok, spacing) = tt
             && let Some(glued_tok) = last_tok.glue(tok)
         {
@@ -592,9 +639,10 @@ impl TokenStream {
 
                     &TokenTree::Token(..) => i += 1,
 
-                    &TokenTree::Delimited(sp, delim, ref delim_stream) => {
+                    &TokenTree::Delimited(sp, spacing, delim, ref delim_stream) => {
                         if let Some(desugared_delim_stream) = desugar_inner(delim_stream.clone()) {
-                            let new_tt = TokenTree::Delimited(sp, delim, desugared_delim_stream);
+                            let new_tt =
+                                TokenTree::Delimited(sp, spacing, delim, desugared_delim_stream);
                             Lrc::make_mut(&mut stream.0)[i] = new_tt;
                             modified = true;
                         }
@@ -622,10 +670,11 @@ impl TokenStream {
                 num_of_hashes = cmp::max(num_of_hashes, count);
             }
 
-            // `/// foo` becomes `doc = r"foo"`.
+            // `/// foo` becomes `[doc = r"foo"]`.
             let delim_span = DelimSpan::from_single(span);
             let body = TokenTree::Delimited(
                 delim_span,
+                DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
                 Delimiter::Bracket,
                 [
                     TokenTree::token_alone(token::Ident(sym::doc, false), span),
@@ -641,7 +690,7 @@ impl TokenStream {
 
             if attr_style == AttrStyle::Inner {
                 vec![
-                    TokenTree::token_alone(token::Pound, span),
+                    TokenTree::token_joint(token::Pound, span),
                     TokenTree::token_alone(token::Not, span),
                     body,
                 ]
@@ -738,6 +787,18 @@ impl DelimSpan {
     }
 }
 
+#[derive(Copy, Clone, Debug, PartialEq, Encodable, Decodable, HashStable_Generic)]
+pub struct DelimSpacing {
+    pub open: Spacing,
+    pub close: Spacing,
+}
+
+impl DelimSpacing {
+    pub fn new(open: Spacing, close: Spacing) -> DelimSpacing {
+        DelimSpacing { open, close }
+    }
+}
+
 // Some types are used a lot. Make sure they don't unintentionally get bigger.
 #[cfg(all(target_arch = "x86_64", target_pointer_width = "64"))]
 mod size_asserts {
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index ce5214efaca..27f1b84f372 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -13,7 +13,7 @@
 //! instance, a walker looking for item names in a module will miss all of
 //! those that are created by the expansion of a macro.
 
-use crate::{ast::*, StaticItem};
+use crate::ast::*;
 
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index 99691f43f91..a44b408feec 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -8,7 +8,6 @@ use super::errors::{
 use super::ResolverAstLoweringExt;
 use super::{ImplTraitContext, LoweringContext, ParamMode, ParenthesizedGenericArgs};
 use crate::{FnDeclKind, ImplTraitPosition};
-use rustc_ast::attr;
 use rustc_ast::ptr::P as AstP;
 use rustc_ast::*;
 use rustc_data_structures::stack::ensure_sufficient_stack;
@@ -582,8 +581,11 @@ impl<'hir> LoweringContext<'_, 'hir> {
         } else {
             // Either `body.is_none()` or `is_never_pattern` here.
             if !is_never_pattern {
-                let suggestion = span.shrink_to_hi();
-                self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
+                if self.tcx.features().never_patterns {
+                    // If the feature is off we already emitted the error after parsing.
+                    let suggestion = span.shrink_to_hi();
+                    self.tcx.sess.emit_err(MatchArmWithNoBody { span, suggestion });
+                }
             } else if let Some(body) = &arm.body {
                 self.tcx.sess.emit_err(NeverPatternWithBody { span: body.span });
                 guard = None;
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index 8fa2cae43bf..6a82005c448 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -1,6 +1,6 @@
 use super::LoweringContext;
 use rustc_ast as ast;
-use rustc_ast::visit::{self, Visitor};
+use rustc_ast::visit::Visitor;
 use rustc_ast::*;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_hir as hir;
diff --git a/compiler/rustc_ast_lowering/src/index.rs b/compiler/rustc_ast_lowering/src/index.rs
index 1741611fb11..f042f46e59c 100644
--- a/compiler/rustc_ast_lowering/src/index.rs
+++ b/compiler/rustc_ast_lowering/src/index.rs
@@ -2,7 +2,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sorted_map::SortedMap;
 use rustc_hir as hir;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::*;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::span_bug;
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index b4c211eec69..d9663d50c59 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -45,7 +45,6 @@ extern crate tracing;
 use crate::errors::{AssocTyParentheses, AssocTyParenthesesSub, MisplacedImplTrait};
 
 use rustc_ast::ptr::P;
-use rustc_ast::visit;
 use rustc_ast::{self as ast, *};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::captures::Captures;
@@ -1575,8 +1574,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
                 Vec::new()
             }
             hir::OpaqueTyOrigin::FnReturn(..) => {
-                if let FnDeclKind::Impl | FnDeclKind::Trait =
-                    fn_kind.expect("expected RPITs to be lowered with a FnKind")
+                if matches!(
+                    fn_kind.expect("expected RPITs to be lowered with a FnKind"),
+                    FnDeclKind::Impl | FnDeclKind::Trait
+                ) || self.tcx.features().lifetime_capture_rules_2024
+                    || span.at_least_rust_2024()
                 {
                     // return-position impl trait in trait was decided to capture all
                     // in-scope lifetimes, which we collect for all opaques during resolution.
diff --git a/compiler/rustc_ast_passes/messages.ftl b/compiler/rustc_ast_passes/messages.ftl
index 876126b02ea..28bd6c2111b 100644
--- a/compiler/rustc_ast_passes/messages.ftl
+++ b/compiler/rustc_ast_passes/messages.ftl
@@ -174,6 +174,10 @@ ast_passes_item_underscore = `{$kind}` items in this context need a name
 ast_passes_keyword_lifetime =
     lifetimes cannot use keyword names
 
+ast_passes_match_arm_with_no_body =
+    `match` arm with no body
+    .suggestion = add a body after the pattern
+
 ast_passes_module_nonascii = trying to load file for module `{$name}` with non-ascii identifier name
     .help = consider using the `#[path]` attribute to specify filesystem path
 
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 1f9bc09f5f7..59cf18c2459 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -8,9 +8,9 @@
 
 use itertools::{Either, Itertools};
 use rustc_ast::ptr::P;
-use rustc_ast::visit::{self, AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
+use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor};
+use rustc_ast::walk_list;
 use rustc_ast::*;
-use rustc_ast::{walk_list, StaticItem};
 use rustc_ast_pretty::pprust::{self, State};
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_feature::Features;
diff --git a/compiler/rustc_ast_passes/src/errors.rs b/compiler/rustc_ast_passes/src/errors.rs
index 7f6fcb49317..928bf19759a 100644
--- a/compiler/rustc_ast_passes/src/errors.rs
+++ b/compiler/rustc_ast_passes/src/errors.rs
@@ -758,3 +758,12 @@ pub struct AnonStructOrUnionNotAllowed {
     pub span: Span,
     pub struct_or_union: &'static str,
 }
+
+#[derive(Diagnostic)]
+#[diag(ast_passes_match_arm_with_no_body)]
+pub struct MatchArmWithNoBody {
+    #[primary_span]
+    pub span: Span,
+    #[suggestion(code = " => todo!(),", applicability = "has-placeholders")]
+    pub suggestion: Span,
+}
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 897f35a5c4a..ac55c6cabd0 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -554,7 +554,34 @@ pub fn check_crate(krate: &ast::Crate, sess: &Session, features: &Features) {
     gate_all!(explicit_tail_calls, "`become` expression is experimental");
     gate_all!(generic_const_items, "generic const items are experimental");
     gate_all!(unnamed_fields, "unnamed fields are not yet fully implemented");
-    gate_all!(never_patterns, "`!` patterns are experimental");
+
+    if !visitor.features.never_patterns {
+        if let Some(spans) = spans.get(&sym::never_patterns) {
+            for &span in spans {
+                if span.allows_unstable(sym::never_patterns) {
+                    continue;
+                }
+                let sm = sess.source_map();
+                // We gate two types of spans: the span of a `!` pattern, and the span of a
+                // match arm without a body. For the latter we want to give the user a normal
+                // error.
+                if let Ok(snippet) = sm.span_to_snippet(span)
+                    && snippet == "!"
+                {
+                    feature_err(
+                        &sess.parse_sess,
+                        sym::never_patterns,
+                        span,
+                        "`!` patterns are experimental",
+                    )
+                    .emit();
+                } else {
+                    let suggestion = span.shrink_to_hi();
+                    sess.emit_err(errors::MatchArmWithNoBody { span, suggestion });
+                }
+            }
+        }
+    }
 
     if !visitor.features.negative_bounds {
         for &span in spans.get(&sym::negative_bounds).iter().copied().flatten() {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index ff36e6c2845..4a2a693862b 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -7,10 +7,11 @@ mod item;
 
 use crate::pp::Breaks::{Consistent, Inconsistent};
 use crate::pp::{self, Breaks};
+use crate::pprust::state::expr::FixupContext;
 use rustc_ast::attr::AttrIdGenerator;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, BinOpToken, CommentKind, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{TokenStream, TokenTree};
+use rustc_ast::tokenstream::{Spacing, TokenStream, TokenTree};
 use rustc_ast::util::classify;
 use rustc_ast::util::comments::{gather_comments, Comment, CommentStyle};
 use rustc_ast::util::parser;
@@ -183,10 +184,10 @@ fn space_between(tt1: &TokenTree, tt2: &TokenTree) -> bool {
         //
         // FIXME: Incorrect cases:
         // - Let: `let(a, b) = (1, 2)`
-        (Tok(Token { kind: Ident(..), .. }, _), Del(_, Parenthesis, _)) => false,
+        (Tok(Token { kind: Ident(..), .. }, _), Del(_, _, Parenthesis, _)) => false,
 
         // `#` + `[`: `#[attr]`
-        (Tok(Token { kind: Pound, .. }, _), Del(_, Bracket, _)) => false,
+        (Tok(Token { kind: Pound, .. }, _), Del(_, _, Bracket, _)) => false,
 
         _ => true,
     }
@@ -509,16 +510,17 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     /// appropriate macro, transcribe back into the grammar we just parsed from,
     /// and then pretty-print the resulting AST nodes (so, e.g., we print
     /// expression arguments as expressions). It can be done! I think.
-    fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) {
+    fn print_tt(&mut self, tt: &TokenTree, convert_dollar_crate: bool) -> Spacing {
         match tt {
-            TokenTree::Token(token, _) => {
+            TokenTree::Token(token, spacing) => {
                 let token_str = self.token_to_string_ext(token, convert_dollar_crate);
                 self.word(token_str);
                 if let token::DocComment(..) = token.kind {
                     self.hardbreak()
                 }
+                *spacing
             }
-            TokenTree::Delimited(dspan, delim, tts) => {
+            TokenTree::Delimited(dspan, spacing, delim, tts) => {
                 self.print_mac_common(
                     None,
                     false,
@@ -528,6 +530,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
                     convert_dollar_crate,
                     dspan.entire(),
                 );
+                spacing.close
             }
         }
     }
@@ -535,9 +538,20 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     fn print_tts(&mut self, tts: &TokenStream, convert_dollar_crate: bool) {
         let mut iter = tts.trees().peekable();
         while let Some(tt) = iter.next() {
-            self.print_tt(tt, convert_dollar_crate);
+            let spacing = self.print_tt(tt, convert_dollar_crate);
             if let Some(next) = iter.peek() {
-                if space_between(tt, next) {
+                // Should we print a space after `tt`? There are two guiding
+                // factors.
+                // - `spacing` is the more important and accurate one. Most
+                //   tokens have good spacing information, and
+                //   `Joint`/`JointHidden` get used a lot.
+                // - `space_between` is the backup. Code produced by proc
+                //   macros has worse spacing information, with no
+                //   `JointHidden` usage and too much `Alone` usage, which
+                //   would result in over-spaced output such as
+                //   `( x () , y . z )`. `space_between` avoids some of the
+                //   excess whitespace.
+                if spacing == Spacing::Alone && space_between(tt, next) {
                     self.space();
                 }
             }
@@ -798,7 +812,7 @@ pub trait PrintState<'a>: std::ops::Deref<Target = pp::Printer> + std::ops::Dere
     }
 
     fn expr_to_string(&self, e: &ast::Expr) -> String {
-        Self::to_string(|s| s.print_expr(e))
+        Self::to_string(|s| s.print_expr(e, FixupContext::default()))
     }
 
     fn meta_item_lit_to_string(&self, lit: &ast::MetaItemLit) -> String {
@@ -903,7 +917,7 @@ impl<'a> State<'a> {
     }
 
     fn commasep_exprs(&mut self, b: Breaks, exprs: &[P<ast::Expr>]) {
-        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e), |e| e.span)
+        self.commasep_cmnt(b, exprs, |s, e| s.print_expr(e, FixupContext::default()), |e| e.span)
     }
 
     pub fn print_opt_lifetime(&mut self, lifetime: &Option<ast::Lifetime>) {
@@ -940,7 +954,7 @@ impl<'a> State<'a> {
         match generic_arg {
             GenericArg::Lifetime(lt) => self.print_lifetime(*lt),
             GenericArg::Type(ty) => self.print_type(ty),
-            GenericArg::Const(ct) => self.print_expr(&ct.value),
+            GenericArg::Const(ct) => self.print_expr(&ct.value, FixupContext::default()),
         }
     }
 
@@ -1007,12 +1021,12 @@ impl<'a> State<'a> {
                 self.word("[");
                 self.print_type(ty);
                 self.word("; ");
-                self.print_expr(&length.value);
+                self.print_expr(&length.value, FixupContext::default());
                 self.word("]");
             }
             ast::TyKind::Typeof(e) => {
                 self.word("typeof(");
-                self.print_expr(&e.value);
+                self.print_expr(&e.value, FixupContext::default());
                 self.word(")");
             }
             ast::TyKind::Infer => {
@@ -1068,7 +1082,7 @@ impl<'a> State<'a> {
                 if let Some((init, els)) = loc.kind.init_else_opt() {
                     self.nbsp();
                     self.word_space("=");
-                    self.print_expr(init);
+                    self.print_expr(init, FixupContext::default());
                     if let Some(els) = els {
                         self.cbox(INDENT_UNIT);
                         self.ibox(INDENT_UNIT);
@@ -1082,14 +1096,14 @@ impl<'a> State<'a> {
             ast::StmtKind::Item(item) => self.print_item(item),
             ast::StmtKind::Expr(expr) => {
                 self.space_if_not_bol();
-                self.print_expr_outer_attr_style(expr, false);
+                self.print_expr_outer_attr_style(expr, false, FixupContext::default());
                 if classify::expr_requires_semi_to_be_stmt(expr) {
                     self.word(";");
                 }
             }
             ast::StmtKind::Semi(expr) => {
                 self.space_if_not_bol();
-                self.print_expr_outer_attr_style(expr, false);
+                self.print_expr_outer_attr_style(expr, false, FixupContext::default());
                 self.word(";");
             }
             ast::StmtKind::Empty => {
@@ -1141,7 +1155,7 @@ impl<'a> State<'a> {
                 ast::StmtKind::Expr(expr) if i == blk.stmts.len() - 1 => {
                     self.maybe_print_comment(st.span.lo());
                     self.space_if_not_bol();
-                    self.print_expr_outer_attr_style(expr, false);
+                    self.print_expr_outer_attr_style(expr, false, FixupContext::default());
                     self.maybe_print_trailing_comment(expr.span, Some(blk.span.hi()));
                 }
                 _ => self.print_stmt(st),
@@ -1154,13 +1168,41 @@ impl<'a> State<'a> {
     }
 
     /// Print a `let pat = expr` expression.
-    fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr) {
+    ///
+    /// Parentheses are inserted surrounding `expr` if a round-trip through the
+    /// parser would otherwise work out the wrong way in a condition position.
+    ///
+    /// For example each of the following would mean the wrong thing without
+    /// parentheses.
+    ///
+    /// ```ignore (illustrative)
+    /// if let _ = (Struct {}) {}
+    ///
+    /// if let _ = (true && false) {}
+    /// ```
+    ///
+    /// In a match guard, the second case still requires parens, but the first
+    /// case no longer does because anything until `=>` is considered part of
+    /// the match guard expression. Parsing of the expression is not terminated
+    /// by `{` in that position.
+    ///
+    /// ```ignore (illustrative)
+    /// match () {
+    ///     () if let _ = Struct {} => {}
+    ///     () if let _ = (true && false) => {}
+    /// }
+    /// ```
+    fn print_let(&mut self, pat: &ast::Pat, expr: &ast::Expr, fixup: FixupContext) {
         self.word("let ");
         self.print_pat(pat);
         self.space();
         self.word_space("=");
-        let npals = || parser::needs_par_as_let_scrutinee(expr.precedence().order());
-        self.print_expr_cond_paren(expr, Self::cond_needs_par(expr) || npals())
+        self.print_expr_cond_paren(
+            expr,
+            fixup.parenthesize_exterior_struct_lit && parser::contains_exterior_struct_lit(expr)
+                || parser::needs_par_as_let_scrutinee(expr.precedence().order()),
+            FixupContext::default(),
+        );
     }
 
     fn print_mac(&mut self, m: &ast::MacCall) {
@@ -1207,7 +1249,7 @@ impl<'a> State<'a> {
                         print_reg_or_class(s, reg);
                         s.pclose();
                         s.space();
-                        s.print_expr(expr);
+                        s.print_expr(expr, FixupContext::default());
                     }
                     InlineAsmOperand::Out { reg, late, expr } => {
                         s.word(if *late { "lateout" } else { "out" });
@@ -1216,7 +1258,7 @@ impl<'a> State<'a> {
                         s.pclose();
                         s.space();
                         match expr {
-                            Some(expr) => s.print_expr(expr),
+                            Some(expr) => s.print_expr(expr, FixupContext::default()),
                             None => s.word("_"),
                         }
                     }
@@ -1226,7 +1268,7 @@ impl<'a> State<'a> {
                         print_reg_or_class(s, reg);
                         s.pclose();
                         s.space();
-                        s.print_expr(expr);
+                        s.print_expr(expr, FixupContext::default());
                     }
                     InlineAsmOperand::SplitInOut { reg, late, in_expr, out_expr } => {
                         s.word(if *late { "inlateout" } else { "inout" });
@@ -1234,18 +1276,18 @@ impl<'a> State<'a> {
                         print_reg_or_class(s, reg);
                         s.pclose();
                         s.space();
-                        s.print_expr(in_expr);
+                        s.print_expr(in_expr, FixupContext::default());
                         s.space();
                         s.word_space("=>");
                         match out_expr {
-                            Some(out_expr) => s.print_expr(out_expr),
+                            Some(out_expr) => s.print_expr(out_expr, FixupContext::default()),
                             None => s.word("_"),
                         }
                     }
                     InlineAsmOperand::Const { anon_const } => {
                         s.word("const");
                         s.space();
-                        s.print_expr(&anon_const.value);
+                        s.print_expr(&anon_const.value, FixupContext::default());
                     }
                     InlineAsmOperand::Sym { sym } => {
                         s.word("sym");
@@ -1439,10 +1481,10 @@ impl<'a> State<'a> {
                     self.print_pat(inner);
                 }
             }
-            PatKind::Lit(e) => self.print_expr(e),
+            PatKind::Lit(e) => self.print_expr(e, FixupContext::default()),
             PatKind::Range(begin, end, Spanned { node: end_kind, .. }) => {
                 if let Some(e) = begin {
-                    self.print_expr(e);
+                    self.print_expr(e, FixupContext::default());
                 }
                 match end_kind {
                     RangeEnd::Included(RangeSyntax::DotDotDot) => self.word("..."),
@@ -1450,7 +1492,7 @@ impl<'a> State<'a> {
                     RangeEnd::Excluded => self.word(".."),
                 }
                 if let Some(e) = end {
-                    self.print_expr(e);
+                    self.print_expr(e, FixupContext::default());
                 }
             }
             PatKind::Slice(elts) => {
@@ -1604,7 +1646,7 @@ impl<'a> State<'a> {
                     if let Some(default) = default {
                         s.space();
                         s.word_space("=");
-                        s.print_expr(&default.value);
+                        s.print_expr(&default.value, FixupContext::default());
                     }
                 }
             }
@@ -1797,7 +1839,9 @@ impl<'a> State<'a> {
     }
 
     pub(crate) fn tt_to_string(&self, tt: &TokenTree) -> String {
-        Self::to_string(|s| s.print_tt(tt, false))
+        Self::to_string(|s| {
+            s.print_tt(tt, false);
+        })
     }
 
     pub(crate) fn tts_to_string(&self, tokens: &TokenStream) -> String {
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
index 5397278bbb1..f5ffcddb83d 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/expr.rs
@@ -12,6 +12,19 @@ use rustc_ast::{
 };
 use std::fmt::Write;
 
+#[derive(Copy, Clone, Debug)]
+pub(crate) struct FixupContext {
+    pub parenthesize_exterior_struct_lit: bool,
+}
+
+/// The default amount of fixing is minimal fixing. Fixups should be turned on
+/// in a targetted fashion where needed.
+impl Default for FixupContext {
+    fn default() -> Self {
+        FixupContext { parenthesize_exterior_struct_lit: false }
+    }
+}
+
 impl<'a> State<'a> {
     fn print_else(&mut self, els: Option<&ast::Expr>) {
         if let Some(_else) = els {
@@ -55,21 +68,22 @@ impl<'a> State<'a> {
         self.pclose()
     }
 
-    fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8) {
-        self.print_expr_cond_paren(expr, expr.precedence().order() < prec)
+    fn print_expr_maybe_paren(&mut self, expr: &ast::Expr, prec: i8, fixup: FixupContext) {
+        self.print_expr_cond_paren(expr, expr.precedence().order() < prec, fixup);
     }
 
     /// Prints an expr using syntax that's acceptable in a condition position, such as the `cond` in
     /// `if cond { ... }`.
     fn print_expr_as_cond(&mut self, expr: &ast::Expr) {
-        self.print_expr_cond_paren(expr, Self::cond_needs_par(expr))
+        let fixup = FixupContext { parenthesize_exterior_struct_lit: true };
+        self.print_expr_cond_paren(expr, Self::cond_needs_par(expr), fixup)
     }
 
     /// Does `expr` need parentheses when printed in a condition position?
     ///
     /// These cases need parens due to the parse error observed in #26461: `if return {}`
     /// parses as the erroneous construct `if (return {})`, not `if (return) {}`.
-    pub(super) fn cond_needs_par(expr: &ast::Expr) -> bool {
+    fn cond_needs_par(expr: &ast::Expr) -> bool {
         match expr.kind {
             ast::ExprKind::Break(..)
             | ast::ExprKind::Closure(..)
@@ -80,11 +94,32 @@ impl<'a> State<'a> {
     }
 
     /// Prints `expr` or `(expr)` when `needs_par` holds.
-    pub(super) fn print_expr_cond_paren(&mut self, expr: &ast::Expr, needs_par: bool) {
+    pub(super) fn print_expr_cond_paren(
+        &mut self,
+        expr: &ast::Expr,
+        needs_par: bool,
+        fixup: FixupContext,
+    ) {
         if needs_par {
             self.popen();
         }
-        self.print_expr(expr);
+
+        // If we are surrounding the whole cond in parentheses, such as:
+        //
+        //     if (return Struct {}) {}
+        //
+        // then there is no need for parenthesizing the individual struct
+        // expressions within. On the other hand if the whole cond is not
+        // parenthesized, then print_expr must parenthesize exterior struct
+        // literals.
+        //
+        //     if x == (Struct {}) {}
+        //
+        let fixup = FixupContext {
+            parenthesize_exterior_struct_lit: fixup.parenthesize_exterior_struct_lit && !needs_par,
+        };
+        self.print_expr(expr, fixup);
+
         if needs_par {
             self.pclose();
         }
@@ -111,7 +146,7 @@ impl<'a> State<'a> {
             self.ibox(0);
             self.print_block_with_attrs(block, attrs);
         } else {
-            self.print_expr(&expr.value);
+            self.print_expr(&expr.value, FixupContext::default());
         }
         self.end();
     }
@@ -119,9 +154,9 @@ impl<'a> State<'a> {
     fn print_expr_repeat(&mut self, element: &ast::Expr, count: &ast::AnonConst) {
         self.ibox(INDENT_UNIT);
         self.word("[");
-        self.print_expr(element);
+        self.print_expr(element, FixupContext::default());
         self.word_space(";");
-        self.print_expr(&count.value);
+        self.print_expr(&count.value, FixupContext::default());
         self.word("]");
         self.end();
     }
@@ -161,7 +196,7 @@ impl<'a> State<'a> {
                 self.print_ident(field.ident);
                 self.word_nbsp(":");
             }
-            self.print_expr(&field.expr);
+            self.print_expr(&field.expr, FixupContext::default());
             if !is_last || has_rest {
                 self.word_space(",");
             } else {
@@ -174,7 +209,7 @@ impl<'a> State<'a> {
             }
             self.word("..");
             if let ast::StructRest::Base(expr) = rest {
-                self.print_expr(expr);
+                self.print_expr(expr, FixupContext::default());
             }
             self.space();
         }
@@ -192,13 +227,13 @@ impl<'a> State<'a> {
         self.pclose()
     }
 
-    fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>]) {
+    fn print_expr_call(&mut self, func: &ast::Expr, args: &[P<ast::Expr>], fixup: FixupContext) {
         let prec = match func.kind {
             ast::ExprKind::Field(..) => parser::PREC_FORCE_PAREN,
             _ => parser::PREC_POSTFIX,
         };
 
-        self.print_expr_maybe_paren(func, prec);
+        self.print_expr_maybe_paren(func, prec, fixup);
         self.print_call_post(args)
     }
 
@@ -207,8 +242,9 @@ impl<'a> State<'a> {
         segment: &ast::PathSegment,
         receiver: &ast::Expr,
         base_args: &[P<ast::Expr>],
+        fixup: FixupContext,
     ) {
-        self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX);
+        self.print_expr_maybe_paren(receiver, parser::PREC_POSTFIX, fixup);
         self.word(".");
         self.print_ident(segment.ident);
         if let Some(args) = &segment.args {
@@ -217,7 +253,13 @@ impl<'a> State<'a> {
         self.print_call_post(base_args)
     }
 
-    fn print_expr_binary(&mut self, op: ast::BinOp, lhs: &ast::Expr, rhs: &ast::Expr) {
+    fn print_expr_binary(
+        &mut self,
+        op: ast::BinOp,
+        lhs: &ast::Expr,
+        rhs: &ast::Expr,
+        fixup: FixupContext,
+    ) {
         let assoc_op = AssocOp::from_ast_binop(op.node);
         let prec = assoc_op.precedence() as i8;
         let fixity = assoc_op.fixity();
@@ -253,15 +295,15 @@ impl<'a> State<'a> {
             _ => left_prec,
         };
 
-        self.print_expr_maybe_paren(lhs, left_prec);
+        self.print_expr_maybe_paren(lhs, left_prec, fixup);
         self.space();
         self.word_space(op.node.as_str());
-        self.print_expr_maybe_paren(rhs, right_prec)
+        self.print_expr_maybe_paren(rhs, right_prec, fixup)
     }
 
-    fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr) {
+    fn print_expr_unary(&mut self, op: ast::UnOp, expr: &ast::Expr, fixup: FixupContext) {
         self.word(op.as_str());
-        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
+        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup)
     }
 
     fn print_expr_addr_of(
@@ -269,6 +311,7 @@ impl<'a> State<'a> {
         kind: ast::BorrowKind,
         mutability: ast::Mutability,
         expr: &ast::Expr,
+        fixup: FixupContext,
     ) {
         self.word("&");
         match kind {
@@ -278,14 +321,19 @@ impl<'a> State<'a> {
                 self.print_mutability(mutability, true);
             }
         }
-        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX)
+        self.print_expr_maybe_paren(expr, parser::PREC_PREFIX, fixup)
     }
 
-    pub(super) fn print_expr(&mut self, expr: &ast::Expr) {
-        self.print_expr_outer_attr_style(expr, true)
+    pub(super) fn print_expr(&mut self, expr: &ast::Expr, fixup: FixupContext) {
+        self.print_expr_outer_attr_style(expr, true, fixup)
     }
 
-    pub(super) fn print_expr_outer_attr_style(&mut self, expr: &ast::Expr, is_inline: bool) {
+    pub(super) fn print_expr_outer_attr_style(
+        &mut self,
+        expr: &ast::Expr,
+        is_inline: bool,
+        fixup: FixupContext,
+    ) {
         self.maybe_print_comment(expr.span.lo());
 
         let attrs = &expr.attrs;
@@ -314,19 +362,19 @@ impl<'a> State<'a> {
                 self.print_expr_tup(exprs);
             }
             ast::ExprKind::Call(func, args) => {
-                self.print_expr_call(func, args);
+                self.print_expr_call(func, args, fixup);
             }
             ast::ExprKind::MethodCall(box ast::MethodCall { seg, receiver, args, .. }) => {
-                self.print_expr_method_call(seg, receiver, args);
+                self.print_expr_method_call(seg, receiver, args, fixup);
             }
             ast::ExprKind::Binary(op, lhs, rhs) => {
-                self.print_expr_binary(*op, lhs, rhs);
+                self.print_expr_binary(*op, lhs, rhs, fixup);
             }
             ast::ExprKind::Unary(op, expr) => {
-                self.print_expr_unary(*op, expr);
+                self.print_expr_unary(*op, expr, fixup);
             }
             ast::ExprKind::AddrOf(k, m, expr) => {
-                self.print_expr_addr_of(*k, *m, expr);
+                self.print_expr_addr_of(*k, *m, expr, fixup);
             }
             ast::ExprKind::Lit(token_lit) => {
                 self.print_token_literal(*token_lit, expr.span);
@@ -337,7 +385,7 @@ impl<'a> State<'a> {
             }
             ast::ExprKind::Cast(expr, ty) => {
                 let prec = AssocOp::As.precedence() as i8;
-                self.print_expr_maybe_paren(expr, prec);
+                self.print_expr_maybe_paren(expr, prec, fixup);
                 self.space();
                 self.word_space("as");
                 self.print_type(ty);
@@ -345,7 +393,7 @@ impl<'a> State<'a> {
             ast::ExprKind::Type(expr, ty) => {
                 self.word("type_ascribe!(");
                 self.ibox(0);
-                self.print_expr(expr);
+                self.print_expr(expr, FixupContext::default());
 
                 self.word(",");
                 self.space_if_not_bol();
@@ -355,7 +403,7 @@ impl<'a> State<'a> {
                 self.word(")");
             }
             ast::ExprKind::Let(pat, scrutinee, _, _) => {
-                self.print_let(pat, scrutinee);
+                self.print_let(pat, scrutinee, fixup);
             }
             ast::ExprKind::If(test, blk, elseopt) => self.print_if(test, blk, elseopt.as_deref()),
             ast::ExprKind::While(test, blk, opt_label) => {
@@ -428,7 +476,7 @@ impl<'a> State<'a> {
 
                 self.print_fn_params_and_ret(fn_decl, true);
                 self.space();
-                self.print_expr(body);
+                self.print_expr(body, FixupContext::default());
                 self.end(); // need to close a box
 
                 // a box will be closed by print_expr, but we didn't want an overall
@@ -456,33 +504,33 @@ impl<'a> State<'a> {
                 self.print_block_with_attrs(blk, attrs);
             }
             ast::ExprKind::Await(expr, _) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
                 self.word(".await");
             }
             ast::ExprKind::Assign(lhs, rhs, _) => {
                 let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_maybe_paren(lhs, prec + 1);
+                self.print_expr_maybe_paren(lhs, prec + 1, fixup);
                 self.space();
                 self.word_space("=");
-                self.print_expr_maybe_paren(rhs, prec);
+                self.print_expr_maybe_paren(rhs, prec, fixup);
             }
             ast::ExprKind::AssignOp(op, lhs, rhs) => {
                 let prec = AssocOp::Assign.precedence() as i8;
-                self.print_expr_maybe_paren(lhs, prec + 1);
+                self.print_expr_maybe_paren(lhs, prec + 1, fixup);
                 self.space();
                 self.word(op.node.as_str());
                 self.word_space("=");
-                self.print_expr_maybe_paren(rhs, prec);
+                self.print_expr_maybe_paren(rhs, prec, fixup);
             }
             ast::ExprKind::Field(expr, ident) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
                 self.word(".");
                 self.print_ident(*ident);
             }
             ast::ExprKind::Index(expr, index, _) => {
-                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX);
+                self.print_expr_maybe_paren(expr, parser::PREC_POSTFIX, fixup);
                 self.word("[");
-                self.print_expr(index);
+                self.print_expr(index, FixupContext::default());
                 self.word("]");
             }
             ast::ExprKind::Range(start, end, limits) => {
@@ -492,14 +540,14 @@ impl<'a> State<'a> {
                 // a "normal" binop gets parenthesized. (`LOr` is the lowest-precedence binop.)
                 let fake_prec = AssocOp::LOr.precedence() as i8;
                 if let Some(e) = start {
-                    self.print_expr_maybe_paren(e, fake_prec);
+                    self.print_expr_maybe_paren(e, fake_prec, fixup);
                 }
                 match limits {
                     ast::RangeLimits::HalfOpen => self.word(".."),
                     ast::RangeLimits::Closed => self.word("..="),
                 }
                 if let Some(e) = end {
-                    self.print_expr_maybe_paren(e, fake_prec);
+                    self.print_expr_maybe_paren(e, fake_prec, fixup);
                 }
             }
             ast::ExprKind::Underscore => self.word("_"),
@@ -513,7 +561,7 @@ impl<'a> State<'a> {
                 }
                 if let Some(expr) = opt_expr {
                     self.space();
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
                 }
             }
             ast::ExprKind::Continue(opt_label) => {
@@ -527,7 +575,7 @@ impl<'a> State<'a> {
                 self.word("return");
                 if let Some(expr) = result {
                     self.word(" ");
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
                 }
             }
             ast::ExprKind::Yeet(result) => {
@@ -536,13 +584,13 @@ impl<'a> State<'a> {
                 self.word("yeet");
                 if let Some(expr) = result {
                     self.word(" ");
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
                 }
             }
             ast::ExprKind::Become(result) => {
                 self.word("become");
                 self.word(" ");
-                self.print_expr_maybe_paren(result, parser::PREC_JUMP);
+                self.print_expr_maybe_paren(result, parser::PREC_JUMP, fixup);
             }
             ast::ExprKind::InlineAsm(a) => {
                 // FIXME: This should have its own syntax, distinct from a macro invocation.
@@ -557,7 +605,7 @@ impl<'a> State<'a> {
                 self.word(reconstruct_format_args_template_string(&fmt.template));
                 for arg in fmt.arguments.all_args() {
                     self.word_space(",");
-                    self.print_expr(&arg.expr);
+                    self.print_expr(&arg.expr, FixupContext::default());
                 }
                 self.end();
                 self.pclose();
@@ -584,7 +632,7 @@ impl<'a> State<'a> {
             ast::ExprKind::MacCall(m) => self.print_mac(m),
             ast::ExprKind::Paren(e) => {
                 self.popen();
-                self.print_expr(e);
+                self.print_expr(e, FixupContext::default());
                 self.pclose();
             }
             ast::ExprKind::Yield(e) => {
@@ -592,11 +640,11 @@ impl<'a> State<'a> {
 
                 if let Some(expr) = e {
                     self.space();
-                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP);
+                    self.print_expr_maybe_paren(expr, parser::PREC_JUMP, fixup);
                 }
             }
             ast::ExprKind::Try(e) => {
-                self.print_expr_maybe_paren(e, parser::PREC_POSTFIX);
+                self.print_expr_maybe_paren(e, parser::PREC_POSTFIX, fixup);
                 self.word("?")
             }
             ast::ExprKind::TryBlock(blk) => {
@@ -628,7 +676,7 @@ impl<'a> State<'a> {
         self.space();
         if let Some(e) = &arm.guard {
             self.word_space("if");
-            self.print_expr(e);
+            self.print_expr(e, FixupContext::default());
             self.space();
         }
 
@@ -652,7 +700,7 @@ impl<'a> State<'a> {
                 }
                 _ => {
                     self.end(); // Close the ibox for the pattern.
-                    self.print_expr(body);
+                    self.print_expr(body, FixupContext::default());
                     self.word(",");
                 }
             }
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index fd5b529b1d4..ea5d22a3448 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -1,4 +1,5 @@
 use crate::pp::Breaks::Inconsistent;
+use crate::pprust::state::expr::FixupContext;
 use crate::pprust::state::{AnnNode, PrintState, State, INDENT_UNIT};
 
 use ast::StaticItem;
@@ -97,7 +98,7 @@ impl<'a> State<'a> {
         self.end(); // end the head-ibox
         if let Some(body) = body {
             self.word_space("=");
-            self.print_expr(body);
+            self.print_expr(body, FixupContext::default());
         }
         self.print_where_clause(&generics.where_clause);
         self.word(";");
@@ -514,7 +515,7 @@ impl<'a> State<'a> {
         if let Some(d) = &v.disr_expr {
             self.space();
             self.word_space("=");
-            self.print_expr(&d.value)
+            self.print_expr(&d.value, FixupContext::default())
         }
     }
 
diff --git a/compiler/rustc_borrowck/src/dataflow.rs b/compiler/rustc_borrowck/src/dataflow.rs
index 1b544b53012..1bd891bdd68 100644
--- a/compiler/rustc_borrowck/src/dataflow.rs
+++ b/compiler/rustc_borrowck/src/dataflow.rs
@@ -10,7 +10,7 @@ use rustc_middle::ty::RegionVid;
 use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::{EverInitializedPlaces, MaybeUninitializedPlaces};
 use rustc_mir_dataflow::ResultsVisitable;
-use rustc_mir_dataflow::{self, fmt::DebugWithContext, GenKill};
+use rustc_mir_dataflow::{fmt::DebugWithContext, GenKill};
 use rustc_mir_dataflow::{Analysis, AnalysisDomain, Results};
 use std::fmt;
 
diff --git a/compiler/rustc_borrowck/src/region_infer/graphviz.rs b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
index a0cf22e935a..408c8390e76 100644
--- a/compiler/rustc_borrowck/src/region_infer/graphviz.rs
+++ b/compiler/rustc_borrowck/src/region_infer/graphviz.rs
@@ -8,7 +8,6 @@ use std::borrow::Cow;
 use std::io::{self, Write};
 
 use super::*;
-use crate::constraints::OutlivesConstraint;
 use rustc_graphviz as dot;
 
 impl<'tcx> RegionInferenceContext<'tcx> {
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index ecc9905e33e..e782221a4c2 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -24,7 +24,6 @@ use rustc_infer::infer::{
 };
 use rustc_middle::mir::tcx::PlaceTy;
 use rustc_middle::mir::visit::{NonMutatingUseContext, PlaceContext, Visitor};
-use rustc_middle::mir::AssertKind;
 use rustc_middle::mir::*;
 use rustc_middle::traits::query::NoSolution;
 use rustc_middle::traits::ObligationCause;
diff --git a/compiler/rustc_builtin_macros/src/assert/context.rs b/compiler/rustc_builtin_macros/src/assert/context.rs
index 2a4bfe9e200..b54e119189a 100644
--- a/compiler/rustc_builtin_macros/src/assert/context.rs
+++ b/compiler/rustc_builtin_macros/src/assert/context.rs
@@ -151,7 +151,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
     fn build_panic(&self, expr_str: &str, panic_path: Path) -> P<Expr> {
         let escaped_expr_str = escape_to_fmt(expr_str);
         let initial = [
-            TokenTree::token_alone(
+            TokenTree::token_joint_hidden(
                 token::Literal(token::Lit {
                     kind: token::LitKind::Str,
                     symbol: Symbol::intern(&if self.fmt_string.is_empty() {
@@ -170,7 +170,7 @@ impl<'cx, 'a> Context<'cx, 'a> {
         ];
         let captures = self.capture_decls.iter().flat_map(|cap| {
             [
-                TokenTree::token_alone(token::Ident(cap.ident.name, false), cap.ident.span),
+                TokenTree::token_joint_hidden(token::Ident(cap.ident.name, false), cap.ident.span),
                 TokenTree::token_alone(token::Comma, self.span),
             ]
         });
diff --git a/compiler/rustc_builtin_macros/src/env.rs b/compiler/rustc_builtin_macros/src/env.rs
index 8c2fa6ee95f..d772642b88b 100644
--- a/compiler/rustc_builtin_macros/src/env.rs
+++ b/compiler/rustc_builtin_macros/src/env.rs
@@ -13,6 +13,16 @@ use thin_vec::thin_vec;
 
 use crate::errors;
 
+fn lookup_env<'cx>(cx: &'cx ExtCtxt<'_>, var: Symbol) -> Option<Symbol> {
+    let var = var.as_str();
+    if let Some(value) = cx.sess.opts.logical_env.get(var) {
+        return Some(Symbol::intern(value));
+    }
+    // If the environment variable was not defined with the `--env` option, we try to retrieve it
+    // from rustc's environment.
+    env::var(var).ok().as_deref().map(Symbol::intern)
+}
+
 pub fn expand_option_env<'cx>(
     cx: &'cx mut ExtCtxt<'_>,
     sp: Span,
@@ -23,7 +33,7 @@ pub fn expand_option_env<'cx>(
     };
 
     let sp = cx.with_def_site_ctxt(sp);
-    let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
+    let value = lookup_env(cx, var);
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
@@ -77,7 +87,7 @@ pub fn expand_env<'cx>(
     };
 
     let span = cx.with_def_site_ctxt(sp);
-    let value = env::var(var.as_str()).ok().as_deref().map(Symbol::intern);
+    let value = lookup_env(cx, var);
     cx.sess.parse_sess.env_depinfo.borrow_mut().insert((var, value));
     let e = match value {
         None => {
diff --git a/compiler/rustc_builtin_macros/src/source_util.rs b/compiler/rustc_builtin_macros/src/source_util.rs
index 7ae4b1b59dc..37808854a56 100644
--- a/compiler/rustc_builtin_macros/src/source_util.rs
+++ b/compiler/rustc_builtin_macros/src/source_util.rs
@@ -5,11 +5,11 @@ use rustc_ast::tokenstream::TokenStream;
 use rustc_ast_pretty::pprust;
 use rustc_expand::base::{self, *};
 use rustc_expand::module::DirOwnership;
+use rustc_parse::new_parser_from_file;
 use rustc_parse::parser::{ForceCollect, Parser};
-use rustc_parse::{self, new_parser_from_file};
 use rustc_session::lint::builtin::INCOMPLETE_INCLUDE;
 use rustc_span::symbol::Symbol;
-use rustc_span::{self, Pos, Span};
+use rustc_span::{Pos, Span};
 
 use smallvec::SmallVec;
 use std::rc::Rc;
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 380556c3ca5..c5daf17abb9 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -2,7 +2,7 @@
 
 use rustc_ast as ast;
 use rustc_ast::entry::EntryPointType;
-use rustc_ast::mut_visit::{ExpectOne, *};
+use rustc_ast::mut_visit::*;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{walk_item, Visitor};
 use rustc_ast::{attr, ModKind};
diff --git a/compiler/rustc_codegen_cranelift/example/mini_core.rs b/compiler/rustc_codegen_cranelift/example/mini_core.rs
index 934e4b1786f..3607b7cd944 100644
--- a/compiler/rustc_codegen_cranelift/example/mini_core.rs
+++ b/compiler/rustc_codegen_cranelift/example/mini_core.rs
@@ -11,7 +11,7 @@
     thread_local
 )]
 #![no_core]
-#![allow(dead_code, internal_features)]
+#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
 
 #[lang = "sized"]
 pub trait Sized {}
diff --git a/compiler/rustc_codegen_cranelift/src/abi/comments.rs b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
index ade6968de2b..a318cae1722 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/comments.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/comments.rs
@@ -3,7 +3,6 @@
 
 use std::borrow::Cow;
 
-use rustc_middle::mir;
 use rustc_target::abi::call::PassMode;
 
 use crate::prelude::*;
diff --git a/compiler/rustc_codegen_cranelift/src/abi/mod.rs b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
index 0ff1473da43..2c194f6d6d3 100644
--- a/compiler/rustc_codegen_cranelift/src/abi/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/abi/mod.rs
@@ -6,7 +6,7 @@ mod returning;
 
 use std::borrow::Cow;
 
-use cranelift_codegen::ir::{AbiParam, SigRef};
+use cranelift_codegen::ir::SigRef;
 use cranelift_module::ModuleError;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::ty::layout::FnAbiOf;
diff --git a/compiler/rustc_codegen_cranelift/src/analyze.rs b/compiler/rustc_codegen_cranelift/src/analyze.rs
index 321612238ea..c5762638a6b 100644
--- a/compiler/rustc_codegen_cranelift/src/analyze.rs
+++ b/compiler/rustc_codegen_cranelift/src/analyze.rs
@@ -2,7 +2,6 @@
 
 use rustc_index::IndexVec;
 use rustc_middle::mir::StatementKind::*;
-use rustc_middle::ty::Ty;
 
 use crate::prelude::*;
 
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index 65f7ee6999a..9ffa006e59b 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -3,10 +3,9 @@
 use std::cmp::Ordering;
 
 use cranelift_module::*;
-use rustc_data_structures::fx::{FxHashMap, FxHashSet};
+use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir::interpret::{read_target_uint, AllocId, GlobalAlloc, Scalar};
-use rustc_middle::mir::ConstValue;
 use rustc_middle::ty::ScalarInt;
 
 use crate::prelude::*;
diff --git a/compiler/rustc_codegen_cranelift/src/inline_asm.rs b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
index 25d14319f57..73f4bc7c151 100644
--- a/compiler/rustc_codegen_cranelift/src/inline_asm.rs
+++ b/compiler/rustc_codegen_cranelift/src/inline_asm.rs
@@ -3,7 +3,6 @@
 use std::fmt::Write;
 
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_middle::mir::InlineAsmOperand;
 use rustc_span::sym;
 use rustc_target::asm::*;
 use target_lexicon::BinaryFormat;
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
index 659e6c133ef..dbd5db87511 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm.rs
@@ -1,7 +1,5 @@
 //! Emulate LLVM intrinsics
 
-use rustc_middle::ty::GenericArgsRef;
-
 use crate::intrinsics::*;
 use crate::prelude::*;
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
index ee098be1fce..e1e514dca44 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_aarch64.rs
@@ -1,7 +1,5 @@
 //! Emulate AArch64 LLVM intrinsics
 
-use rustc_middle::ty::GenericArgsRef;
-
 use crate::intrinsics::*;
 use crate::prelude::*;
 
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
index 07b95b7933d..99bb5c4eae2 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/llvm_x86.rs
@@ -1,7 +1,6 @@
 //! Emulate x86 LLVM intrinsics
 
 use rustc_ast::ast::{InlineAsmOptions, InlineAsmTemplatePiece};
-use rustc_middle::ty::GenericArgsRef;
 use rustc_target::asm::*;
 
 use crate::inline_asm::{codegen_inline_asm_inner, CInlineAsmOperand};
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
index 5997e6026b4..fe4f073f799 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/simd.rs
@@ -1,8 +1,6 @@
 //! Codegen `extern "platform-intrinsic"` intrinsics.
 
 use cranelift_codegen::ir::immediates::Offset32;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_span::Symbol;
 use rustc_target::abi::Endian;
 
 use super::*;
diff --git a/compiler/rustc_codegen_gcc/example/mini_core.rs b/compiler/rustc_codegen_gcc/example/mini_core.rs
index 34328520343..db94bc1c86a 100644
--- a/compiler/rustc_codegen_gcc/example/mini_core.rs
+++ b/compiler/rustc_codegen_gcc/example/mini_core.rs
@@ -4,7 +4,7 @@
     thread_local
 )]
 #![no_core]
-#![allow(dead_code, internal_features)]
+#![allow(dead_code, internal_features, ambiguous_wide_pointer_comparisons)]
 
 #[no_mangle]
 unsafe extern "C" fn _Unwind_Resume() {
diff --git a/compiler/rustc_codegen_llvm/src/abi.rs b/compiler/rustc_codegen_llvm/src/abi.rs
index b5f53f51838..97dc401251c 100644
--- a/compiler/rustc_codegen_llvm/src/abi.rs
+++ b/compiler/rustc_codegen_llvm/src/abi.rs
@@ -15,7 +15,6 @@ use rustc_middle::ty::layout::LayoutOf;
 pub use rustc_middle::ty::layout::{FAT_PTR_ADDR, FAT_PTR_EXTRA};
 use rustc_middle::ty::Ty;
 use rustc_session::config;
-use rustc_target::abi::call::ArgAbi;
 pub use rustc_target::abi::call::*;
 use rustc_target::abi::{self, HasDataLayout, Int};
 pub use rustc_target::spec::abi::Abi;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
index cf78fc56b49..98563673c30 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/metadata.rs
@@ -35,7 +35,7 @@ use rustc_middle::ty::{
 use rustc_session::config::{self, DebugInfo, Lto};
 use rustc_span::symbol::Symbol;
 use rustc_span::FileName;
-use rustc_span::{self, FileNameDisplayPreference, SourceFile};
+use rustc_span::{FileNameDisplayPreference, SourceFile};
 use rustc_symbol_mangling::typeid_for_trait_ref;
 use rustc_target::abi::{Align, Size};
 use smallvec::smallvec;
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 4832b147a54..a0ae1e9bf5d 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -32,7 +32,7 @@ use rustc_middle::ty::{self, Instance, ParamEnv, Ty, TypeVisitableExt};
 use rustc_session::config::{self, DebugInfo};
 use rustc_session::Session;
 use rustc_span::symbol::Symbol;
-use rustc_span::{self, BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span};
+use rustc_span::{BytePos, Pos, SourceFile, SourceFileAndLine, SourceFileHash, Span};
 use rustc_target::abi::Size;
 
 use libc::c_uint;
diff --git a/compiler/rustc_codegen_llvm/src/intrinsic.rs b/compiler/rustc_codegen_llvm/src/intrinsic.rs
index f16014e1361..23b424f25ba 100644
--- a/compiler/rustc_codegen_llvm/src/intrinsic.rs
+++ b/compiler/rustc_codegen_llvm/src/intrinsic.rs
@@ -10,7 +10,7 @@ use crate::value::Value;
 use rustc_codegen_ssa::base::{compare_simd_types, wants_msvc_seh, wants_wasm_eh};
 use rustc_codegen_ssa::common::{IntPredicate, TypeKind};
 use rustc_codegen_ssa::errors::{ExpectedPointerMutability, InvalidMonomorphization};
-use rustc_codegen_ssa::mir::operand::OperandRef;
+use rustc_codegen_ssa::mir::operand::{OperandRef, OperandValue};
 use rustc_codegen_ssa::mir::place::PlaceRef;
 use rustc_codegen_ssa::traits::*;
 use rustc_hir as hir;
@@ -946,6 +946,13 @@ fn generic_simd_intrinsic<'ll, 'tcx>(
         tcx.normalize_erasing_late_bound_regions(ty::ParamEnv::reveal_all(), callee_ty.fn_sig(tcx));
     let arg_tys = sig.inputs();
 
+    // Vectors must be immediates (non-power-of-2 #[repr(packed)] are not)
+    for (ty, arg) in arg_tys.iter().zip(args) {
+        if ty.is_simd() && !matches!(arg.val, OperandValue::Immediate(_)) {
+            return_error!(InvalidMonomorphization::SimdArgument { span, name, ty: *ty });
+        }
+    }
+
     if name == sym::simd_select_bitmask {
         let (len, _) = require_simd!(arg_tys[1], SimdArgument);
 
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 3e26e3653ea..bc0e3a82806 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -158,12 +158,12 @@ pub(super) fn get_metadata_xcoff<'a>(path: &Path, data: &'a [u8]) -> Result<&'a
         file.symbols().find(|sym| sym.name() == Ok(AIX_METADATA_SYMBOL_NAME))
     {
         let offset = metadata_symbol.address() as usize;
-        if offset < 4 {
+        if offset < 8 {
             return Err(format!("Invalid metadata symbol offset: {offset}"));
         }
         // The offset specifies the location of rustc metadata in the comment section.
-        // The metadata is preceded by a 4-byte length field.
-        let len = u32::from_be_bytes(info_data[(offset - 4)..offset].try_into().unwrap()) as usize;
+        // The metadata is preceded by a 8-byte length field.
+        let len = u64::from_le_bytes(info_data[(offset - 8)..offset].try_into().unwrap()) as usize;
         if offset + len > (info_data.len() as usize) {
             return Err(format!(
                 "Metadata at offset {offset} with size {len} is beyond .info section"
@@ -479,8 +479,8 @@ pub fn create_wrapper_file(
             file.section_mut(section).flags =
                 SectionFlags::Xcoff { s_flags: xcoff::STYP_INFO as u32 };
 
-            let len = data.len() as u32;
-            let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
+            let len = data.len() as u64;
+            let offset = file.append_section_data(section, &len.to_le_bytes(), 1);
             // Add a symbol referring to the data in .info section.
             file.add_symbol(Symbol {
                 name: AIX_METADATA_SYMBOL_NAME.into(),
@@ -524,7 +524,7 @@ pub fn create_compressed_metadata_file(
     symbol_name: &str,
 ) -> Vec<u8> {
     let mut packed_metadata = rustc_metadata::METADATA_HEADER.to_vec();
-    packed_metadata.write_all(&(metadata.raw_data().len() as u32).to_be_bytes()).unwrap();
+    packed_metadata.write_all(&(metadata.raw_data().len() as u64).to_le_bytes()).unwrap();
     packed_metadata.extend(metadata.raw_data());
 
     let Some(mut file) = create_object_file(sess) else {
@@ -599,12 +599,12 @@ pub fn create_compressed_metadata_file_for_xcoff(
         section: SymbolSection::Section(data_section),
         flags: SymbolFlags::None,
     });
-    let len = data.len() as u32;
-    let offset = file.append_section_data(section, &len.to_be_bytes(), 1);
+    let len = data.len() as u64;
+    let offset = file.append_section_data(section, &len.to_le_bytes(), 1);
     // Add a symbol referring to the rustc metadata.
     file.add_symbol(Symbol {
         name: AIX_METADATA_SYMBOL_NAME.into(),
-        value: offset + 4, // The metadata is preceded by a 4-byte length field.
+        value: offset + 8, // The metadata is preceded by a 8-byte length field.
         size: 0,
         kind: SymbolKind::Unknown,
         scope: SymbolScope::Dynamic,
diff --git a/compiler/rustc_codegen_ssa/src/mir/operand.rs b/compiler/rustc_codegen_ssa/src/mir/operand.rs
index d724f9503bb..feee3ac03d0 100644
--- a/compiler/rustc_codegen_ssa/src/mir/operand.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/operand.rs
@@ -155,7 +155,7 @@ impl<'a, 'tcx, V: CodegenObject> OperandRef<'tcx, V> {
             Abi::Scalar(s @ abi::Scalar::Initialized { .. }) => {
                 let size = s.size(bx);
                 assert_eq!(size, layout.size, "abi::Scalar size does not match layout size");
-                let val = read_scalar(offset, size, s, bx.backend_type(layout));
+                let val = read_scalar(offset, size, s, bx.immediate_backend_type(layout));
                 OperandRef { val: OperandValue::Immediate(val), layout }
             }
             Abi::ScalarPair(
diff --git a/compiler/rustc_codegen_ssa/src/mir/statement.rs b/compiler/rustc_codegen_ssa/src/mir/statement.rs
index 899e41265bb..a158fc6e260 100644
--- a/compiler/rustc_codegen_ssa/src/mir/statement.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/statement.rs
@@ -3,7 +3,6 @@ use rustc_middle::mir::NonDivergingIntrinsic;
 
 use super::FunctionCx;
 use super::LocalRef;
-use crate::traits::BuilderMethods;
 use crate::traits::*;
 
 impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index e48506bd083..2358caffc9b 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -384,10 +384,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         }
 
         // Compatible integer types (in particular, usize vs ptr-sized-u32/u64).
+        // `char` counts as `u32.`
         let int_ty = |ty: Ty<'tcx>| {
             Some(match ty.kind() {
                 ty::Int(ity) => (Integer::from_int_ty(&self.tcx, *ity), /* signed */ true),
                 ty::Uint(uty) => (Integer::from_uint_ty(&self.tcx, *uty), /* signed */ false),
+                ty::Char => (Integer::I32, /* signed */ false),
                 _ => return None,
             })
         };
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index e604f4c1aec..5380d3071d6 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -12,7 +12,7 @@ use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::GenericArgs;
 use rustc_middle::ty::{self, adjustment::PointerCoercion, Instance, InstanceDef, Ty, TyCtxt};
 use rustc_middle::ty::{TraitRef, TypeVisitableExt};
-use rustc_mir_dataflow::{self, Analysis};
+use rustc_mir_dataflow::Analysis;
 use rustc_span::{sym, Span, Symbol};
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::{self, ObligationCauseCode, ObligationCtxt, SelectionContext};
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index d5f418e1710..7e1cbfe6667 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -172,7 +172,7 @@ impl Qualif for NeedsNonConstDrop {
                 destruct_def_id,
                 [
                     ty::GenericArg::from(ty),
-                    ty::GenericArg::from(cx.tcx.expected_const_effect_param_for_body(cx.def_id())),
+                    ty::GenericArg::from(cx.tcx.expected_host_effect_param_for_body(cx.def_id())),
                 ],
             ),
         );
diff --git a/compiler/rustc_data_structures/src/fingerprint/tests.rs b/compiler/rustc_data_structures/src/fingerprint/tests.rs
index 09ec2622a65..e04af19abf2 100644
--- a/compiler/rustc_data_structures/src/fingerprint/tests.rs
+++ b/compiler/rustc_data_structures/src/fingerprint/tests.rs
@@ -1,5 +1,4 @@
 use super::*;
-use crate::stable_hasher::Hash64;
 
 // Check that `combine_commutative` is order independent.
 #[test]
diff --git a/compiler/rustc_data_structures/src/graph/implementation/tests.rs b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
index dc1ce1747bf..3ae5f5868f0 100644
--- a/compiler/rustc_data_structures/src/graph/implementation/tests.rs
+++ b/compiler/rustc_data_structures/src/graph/implementation/tests.rs
@@ -1,5 +1,4 @@
 use crate::graph::implementation::*;
-use std::fmt::Debug;
 
 type TestGraph = Graph<&'static str, &'static str>;
 
diff --git a/compiler/rustc_data_structures/src/intern/tests.rs b/compiler/rustc_data_structures/src/intern/tests.rs
index 09810a0850e..a85cd480a09 100644
--- a/compiler/rustc_data_structures/src/intern/tests.rs
+++ b/compiler/rustc_data_structures/src/intern/tests.rs
@@ -1,5 +1,4 @@
 use super::*;
-use std::cmp::Ordering;
 
 #[derive(Debug)]
 struct S(u32);
diff --git a/compiler/rustc_data_structures/src/obligation_forest/tests.rs b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
index bc252f772a1..d09c8e54436 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/tests.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/tests.rs
@@ -1,7 +1,6 @@
 use super::*;
 
 use std::fmt;
-use std::marker::PhantomData;
 
 impl<'a> super::ForestObligation for &'a str {
     type CacheKey = &'a str;
diff --git a/compiler/rustc_data_structures/src/sip128/tests.rs b/compiler/rustc_data_structures/src/sip128/tests.rs
index cc6d3b0f471..e9dd0f1176b 100644
--- a/compiler/rustc_data_structures/src/sip128/tests.rs
+++ b/compiler/rustc_data_structures/src/sip128/tests.rs
@@ -1,6 +1,6 @@
 use super::*;
 
-use std::hash::{Hash, Hasher};
+use std::hash::Hash;
 
 // Hash just the bytes of the slice, without length prefix
 struct Bytes<'a>(&'a [u8]);
diff --git a/compiler/rustc_error_codes/src/error_codes/E0705.md b/compiler/rustc_error_codes/src/error_codes/E0705.md
index eb76d1836fc..317f3a47eff 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0705.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0705.md
@@ -1,9 +1,11 @@
+#### Note: this error code is no longer emitted by the compiler.
+
 A `#![feature]` attribute was declared for a feature that is stable in the
 current edition, but not in all editions.
 
 Erroneous code example:
 
-```rust2018,compile_fail,E0705
+```compile_fail
 #![feature(rust_2018_preview)]
 #![feature(test_2018_feature)] // error: the feature
                                // `test_2018_feature` is
diff --git a/compiler/rustc_errors/src/json/tests.rs b/compiler/rustc_errors/src/json/tests.rs
index 1f9a2981e02..5f9e821a48c 100644
--- a/compiler/rustc_errors/src/json/tests.rs
+++ b/compiler/rustc_errors/src/json/tests.rs
@@ -1,11 +1,8 @@
 use super::*;
 
-use crate::json::JsonEmitter;
-use rustc_span::source_map::{FilePathMapping, SourceMap};
-
-use crate::emitter::{ColorConfig, HumanReadableErrorType};
-use crate::{Handler, TerminalUrl};
-use rustc_span::{BytePos, Span};
+use crate::emitter::ColorConfig;
+use crate::Handler;
+use rustc_span::BytePos;
 
 use std::str;
 
diff --git a/compiler/rustc_errors/src/markdown/tests/term.rs b/compiler/rustc_errors/src/markdown/tests/term.rs
index 6f68fb25a58..a0d956bf0cd 100644
--- a/compiler/rustc_errors/src/markdown/tests/term.rs
+++ b/compiler/rustc_errors/src/markdown/tests/term.rs
@@ -3,7 +3,6 @@ use std::path::PathBuf;
 use termcolor::{BufferWriter, ColorChoice};
 
 use super::*;
-use crate::markdown::MdStream;
 
 const INPUT: &str = include_str!("input.md");
 const OUTPUT_PATH: &[&str] = &[env!("CARGO_MANIFEST_DIR"), "src","markdown","tests","output.stdout"];
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index fc3f7b1d749..475dd348e7b 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -35,9 +35,6 @@ expand_explain_doc_comment_outer =
 expand_expr_repeat_no_syntax_vars =
     attempted to repeat an expression containing no syntax variables matched as repeating at this depth
 
-expand_feature_included_in_edition =
-    the feature `{$feature}` is included in the Rust {$edition} edition
-
 expand_feature_not_allowed =
     the feature `{$name}` is not in the list of allowed features
 
diff --git a/compiler/rustc_expand/src/base.rs b/compiler/rustc_expand/src/base.rs
index 74f46efb365..11db4bb4017 100644
--- a/compiler/rustc_expand/src/base.rs
+++ b/compiler/rustc_expand/src/base.rs
@@ -21,7 +21,7 @@ use rustc_errors::{
 use rustc_feature::Features;
 use rustc_lint_defs::builtin::PROC_MACRO_BACK_COMPAT;
 use rustc_lint_defs::{BufferedEarlyLint, BuiltinLintDiagnostics, RegisteredTools};
-use rustc_parse::{self, parser, MACRO_ARGUMENTS};
+use rustc_parse::{parser, MACRO_ARGUMENTS};
 use rustc_session::errors::report_lit_error;
 use rustc_session::{parse::ParseSess, Limit, Session};
 use rustc_span::def_id::{CrateNum, DefId, LocalDefId};
diff --git a/compiler/rustc_expand/src/config.rs b/compiler/rustc_expand/src/config.rs
index 5ccef343b17..0b56dbb2c19 100644
--- a/compiler/rustc_expand/src/config.rs
+++ b/compiler/rustc_expand/src/config.rs
@@ -1,25 +1,22 @@
 //! Conditional compilation stripping.
 
 use crate::errors::{
-    FeatureIncludedInEdition, FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg,
-    MalformedFeatureAttribute, MalformedFeatureAttributeHelp, RemoveExprNotSupported,
+    FeatureNotAllowed, FeatureRemoved, FeatureRemovedReason, InvalidCfg, MalformedFeatureAttribute,
+    MalformedFeatureAttributeHelp, RemoveExprNotSupported,
 };
 use rustc_ast::ptr::P;
 use rustc_ast::token::{Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree};
-use rustc_ast::tokenstream::{DelimSpan, Spacing};
+use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, DelimSpacing, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{LazyAttrTokenStream, TokenTree};
 use rustc_ast::NodeId;
 use rustc_ast::{self as ast, AttrStyle, Attribute, HasAttrs, HasTokens, MetaItem};
 use rustc_attr as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
-use rustc_data_structures::fx::FxHashSet;
 use rustc_feature::Features;
 use rustc_feature::{ACCEPTED_FEATURES, REMOVED_FEATURES, UNSTABLE_FEATURES};
 use rustc_parse::validate_attr;
 use rustc_session::parse::feature_err;
 use rustc_session::Session;
-use rustc_span::edition::ALL_EDITIONS;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 use thin_vec::ThinVec;
@@ -48,42 +45,6 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
 
     let mut features = Features::default();
 
-    // The edition from `--edition`.
-    let crate_edition = sess.edition();
-
-    // The maximum of (a) the edition from `--edition` and (b) any edition
-    // umbrella feature-gates declared in the code.
-    // - E.g. if `crate_edition` is 2015 but `rust_2018_preview` is present,
-    //   `feature_edition` is 2018
-    let mut features_edition = crate_edition;
-    for attr in krate_attrs {
-        for mi in feature_list(attr) {
-            if mi.is_word() {
-                let name = mi.name_or_empty();
-                let edition = ALL_EDITIONS.iter().find(|e| name == e.feature_name()).copied();
-                if let Some(edition) = edition
-                    && edition > features_edition
-                {
-                    features_edition = edition;
-                }
-            }
-        }
-    }
-
-    // Enable edition-dependent features based on `features_edition`.
-    // - E.g. enable `test_2018_feature` if `features_edition` is 2018 or higher
-    let mut edition_enabled_features = FxHashSet::default();
-    for f in UNSTABLE_FEATURES {
-        if let Some(edition) = f.feature.edition
-            && edition <= features_edition
-        {
-            // FIXME(Manishearth) there is currently no way to set lib features by
-            // edition.
-            edition_enabled_features.insert(f.feature.name);
-            (f.set_enabled)(&mut features);
-        }
-    }
-
     // Process all features declared in the code.
     for attr in krate_attrs {
         for mi in feature_list(attr) {
@@ -108,38 +69,6 @@ pub fn features(sess: &Session, krate_attrs: &[Attribute], crate_name: Symbol) -
                 }
             };
 
-            // If the declared feature is an edition umbrella feature-gate,
-            // warn if it was redundant w.r.t. `crate_edition`.
-            // - E.g. warn if `rust_2018_preview` is declared when
-            //   `crate_edition` is 2018
-            // - E.g. don't warn if `rust_2018_preview` is declared when
-            //   `crate_edition` is 2015.
-            if let Some(&edition) = ALL_EDITIONS.iter().find(|e| name == e.feature_name()) {
-                if edition <= crate_edition {
-                    sess.emit_warning(FeatureIncludedInEdition {
-                        span: mi.span(),
-                        feature: name,
-                        edition,
-                    });
-                }
-                features.set_declared_lang_feature(name, mi.span(), None);
-                continue;
-            }
-
-            // If the declared feature is edition-dependent and was already
-            // enabled due to `feature_edition`, give a warning.
-            // - E.g. warn if `test_2018_feature` is declared when
-            //   `feature_edition` is 2018 or higher.
-            if edition_enabled_features.contains(&name) {
-                sess.emit_warning(FeatureIncludedInEdition {
-                    span: mi.span(),
-                    feature: name,
-                    edition: features_edition,
-                });
-                features.set_declared_lang_feature(name, mi.span(), None);
-                continue;
-            }
-
             // If the declared feature has been removed, issue an error.
             if let Some(f) = REMOVED_FEATURES.iter().find(|f| name == f.feature.name) {
                 sess.emit_err(FeatureRemoved {
@@ -242,7 +171,7 @@ impl<'a> StripUnconfigured<'a> {
             stream.0.iter().all(|tree| match tree {
                 AttrTokenTree::Attributes(_) => false,
                 AttrTokenTree::Token(..) => true,
-                AttrTokenTree::Delimited(_, _, inner) => can_skip(inner),
+                AttrTokenTree::Delimited(.., inner) => can_skip(inner),
             })
         }
 
@@ -266,9 +195,9 @@ impl<'a> StripUnconfigured<'a> {
                         None.into_iter()
                     }
                 }
-                AttrTokenTree::Delimited(sp, delim, mut inner) => {
+                AttrTokenTree::Delimited(sp, spacing, delim, mut inner) => {
                     inner = self.configure_tokens(&inner);
-                    Some(AttrTokenTree::Delimited(sp, delim, inner)).into_iter()
+                    Some(AttrTokenTree::Delimited(sp, spacing, delim, inner)).into_iter()
                 }
                 AttrTokenTree::Token(ref token, _)
                     if let TokenKind::Interpolated(nt) = &token.kind =>
@@ -372,27 +301,32 @@ impl<'a> StripUnconfigured<'a> {
         };
         let pound_span = pound_token.span;
 
-        let mut trees = vec![AttrTokenTree::Token(pound_token, Spacing::Alone)];
-        if attr.style == AttrStyle::Inner {
-            // For inner attributes, we do the same thing for the `!` in `#![some_attr]`
-            let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) =
-                orig_trees.next().unwrap().clone()
-            else {
-                panic!("Bad tokens for attribute {attr:?}");
-            };
-            trees.push(AttrTokenTree::Token(bang_token, Spacing::Alone));
-        }
         // We don't really have a good span to use for the synthesized `[]`
         // in `#[attr]`, so just use the span of the `#` token.
         let bracket_group = AttrTokenTree::Delimited(
             DelimSpan::from_single(pound_span),
+            DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
             Delimiter::Bracket,
             item.tokens
                 .as_ref()
                 .unwrap_or_else(|| panic!("Missing tokens for {item:?}"))
                 .to_attr_token_stream(),
         );
-        trees.push(bracket_group);
+        let trees = if attr.style == AttrStyle::Inner {
+            // For inner attributes, we do the same thing for the `!` in `#![some_attr]`
+            let TokenTree::Token(bang_token @ Token { kind: TokenKind::Not, .. }, _) =
+                orig_trees.next().unwrap().clone()
+            else {
+                panic!("Bad tokens for attribute {attr:?}");
+            };
+            vec![
+                AttrTokenTree::Token(pound_token, Spacing::Joint),
+                AttrTokenTree::Token(bang_token, Spacing::JointHidden),
+                bracket_group,
+            ]
+        } else {
+            vec![AttrTokenTree::Token(pound_token, Spacing::JointHidden), bracket_group]
+        };
         let tokens = Some(LazyAttrTokenStream::new(AttrTokenStream::new(trees)));
         let attr = attr::mk_attr_from_item(
             &self.sess.parse_sess.attr_id_generator,
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index 6e919a8fa9f..2b43fae6852 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -1,7 +1,6 @@
 use rustc_ast::ast;
 use rustc_macros::Diagnostic;
 use rustc_session::Limit;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::{Ident, MacroRulesNormalizedIdent};
 use rustc_span::{Span, Symbol};
 use std::borrow::Cow;
@@ -169,15 +168,6 @@ pub(crate) struct TakesNoArguments<'a> {
 }
 
 #[derive(Diagnostic)]
-#[diag(expand_feature_included_in_edition, code = "E0705")]
-pub(crate) struct FeatureIncludedInEdition {
-    #[primary_span]
-    pub span: Span,
-    pub feature: Symbol,
-    pub edition: Edition,
-}
-
-#[derive(Diagnostic)]
 #[diag(expand_feature_removed, code = "E0557")]
 pub(crate) struct FeatureRemoved<'a> {
     #[primary_span]
diff --git a/compiler/rustc_expand/src/mbe.rs b/compiler/rustc_expand/src/mbe.rs
index a43b2a00188..ca4a1f327ad 100644
--- a/compiler/rustc_expand/src/mbe.rs
+++ b/compiler/rustc_expand/src/mbe.rs
@@ -13,7 +13,7 @@ pub(crate) mod transcribe;
 
 use metavar_expr::MetaVarExpr;
 use rustc_ast::token::{Delimiter, NonterminalKind, Token, TokenKind};
-use rustc_ast::tokenstream::DelimSpan;
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan};
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
@@ -68,7 +68,7 @@ pub(crate) enum KleeneOp {
 enum TokenTree {
     Token(Token),
     /// A delimited sequence, e.g. `($e:expr)` (RHS) or `{ $e }` (LHS).
-    Delimited(DelimSpan, Delimited),
+    Delimited(DelimSpan, DelimSpacing, Delimited),
     /// A kleene-style repetition sequence, e.g. `$($e:expr)*` (RHS) or `$($e),*` (LHS).
     Sequence(DelimSpan, SequenceRepetition),
     /// e.g., `$var`.
@@ -99,7 +99,7 @@ impl TokenTree {
             TokenTree::Token(Token { span, .. })
             | TokenTree::MetaVar(span, _)
             | TokenTree::MetaVarDecl(span, _, _) => span,
-            TokenTree::Delimited(span, _)
+            TokenTree::Delimited(span, ..)
             | TokenTree::MetaVarExpr(span, _)
             | TokenTree::Sequence(span, _) => span.entire(),
         }
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index 42c91824baf..0b1f25b67c8 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -290,7 +290,7 @@ fn check_binders(
         }
         // `MetaVarExpr` can not appear in the LHS of a macro arm
         TokenTree::MetaVarExpr(..) => {}
-        TokenTree::Delimited(_, ref del) => {
+        TokenTree::Delimited(.., ref del) => {
             for tt in &del.tts {
                 check_binders(sess, node_id, tt, macros, binders, ops, valid);
             }
@@ -353,7 +353,7 @@ fn check_occurrences(
             };
             check_ops_is_prefix(sess, node_id, macros, binders, ops, dl.entire(), name);
         }
-        TokenTree::Delimited(_, ref del) => {
+        TokenTree::Delimited(.., ref del) => {
             check_nested_occurrences(sess, node_id, &del.tts, macros, binders, ops, valid);
         }
         TokenTree::Sequence(_, ref seq) => {
@@ -435,8 +435,8 @@ fn check_nested_occurrences(
                 // We check that the meta-variable is correctly used.
                 check_occurrences(sess, node_id, tt, macros, binders, ops, valid);
             }
-            (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(_, del))
-            | (NestedMacroState::MacroName, TokenTree::Delimited(_, del))
+            (NestedMacroState::MacroRulesNotName, TokenTree::Delimited(.., del))
+            | (NestedMacroState::MacroName, TokenTree::Delimited(.., del))
                 if del.delim == Delimiter::Brace =>
             {
                 let macro_rules = state == NestedMacroState::MacroRulesNotName;
@@ -466,7 +466,7 @@ fn check_nested_occurrences(
                 // We check that the meta-variable is correctly used.
                 check_occurrences(sess, node_id, tt, macros, binders, ops, valid);
             }
-            (NestedMacroState::MacroName, TokenTree::Delimited(_, del))
+            (NestedMacroState::MacroName, TokenTree::Delimited(.., del))
                 if del.delim == Delimiter::Parenthesis =>
             {
                 state = NestedMacroState::MacroNameParen;
@@ -481,7 +481,7 @@ fn check_nested_occurrences(
                     valid,
                 );
             }
-            (NestedMacroState::MacroNameParen, TokenTree::Delimited(_, del))
+            (NestedMacroState::MacroNameParen, TokenTree::Delimited(.., del))
                 if del.delim == Delimiter::Brace =>
             {
                 state = NestedMacroState::Empty;
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 965beb9bf84..b248a1fe349 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -184,7 +184,7 @@ pub(super) fn compute_locs(matcher: &[TokenTree]) -> Vec<MatcherLoc> {
                 TokenTree::Token(token) => {
                     locs.push(MatcherLoc::Token { token: token.clone() });
                 }
-                TokenTree::Delimited(span, delimited) => {
+                TokenTree::Delimited(span, _, delimited) => {
                     let open_token = Token::new(token::OpenDelim(delimited.delim), span.open);
                     let close_token = Token::new(token::CloseDelim(delimited.delim), span.close);
 
@@ -335,7 +335,7 @@ pub(super) fn count_metavar_decls(matcher: &[TokenTree]) -> usize {
         .map(|tt| match tt {
             TokenTree::MetaVarDecl(..) => 1,
             TokenTree::Sequence(_, seq) => seq.num_captures,
-            TokenTree::Delimited(_, delim) => count_metavar_decls(&delim.tts),
+            TokenTree::Delimited(.., delim) => count_metavar_decls(&delim.tts),
             TokenTree::Token(..) => 0,
             TokenTree::MetaVar(..) | TokenTree::MetaVarExpr(..) => unreachable!(),
         })
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 19734394382..393eec3997b 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -207,7 +207,7 @@ fn expand_macro<'cx>(
     match try_success_result {
         Ok((i, named_matches)) => {
             let (rhs, rhs_span): (&mbe::Delimited, DelimSpan) = match &rhses[i] {
-                mbe::TokenTree::Delimited(span, delimited) => (&delimited, *span),
+                mbe::TokenTree::Delimited(span, _, delimited) => (&delimited, *span),
                 _ => cx.span_bug(sp, "malformed macro rhs"),
             };
             let arm_span = rhses[i].span();
@@ -589,7 +589,7 @@ pub fn compile_declarative_macro(
             .map(|lhs| {
                 // Ignore the delimiters around the matcher.
                 match lhs {
-                    mbe::TokenTree::Delimited(_, delimited) => {
+                    mbe::TokenTree::Delimited(.., delimited) => {
                         mbe::macro_parser::compute_locs(&delimited.tts)
                     }
                     _ => sess.diagnostic().span_bug(def.span, "malformed macro lhs"),
@@ -615,7 +615,7 @@ pub fn compile_declarative_macro(
 fn check_lhs_nt_follows(sess: &ParseSess, def: &ast::Item, lhs: &mbe::TokenTree) -> bool {
     // lhs is going to be like TokenTree::Delimited(...), where the
     // entire lhs is those tts. Or, it can be a "bare sequence", not wrapped in parens.
-    if let mbe::TokenTree::Delimited(_, delimited) = lhs {
+    if let mbe::TokenTree::Delimited(.., delimited) = lhs {
         check_matcher(sess, def, &delimited.tts)
     } else {
         let msg = "invalid macro matcher; matchers must be contained in balanced delimiters";
@@ -668,7 +668,7 @@ fn check_lhs_no_empty_seq(sess: &ParseSess, tts: &[mbe::TokenTree]) -> bool {
             | TokenTree::MetaVar(..)
             | TokenTree::MetaVarDecl(..)
             | TokenTree::MetaVarExpr(..) => (),
-            TokenTree::Delimited(_, del) => {
+            TokenTree::Delimited(.., del) => {
                 if !check_lhs_no_empty_seq(sess, &del.tts) {
                     return false;
                 }
@@ -709,14 +709,14 @@ fn check_matcher(sess: &ParseSess, def: &ast::Item, matcher: &[mbe::TokenTree])
 
 fn has_compile_error_macro(rhs: &mbe::TokenTree) -> bool {
     match rhs {
-        mbe::TokenTree::Delimited(_sp, d) => {
+        mbe::TokenTree::Delimited(.., d) => {
             let has_compile_error = d.tts.array_windows::<3>().any(|[ident, bang, args]| {
                 if let mbe::TokenTree::Token(ident) = ident
                     && let TokenKind::Ident(ident, _) = ident.kind
                     && ident == sym::compile_error
                     && let mbe::TokenTree::Token(bang) = bang
                     && let TokenKind::Not = bang.kind
-                    && let mbe::TokenTree::Delimited(_, del) = args
+                    && let mbe::TokenTree::Delimited(.., del) = args
                     && del.delim != Delimiter::Invisible
                 {
                     true
@@ -773,7 +773,7 @@ impl<'tt> FirstSets<'tt> {
                     | TokenTree::MetaVarExpr(..) => {
                         first.replace_with(TtHandle::TtRef(tt));
                     }
-                    TokenTree::Delimited(span, delimited) => {
+                    TokenTree::Delimited(span, _, delimited) => {
                         build_recur(sets, &delimited.tts);
                         first.replace_with(TtHandle::from_token_kind(
                             token::OpenDelim(delimited.delim),
@@ -842,7 +842,7 @@ impl<'tt> FirstSets<'tt> {
                     first.add_one(TtHandle::TtRef(tt));
                     return first;
                 }
-                TokenTree::Delimited(span, delimited) => {
+                TokenTree::Delimited(span, _, delimited) => {
                     first.add_one(TtHandle::from_token_kind(
                         token::OpenDelim(delimited.delim),
                         span.open,
@@ -1087,7 +1087,7 @@ fn check_matcher_core<'tt>(
                     suffix_first = build_suffix_first();
                 }
             }
-            TokenTree::Delimited(span, d) => {
+            TokenTree::Delimited(span, _, d) => {
                 let my_suffix = TokenSet::singleton(TtHandle::from_token_kind(
                     token::CloseDelim(d.delim),
                     span.close,
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index 7cb279a9812..c29edc3dc9f 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -35,7 +35,7 @@ impl MetaVarExpr {
     ) -> PResult<'sess, MetaVarExpr> {
         let mut tts = input.trees();
         let ident = parse_ident(&mut tts, sess, outer_span)?;
-        let Some(TokenTree::Delimited(_, Delimiter::Parenthesis, args)) = tts.next() else {
+        let Some(TokenTree::Delimited(.., Delimiter::Parenthesis, args)) = tts.next() else {
             let msg = "meta-variable expression parameter must be wrapped in parentheses";
             return Err(sess.span_diagnostic.struct_span_err(ident.span, msg));
         };
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 6a99412fc5b..ab9fb20b364 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -151,7 +151,7 @@ fn parse_tree<'a>(
             // during parsing.
             let mut next = outer_trees.next();
             let mut trees: Box<dyn Iterator<Item = &tokenstream::TokenTree>>;
-            if let Some(tokenstream::TokenTree::Delimited(_, Delimiter::Invisible, tts)) = next {
+            if let Some(tokenstream::TokenTree::Delimited(.., Delimiter::Invisible, tts)) = next {
                 trees = Box::new(tts.trees());
                 next = trees.next();
             } else {
@@ -160,7 +160,7 @@ fn parse_tree<'a>(
 
             match next {
                 // `tree` is followed by a delimited set of token trees.
-                Some(&tokenstream::TokenTree::Delimited(delim_span, delim, ref tts)) => {
+                Some(&tokenstream::TokenTree::Delimited(delim_span, _, delim, ref tts)) => {
                     if parsing_patterns {
                         if delim != Delimiter::Parenthesis {
                             span_dollar_dollar_or_metavar_in_the_lhs_err(
@@ -258,8 +258,9 @@ fn parse_tree<'a>(
 
         // `tree` is the beginning of a delimited set of tokens (e.g., `(` or `{`). We need to
         // descend into the delimited set and further parse it.
-        &tokenstream::TokenTree::Delimited(span, delim, ref tts) => TokenTree::Delimited(
+        &tokenstream::TokenTree::Delimited(span, spacing, delim, ref tts) => TokenTree::Delimited(
             span,
+            spacing,
             Delimited {
                 delim,
                 tts: parse(tts, parsing_patterns, sess, node_id, features, edition),
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index bc03fc0d1b1..18707cebcd5 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -7,7 +7,7 @@ use crate::mbe::macro_parser::{MatchedNonterminal, MatchedSeq, MatchedTokenTree,
 use crate::mbe::{self, MetaVarExpr};
 use rustc_ast::mut_visit::{self, MutVisitor};
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{pluralize, PResult};
 use rustc_errors::{DiagnosticBuilder, ErrorGuaranteed};
@@ -31,14 +31,24 @@ impl MutVisitor for Marker {
 
 /// An iterator over the token trees in a delimited token tree (`{ ... }`) or a sequence (`$(...)`).
 enum Frame<'a> {
-    Delimited { tts: &'a [mbe::TokenTree], idx: usize, delim: Delimiter, span: DelimSpan },
-    Sequence { tts: &'a [mbe::TokenTree], idx: usize, sep: Option<Token> },
+    Delimited {
+        tts: &'a [mbe::TokenTree],
+        idx: usize,
+        delim: Delimiter,
+        span: DelimSpan,
+        spacing: DelimSpacing,
+    },
+    Sequence {
+        tts: &'a [mbe::TokenTree],
+        idx: usize,
+        sep: Option<Token>,
+    },
 }
 
 impl<'a> Frame<'a> {
     /// Construct a new frame around the delimited set of tokens.
-    fn new(src: &'a mbe::Delimited, span: DelimSpan) -> Frame<'a> {
-        Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span }
+    fn new(src: &'a mbe::Delimited, span: DelimSpan, spacing: DelimSpacing) -> Frame<'a> {
+        Frame::Delimited { tts: &src.tts, idx: 0, delim: src.delim, span, spacing }
     }
 }
 
@@ -89,8 +99,10 @@ pub(super) fn transcribe<'a>(
     }
 
     // We descend into the RHS (`src`), expanding things as we go. This stack contains the things
-    // we have yet to expand/are still expanding. We start the stack off with the whole RHS.
-    let mut stack: SmallVec<[Frame<'_>; 1]> = smallvec![Frame::new(src, src_span)];
+    // we have yet to expand/are still expanding. We start the stack off with the whole RHS. The
+    // choice of spacing values doesn't matter.
+    let mut stack: SmallVec<[Frame<'_>; 1]> =
+        smallvec![Frame::new(src, src_span, DelimSpacing::new(Spacing::Alone, Spacing::Alone))];
 
     // As we descend in the RHS, we will need to be able to match nested sequences of matchers.
     // `repeats` keeps track of where we are in matching at each level, with the last element being
@@ -144,14 +156,19 @@ pub(super) fn transcribe<'a>(
                 // We are done processing a Delimited. If this is the top-level delimited, we are
                 // done. Otherwise, we unwind the result_stack to append what we have produced to
                 // any previous results.
-                Frame::Delimited { delim, span, .. } => {
+                Frame::Delimited { delim, span, mut spacing, .. } => {
+                    // Hack to force-insert a space after `]` in certain case.
+                    // See discussion of the `hex-literal` crate in #114571.
+                    if delim == Delimiter::Bracket {
+                        spacing.close = Spacing::Alone;
+                    }
                     if result_stack.is_empty() {
                         // No results left to compute! We are back at the top-level.
                         return Ok(TokenStream::new(result));
                     }
 
                     // Step back into the parent Delimited.
-                    let tree = TokenTree::Delimited(span, delim, TokenStream::new(result));
+                    let tree = TokenTree::Delimited(span, spacing, delim, TokenStream::new(result));
                     result = result_stack.pop().unwrap();
                     result.push(tree);
                 }
@@ -240,7 +257,7 @@ pub(super) fn transcribe<'a>(
                     // with modified syntax context. (I believe this supports nested macros).
                     marker.visit_span(&mut sp);
                     marker.visit_ident(&mut original_ident);
-                    result.push(TokenTree::token_alone(token::Dollar, sp));
+                    result.push(TokenTree::token_joint_hidden(token::Dollar, sp));
                     result.push(TokenTree::Token(
                         Token::from_ast_ident(original_ident),
                         Spacing::Alone,
@@ -258,13 +275,14 @@ pub(super) fn transcribe<'a>(
             // We will produce all of the results of the inside of the `Delimited` and then we will
             // jump back out of the Delimited, pop the result_stack and add the new results back to
             // the previous results (from outside the Delimited).
-            mbe::TokenTree::Delimited(mut span, delimited) => {
+            mbe::TokenTree::Delimited(mut span, spacing, delimited) => {
                 mut_visit::visit_delim_span(&mut span, &mut marker);
                 stack.push(Frame::Delimited {
                     tts: &delimited.tts,
                     delim: delimited.delim,
                     idx: 0,
                     span,
+                    spacing: *spacing,
                 });
                 result_stack.push(mem::take(&mut result));
             }
@@ -374,7 +392,7 @@ fn lockstep_iter_size(
 ) -> LockstepIterSize {
     use mbe::TokenTree;
     match tree {
-        TokenTree::Delimited(_, delimited) => {
+        TokenTree::Delimited(.., delimited) => {
             delimited.tts.iter().fold(LockstepIterSize::Unconstrained, |size, tt| {
                 size.with(lockstep_iter_size(tt, interpolations, repeats))
             })
diff --git a/compiler/rustc_expand/src/parse/tests.rs b/compiler/rustc_expand/src/parse/tests.rs
index bdc20882a9d..7a888250ca1 100644
--- a/compiler/rustc_expand/src/parse/tests.rs
+++ b/compiler/rustc_expand/src/parse/tests.rs
@@ -4,7 +4,7 @@ use crate::tests::{
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Token};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast::visit;
 use rustc_ast::{self as ast, PatKind};
 use rustc_ast_pretty::pprust::item_to_string;
@@ -77,14 +77,14 @@ fn string_to_tts_macro() {
                 TokenTree::Token(Token { kind: token::Ident(name_macro_rules, false), .. }, _),
                 TokenTree::Token(Token { kind: token::Not, .. }, _),
                 TokenTree::Token(Token { kind: token::Ident(name_zip, false), .. }, _),
-                TokenTree::Delimited(_, macro_delim, macro_tts),
+                TokenTree::Delimited(.., macro_delim, macro_tts),
             ] if name_macro_rules == &kw::MacroRules && name_zip.as_str() == "zip" => {
                 let tts = &macro_tts.trees().collect::<Vec<_>>();
                 match &tts[..] {
                     [
-                        TokenTree::Delimited(_, first_delim, first_tts),
+                        TokenTree::Delimited(.., first_delim, first_tts),
                         TokenTree::Token(Token { kind: token::FatArrow, .. }, _),
-                        TokenTree::Delimited(_, second_delim, second_tts),
+                        TokenTree::Delimited(.., second_delim, second_tts),
                     ] if macro_delim == &Delimiter::Parenthesis => {
                         let tts = &first_tts.trees().collect::<Vec<_>>();
                         match &tts[..] {
@@ -116,27 +116,36 @@ fn string_to_tts_macro() {
 #[test]
 fn string_to_tts_1() {
     create_default_session_globals_then(|| {
-        let tts = string_to_stream("fn a (b : i32) { b; }".to_string());
+        let tts = string_to_stream("fn a(b: i32) { b; }".to_string());
 
         let expected = TokenStream::new(vec![
             TokenTree::token_alone(token::Ident(kw::Fn, false), sp(0, 2)),
-            TokenTree::token_alone(token::Ident(Symbol::intern("a"), false), sp(3, 4)),
+            TokenTree::token_joint_hidden(token::Ident(Symbol::intern("a"), false), sp(3, 4)),
             TokenTree::Delimited(
-                DelimSpan::from_pair(sp(5, 6), sp(13, 14)),
+                DelimSpan::from_pair(sp(4, 5), sp(11, 12)),
+                // `JointHidden` because the `(` is followed immediately by
+                // `b`, `Alone` because the `)` is followed by whitespace.
+                DelimSpacing::new(Spacing::JointHidden, Spacing::Alone),
                 Delimiter::Parenthesis,
                 TokenStream::new(vec![
-                    TokenTree::token_alone(token::Ident(Symbol::intern("b"), false), sp(6, 7)),
-                    TokenTree::token_alone(token::Colon, sp(8, 9)),
-                    TokenTree::token_alone(token::Ident(sym::i32, false), sp(10, 13)),
+                    TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(5, 6)),
+                    TokenTree::token_alone(token::Colon, sp(6, 7)),
+                    // `JointHidden` because the `i32` is immediately followed by the `)`.
+                    TokenTree::token_joint_hidden(token::Ident(sym::i32, false), sp(8, 11)),
                 ])
                 .into(),
             ),
             TokenTree::Delimited(
-                DelimSpan::from_pair(sp(15, 16), sp(20, 21)),
+                DelimSpan::from_pair(sp(13, 14), sp(18, 19)),
+                // First `Alone` because the `{` is followed by whitespace,
+                // second `Alone` because the `}` is followed immediately by
+                // EOF.
+                DelimSpacing::new(Spacing::Alone, Spacing::Alone),
                 Delimiter::Brace,
                 TokenStream::new(vec![
-                    TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(17, 18)),
-                    TokenTree::token_alone(token::Semi, sp(18, 19)),
+                    TokenTree::token_joint(token::Ident(Symbol::intern("b"), false), sp(15, 16)),
+                    // `Alone` because the `;` is followed by whitespace.
+                    TokenTree::token_alone(token::Semi, sp(16, 17)),
                 ])
                 .into(),
             ),
diff --git a/compiler/rustc_expand/src/proc_macro_server.rs b/compiler/rustc_expand/src/proc_macro_server.rs
index b057a645f81..5308e338d7f 100644
--- a/compiler/rustc_expand/src/proc_macro_server.rs
+++ b/compiler/rustc_expand/src/proc_macro_server.rs
@@ -5,7 +5,7 @@ use pm::bridge::{
 use pm::{Delimiter, Level};
 use rustc_ast as ast;
 use rustc_ast::token;
-use rustc_ast::tokenstream::{self, Spacing::*, TokenStream};
+use rustc_ast::tokenstream::{self, DelimSpacing, Spacing, TokenStream};
 use rustc_ast::util::literal::escape_byte_str_symbol;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
@@ -98,7 +98,7 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
 
         while let Some(tree) = cursor.next() {
             let (Token { kind, span }, joint) = match tree.clone() {
-                tokenstream::TokenTree::Delimited(span, delim, tts) => {
+                tokenstream::TokenTree::Delimited(span, _, delim, tts) => {
                     let delimiter = pm::Delimiter::from_internal(delim);
                     trees.push(TokenTree::Group(Group {
                         delimiter,
@@ -111,7 +111,22 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     }));
                     continue;
                 }
-                tokenstream::TokenTree::Token(token, spacing) => (token, spacing == Joint),
+                tokenstream::TokenTree::Token(token, spacing) => {
+                    // Do not be tempted to check here that the `spacing`
+                    // values are "correct" w.r.t. the token stream (e.g. that
+                    // `Spacing::Joint` is actually followed by a `Punct` token
+                    // tree). Because the problem in #76399 was introduced that
+                    // way.
+                    //
+                    // This is where the `Hidden` in `JointHidden` applies,
+                    // because the jointness is effectively hidden from proc
+                    // macros.
+                    let joint = match spacing {
+                        Spacing::Alone | Spacing::JointHidden => false,
+                        Spacing::Joint => true,
+                    };
+                    (token, joint)
+                }
             };
 
             // Split the operator into one or more `Punct`s, one per character.
@@ -133,7 +148,8 @@ impl FromInternal<(TokenStream, &mut Rustc<'_, '_>)> for Vec<TokenTree<TokenStre
                     } else {
                         span
                     };
-                    TokenTree::Punct(Punct { ch, joint: if is_final { joint } else { true }, span })
+                    let joint = if is_final { joint } else { true };
+                    TokenTree::Punct(Punct { ch, joint, span })
                 }));
             };
 
@@ -268,6 +284,11 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
     fn to_internal(self) -> SmallVec<[tokenstream::TokenTree; 2]> {
         use rustc_ast::token::*;
 
+        // The code below is conservative, using `token_alone`/`Spacing::Alone`
+        // in most places. When the resulting code is pretty-printed by
+        // `print_tts` it ends up with spaces between most tokens, which is
+        // safe but ugly. It's hard in general to do better when working at the
+        // token level.
         let (tree, rustc) = self;
         match tree {
             TokenTree::Punct(Punct { ch, joint, span }) => {
@@ -296,6 +317,11 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                     b'\'' => SingleQuote,
                     _ => unreachable!(),
                 };
+                // We never produce `token::Spacing::JointHidden` here, which
+                // means the pretty-printing of code produced by proc macros is
+                // ugly, with lots of whitespace between tokens. This is
+                // unavoidable because `proc_macro::Spacing` only applies to
+                // `Punct` token trees.
                 smallvec![if joint {
                     tokenstream::TokenTree::token_joint(kind, span)
                 } else {
@@ -305,6 +331,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
             TokenTree::Group(Group { delimiter, stream, span: DelimSpan { open, close, .. } }) => {
                 smallvec![tokenstream::TokenTree::Delimited(
                     tokenstream::DelimSpan { open, close },
+                    DelimSpacing::new(Spacing::Alone, Spacing::Alone),
                     delimiter.to_internal(),
                     stream.unwrap_or_default(),
                 )]
@@ -322,7 +349,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                 let minus = BinOp(BinOpToken::Minus);
                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
                 let integer = TokenKind::lit(token::Integer, symbol, suffix);
-                let a = tokenstream::TokenTree::token_alone(minus, span);
+                let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
                 let b = tokenstream::TokenTree::token_alone(integer, span);
                 smallvec![a, b]
             }
@@ -335,7 +362,7 @@ impl ToInternal<SmallVec<[tokenstream::TokenTree; 2]>>
                 let minus = BinOp(BinOpToken::Minus);
                 let symbol = Symbol::intern(&symbol.as_str()[1..]);
                 let float = TokenKind::lit(token::Float, symbol, suffix);
-                let a = tokenstream::TokenTree::token_alone(minus, span);
+                let a = tokenstream::TokenTree::token_joint_hidden(minus, span);
                 let b = tokenstream::TokenTree::token_alone(float, span);
                 smallvec![a, b]
             }
@@ -546,7 +573,10 @@ impl server::TokenStream for Rustc<'_, '_> {
                         Ok(Self::TokenStream::from_iter([
                             // FIXME: The span of the `-` token is lost when
                             // parsing, so we cannot faithfully recover it here.
-                            tokenstream::TokenTree::token_alone(token::BinOp(token::Minus), e.span),
+                            tokenstream::TokenTree::token_joint_hidden(
+                                token::BinOp(token::Minus),
+                                e.span,
+                            ),
                             tokenstream::TokenTree::token_alone(token::Literal(*token_lit), e.span),
                         ]))
                     }
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 94e79144593..4993112089a 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -5,7 +5,7 @@ use rustc_span::symbol::sym;
 
 macro_rules! declare_features {
     ($(
-        $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr, None),
+        $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr),
     )+) => {
         /// Formerly unstable features that have now been accepted (stabilized).
         pub const ACCEPTED_FEATURES: &[Feature] = &[
@@ -13,7 +13,6 @@ macro_rules! declare_features {
                 name: sym::$feature,
                 since: $ver,
                 issue: to_nonzero($issue),
-                edition: None,
             }),+
         ];
     }
@@ -27,10 +26,10 @@ declare_features! (
 
     /// A temporary feature gate used to enable parser extensions needed
     /// to bootstrap fix for #5723.
-    (accepted, issue_5723_bootstrap, "1.0.0", None, None),
+    (accepted, issue_5723_bootstrap, "1.0.0", None),
     /// These are used to test this portion of the compiler,
     /// they don't actually mean anything.
-    (accepted, test_accepted_feature, "1.0.0", None, None),
+    (accepted, test_accepted_feature, "1.0.0", None),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
@@ -44,338 +43,338 @@ declare_features! (
     // -------------------------------------------------------------------------
 
     /// Allows `#[target_feature(...)]` on aarch64 platforms
-    (accepted, aarch64_target_feature, "1.61.0", Some(44839), None),
+    (accepted, aarch64_target_feature, "1.61.0", Some(44839)),
     /// Allows using the `efiapi` ABI.
-    (accepted, abi_efiapi, "1.68.0", Some(65815), None),
+    (accepted, abi_efiapi, "1.68.0", Some(65815)),
     /// Allows the sysV64 ABI to be specified on all platforms
     /// instead of just the platforms on which it is the C ABI.
-    (accepted, abi_sysv64, "1.24.0", Some(36167), None),
+    (accepted, abi_sysv64, "1.24.0", Some(36167)),
     /// Allows using the `thiscall` ABI.
-    (accepted, abi_thiscall, "1.73.0", None, None),
+    (accepted, abi_thiscall, "1.73.0", None),
     /// Allows using ADX intrinsics from `core::arch::{x86, x86_64}`.
-    (accepted, adx_target_feature, "1.61.0", Some(44839), None),
+    (accepted, adx_target_feature, "1.61.0", Some(44839)),
     /// Allows explicit discriminants on non-unit enum variants.
-    (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553), None),
+    (accepted, arbitrary_enum_discriminant, "1.66.0", Some(60553)),
     /// Allows using `sym` operands in inline assembly.
-    (accepted, asm_sym, "1.66.0", Some(93333), None),
+    (accepted, asm_sym, "1.66.0", Some(93333)),
     /// Allows the definition of associated constants in `trait` or `impl` blocks.
-    (accepted, associated_consts, "1.20.0", Some(29646), None),
+    (accepted, associated_consts, "1.20.0", Some(29646)),
     /// Allows using associated `type`s in `trait`s.
-    (accepted, associated_types, "1.0.0", None, None),
+    (accepted, associated_types, "1.0.0", None),
     /// Allows free and inherent `async fn`s, `async` blocks, and `<expr>.await` expressions.
-    (accepted, async_await, "1.39.0", Some(50547), None),
+    (accepted, async_await, "1.39.0", Some(50547)),
     /// Allows async functions to be declared, implemented, and used in traits.
-    (accepted, async_fn_in_trait, "1.75.0", Some(91611), None),
+    (accepted, async_fn_in_trait, "1.75.0", Some(91611)),
     /// Allows all literals in attribute lists and values of key-value pairs.
-    (accepted, attr_literals, "1.30.0", Some(34981), None),
+    (accepted, attr_literals, "1.30.0", Some(34981)),
     /// Allows overloading augmented assignment operations like `a += b`.
-    (accepted, augmented_assignments, "1.8.0", Some(28235), None),
+    (accepted, augmented_assignments, "1.8.0", Some(28235)),
     /// Allows mixing bind-by-move in patterns and references to those identifiers in guards.
-    (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287), None),
+    (accepted, bind_by_move_pattern_guards, "1.39.0", Some(15287)),
     /// Allows bindings in the subpattern of a binding pattern.
     /// For example, you can write `x @ Some(y)`.
-    (accepted, bindings_after_at, "1.56.0", Some(65490), None),
+    (accepted, bindings_after_at, "1.56.0", Some(65490)),
     /// Allows empty structs and enum variants with braces.
-    (accepted, braced_empty_structs, "1.8.0", Some(29720), None),
+    (accepted, braced_empty_structs, "1.8.0", Some(29720)),
     /// Allows `c"foo"` literals.
-    (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723), None),
+    (accepted, c_str_literals, "CURRENT_RUSTC_VERSION", Some(105723)),
     /// Allows `#[cfg_attr(predicate, multiple, attributes, here)]`.
-    (accepted, cfg_attr_multi, "1.33.0", Some(54881), None),
+    (accepted, cfg_attr_multi, "1.33.0", Some(54881)),
     /// Allows the use of `#[cfg(doctest)]`, set when rustdoc is collecting doctests.
-    (accepted, cfg_doctest, "1.40.0", Some(62210), None),
+    (accepted, cfg_doctest, "1.40.0", Some(62210)),
     /// Enables `#[cfg(panic = "...")]` config key.
-    (accepted, cfg_panic, "1.60.0", Some(77443), None),
+    (accepted, cfg_panic, "1.60.0", Some(77443)),
     /// Allows `cfg(target_feature = "...")`.
-    (accepted, cfg_target_feature, "1.27.0", Some(29717), None),
+    (accepted, cfg_target_feature, "1.27.0", Some(29717)),
     /// Allows `cfg(target_vendor = "...")`.
-    (accepted, cfg_target_vendor, "1.33.0", Some(29718), None),
+    (accepted, cfg_target_vendor, "1.33.0", Some(29718)),
     /// Allows implementing `Clone` for closures where possible (RFC 2132).
-    (accepted, clone_closures, "1.26.0", Some(44490), None),
+    (accepted, clone_closures, "1.26.0", Some(44490)),
     /// Allows coercing non capturing closures to function pointers.
-    (accepted, closure_to_fn_coercion, "1.19.0", Some(39817), None),
+    (accepted, closure_to_fn_coercion, "1.19.0", Some(39817)),
     /// Allows using the CMPXCHG16B target feature.
-    (accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839), None),
+    (accepted, cmpxchg16b_target_feature, "1.69.0", Some(44839)),
     /// Allows usage of the `compile_error!` macro.
-    (accepted, compile_error, "1.20.0", Some(40872), None),
+    (accepted, compile_error, "1.20.0", Some(40872)),
     /// Allows `impl Trait` in function return types.
-    (accepted, conservative_impl_trait, "1.26.0", Some(34511), None),
+    (accepted, conservative_impl_trait, "1.26.0", Some(34511)),
     /// Allows calling constructor functions in `const fn`.
-    (accepted, const_constructor, "1.40.0", Some(61456), None),
+    (accepted, const_constructor, "1.40.0", Some(61456)),
     /// Allows using and casting function pointers in a `const fn`.
-    (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563), None),
+    (accepted, const_fn_fn_ptr_basics, "1.61.0", Some(57563)),
     /// Allows trait bounds in `const fn`.
-    (accepted, const_fn_trait_bound, "1.61.0", Some(93706), None),
+    (accepted, const_fn_trait_bound, "1.61.0", Some(93706)),
     /// Allows calling `transmute` in const fn
-    (accepted, const_fn_transmute, "1.56.0", Some(53605), None),
+    (accepted, const_fn_transmute, "1.56.0", Some(53605)),
     /// Allows accessing fields of unions inside `const` functions.
-    (accepted, const_fn_union, "1.56.0", Some(51909), None),
+    (accepted, const_fn_union, "1.56.0", Some(51909)),
     /// Allows unsizing coercions in `const fn`.
-    (accepted, const_fn_unsize, "1.54.0", Some(64992), None),
+    (accepted, const_fn_unsize, "1.54.0", Some(64992)),
     /// Allows const generics to have default values (e.g. `struct Foo<const N: usize = 3>(...);`).
-    (accepted, const_generics_defaults, "1.59.0", Some(44580), None),
+    (accepted, const_generics_defaults, "1.59.0", Some(44580)),
     /// Allows the use of `if` and `match` in constants.
-    (accepted, const_if_match, "1.46.0", Some(49146), None),
+    (accepted, const_if_match, "1.46.0", Some(49146)),
     /// Allows argument and return position `impl Trait` in a `const fn`.
-    (accepted, const_impl_trait, "1.61.0", Some(77463), None),
+    (accepted, const_impl_trait, "1.61.0", Some(77463)),
     /// Allows indexing into constant arrays.
-    (accepted, const_indexing, "1.26.0", Some(29947), None),
+    (accepted, const_indexing, "1.26.0", Some(29947)),
     /// Allows let bindings, assignments and destructuring in `const` functions and constants.
     /// As long as control flow is not implemented in const eval, `&&` and `||` may not be used
     /// at the same time as let bindings.
-    (accepted, const_let, "1.33.0", Some(48821), None),
+    (accepted, const_let, "1.33.0", Some(48821)),
     /// Allows the use of `loop` and `while` in constants.
-    (accepted, const_loop, "1.46.0", Some(52000), None),
+    (accepted, const_loop, "1.46.0", Some(52000)),
     /// Allows panicking during const eval (producing compile-time errors).
-    (accepted, const_panic, "1.57.0", Some(51999), None),
+    (accepted, const_panic, "1.57.0", Some(51999)),
     /// Allows dereferencing raw pointers during const eval.
-    (accepted, const_raw_ptr_deref, "1.58.0", Some(51911), None),
+    (accepted, const_raw_ptr_deref, "1.58.0", Some(51911)),
     /// Allows implementing `Copy` for closures where possible (RFC 2132).
-    (accepted, copy_closures, "1.26.0", Some(44490), None),
+    (accepted, copy_closures, "1.26.0", Some(44490)),
     /// Allows `crate` in paths.
-    (accepted, crate_in_paths, "1.30.0", Some(45477), None),
+    (accepted, crate_in_paths, "1.30.0", Some(45477)),
     /// Allows using `#[debugger_visualizer]` attribute.
-    (accepted, debugger_visualizer, "1.71.0", Some(95939), None),
+    (accepted, debugger_visualizer, "1.71.0", Some(95939)),
     /// Allows rustc to inject a default alloc_error_handler
-    (accepted, default_alloc_error_handler, "1.68.0", Some(66741), None),
+    (accepted, default_alloc_error_handler, "1.68.0", Some(66741)),
     /// Allows using assigning a default type to type parameters in algebraic data type definitions.
-    (accepted, default_type_params, "1.0.0", None, None),
+    (accepted, default_type_params, "1.0.0", None),
     /// Allows `#[deprecated]` attribute.
-    (accepted, deprecated, "1.9.0", Some(29935), None),
+    (accepted, deprecated, "1.9.0", Some(29935)),
     /// Allows `#[derive(Default)]` and `#[default]` on enums.
-    (accepted, derive_default_enum, "1.62.0", Some(86985), None),
+    (accepted, derive_default_enum, "1.62.0", Some(86985)),
     /// Allows the use of destructuring assignments.
-    (accepted, destructuring_assignment, "1.59.0", Some(71126), None),
+    (accepted, destructuring_assignment, "1.59.0", Some(71126)),
     /// Allows `#[doc(alias = "...")]`.
-    (accepted, doc_alias, "1.48.0", Some(50146), None),
+    (accepted, doc_alias, "1.48.0", Some(50146)),
     /// Allows `..` in tuple (struct) patterns.
-    (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627), None),
+    (accepted, dotdot_in_tuple_patterns, "1.14.0", Some(33627)),
     /// Allows `..=` in patterns (RFC 1192).
-    (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237), None),
+    (accepted, dotdoteq_in_patterns, "1.26.0", Some(28237)),
     /// Allows `Drop` types in constants (RFC 1440).
-    (accepted, drop_types_in_const, "1.22.0", Some(33156), None),
+    (accepted, drop_types_in_const, "1.22.0", Some(33156)),
     /// Allows using `dyn Trait` as a syntax for trait objects.
-    (accepted, dyn_trait, "1.27.0", Some(44662), None),
+    (accepted, dyn_trait, "1.27.0", Some(44662)),
     /// Allows integer match exhaustiveness checking (RFC 2591).
-    (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907), None),
+    (accepted, exhaustive_integer_patterns, "1.33.0", Some(50907)),
     /// Allows explicit generic arguments specification with `impl Trait` present.
-    (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701), None),
+    (accepted, explicit_generic_args_with_impl_trait, "1.63.0", Some(83701)),
     /// Allows arbitrary expressions in key-value attributes at parse time.
-    (accepted, extended_key_value_attributes, "1.54.0", Some(78835), None),
+    (accepted, extended_key_value_attributes, "1.54.0", Some(78835)),
     /// Allows resolving absolute paths as paths from other crates.
-    (accepted, extern_absolute_paths, "1.30.0", Some(44660), None),
+    (accepted, extern_absolute_paths, "1.30.0", Some(44660)),
     /// Allows `extern crate foo as bar;`. This puts `bar` into extern prelude.
-    (accepted, extern_crate_item_prelude, "1.31.0", Some(55599), None),
+    (accepted, extern_crate_item_prelude, "1.31.0", Some(55599)),
     /// Allows `extern crate self as foo;`.
     /// This puts local crate root into extern prelude under name `foo`.
-    (accepted, extern_crate_self, "1.34.0", Some(56409), None),
+    (accepted, extern_crate_self, "1.34.0", Some(56409)),
     /// Allows access to crate names passed via `--extern` through prelude.
-    (accepted, extern_prelude, "1.30.0", Some(44660), None),
+    (accepted, extern_prelude, "1.30.0", Some(44660)),
     /// Allows using F16C intrinsics from `core::arch::{x86, x86_64}`.
-    (accepted, f16c_target_feature, "1.68.0", Some(44839), None),
+    (accepted, f16c_target_feature, "1.68.0", Some(44839)),
     /// Allows field shorthands (`x` meaning `x: x`) in struct literal expressions.
-    (accepted, field_init_shorthand, "1.17.0", Some(37340), None),
+    (accepted, field_init_shorthand, "1.17.0", Some(37340)),
     /// Allows `#[must_use]` on functions, and introduces must-use operators (RFC 1940).
-    (accepted, fn_must_use, "1.27.0", Some(43302), None),
+    (accepted, fn_must_use, "1.27.0", Some(43302)),
     /// Allows capturing variables in scope using format_args!
-    (accepted, format_args_capture, "1.58.0", Some(67984), None),
+    (accepted, format_args_capture, "1.58.0", Some(67984)),
     /// Allows associated types to be generic, e.g., `type Foo<T>;` (RFC 1598).
-    (accepted, generic_associated_types, "1.65.0", Some(44265), None),
+    (accepted, generic_associated_types, "1.65.0", Some(44265)),
     /// Allows attributes on lifetime/type formal parameters in generics (RFC 1327).
-    (accepted, generic_param_attrs, "1.27.0", Some(48848), None),
+    (accepted, generic_param_attrs, "1.27.0", Some(48848)),
     /// Allows the `#[global_allocator]` attribute.
-    (accepted, global_allocator, "1.28.0", Some(27389), None),
+    (accepted, global_allocator, "1.28.0", Some(27389)),
     // FIXME: explain `globs`.
-    (accepted, globs, "1.0.0", None, None),
+    (accepted, globs, "1.0.0", None),
     /// Allows using `..=X` as a pattern.
-    (accepted, half_open_range_patterns, "1.66.0", Some(67264), None),
+    (accepted, half_open_range_patterns, "1.66.0", Some(67264)),
     /// Allows using the `u128` and `i128` types.
-    (accepted, i128_type, "1.26.0", Some(35118), None),
+    (accepted, i128_type, "1.26.0", Some(35118)),
     /// Allows the use of `if let` expressions.
-    (accepted, if_let, "1.0.0", None, None),
+    (accepted, if_let, "1.0.0", None),
     /// Allows top level or-patterns (`p | q`) in `if let` and `while let`.
-    (accepted, if_while_or_patterns, "1.33.0", Some(48215), None),
+    (accepted, if_while_or_patterns, "1.33.0", Some(48215)),
     /// Allows lifetime elision in `impl` headers. For example:
     /// + `impl<I:Iterator> Iterator for &mut Iterator`
     /// + `impl Debug for Foo<'_>`
-    (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872), None),
+    (accepted, impl_header_lifetime_elision, "1.31.0", Some(15872)),
     /// Allows referencing `Self` and projections in impl-trait.
-    (accepted, impl_trait_projections, "1.74.0", Some(103532), None),
+    (accepted, impl_trait_projections, "1.74.0", Some(103532)),
     /// Allows using `a..=b` and `..=b` as inclusive range syntaxes.
-    (accepted, inclusive_range_syntax, "1.26.0", Some(28237), None),
+    (accepted, inclusive_range_syntax, "1.26.0", Some(28237)),
     /// Allows inferring outlives requirements (RFC 2093).
-    (accepted, infer_outlives_requirements, "1.30.0", Some(44493), None),
+    (accepted, infer_outlives_requirements, "1.30.0", Some(44493)),
     /// Allows irrefutable patterns in `if let` and `while let` statements (RFC 2086).
-    (accepted, irrefutable_let_patterns, "1.33.0", Some(44495), None),
+    (accepted, irrefutable_let_patterns, "1.33.0", Some(44495)),
     /// Allows `#[instruction_set(_)]` attribute.
-    (accepted, isa_attribute, "1.67.0", Some(74727), None),
+    (accepted, isa_attribute, "1.67.0", Some(74727)),
     /// Allows some increased flexibility in the name resolution rules,
     /// especially around globs and shadowing (RFC 1560).
-    (accepted, item_like_imports, "1.15.0", Some(35120), None),
+    (accepted, item_like_imports, "1.15.0", Some(35120)),
     /// Allows `'a: { break 'a; }`.
-    (accepted, label_break_value, "1.65.0", Some(48594), None),
+    (accepted, label_break_value, "1.65.0", Some(48594)),
     /// Allows `let...else` statements.
-    (accepted, let_else, "1.65.0", Some(87335), None),
+    (accepted, let_else, "1.65.0", Some(87335)),
     /// Allows `break {expr}` with a value inside `loop`s.
-    (accepted, loop_break_value, "1.19.0", Some(37339), None),
+    (accepted, loop_break_value, "1.19.0", Some(37339)),
     /// Allows use of `?` as the Kleene "at most one" operator in macros.
-    (accepted, macro_at_most_once_rep, "1.32.0", Some(48075), None),
+    (accepted, macro_at_most_once_rep, "1.32.0", Some(48075)),
     /// Allows macro attributes to observe output of `#[derive]`.
-    (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119), None),
+    (accepted, macro_attributes_in_derive_output, "1.57.0", Some(81119)),
     /// Allows use of the `:lifetime` macro fragment specifier.
-    (accepted, macro_lifetime_matcher, "1.27.0", Some(34303), None),
+    (accepted, macro_lifetime_matcher, "1.27.0", Some(34303)),
     /// Allows use of the `:literal` macro fragment specifier (RFC 1576).
-    (accepted, macro_literal_matcher, "1.32.0", Some(35625), None),
+    (accepted, macro_literal_matcher, "1.32.0", Some(35625)),
     /// Allows `macro_rules!` items.
-    (accepted, macro_rules, "1.0.0", None, None),
+    (accepted, macro_rules, "1.0.0", None),
     /// Allows use of the `:vis` macro fragment specifier
-    (accepted, macro_vis_matcher, "1.30.0", Some(41022), None),
+    (accepted, macro_vis_matcher, "1.30.0", Some(41022)),
     /// Allows macro invocations in `extern {}` blocks.
-    (accepted, macros_in_extern, "1.40.0", Some(49476), None),
+    (accepted, macros_in_extern, "1.40.0", Some(49476)),
     /// Allows '|' at beginning of match arms (RFC 1925).
-    (accepted, match_beginning_vert, "1.25.0", Some(44101), None),
+    (accepted, match_beginning_vert, "1.25.0", Some(44101)),
     /// Allows default match binding modes (RFC 2005).
-    (accepted, match_default_bindings, "1.26.0", Some(42640), None),
+    (accepted, match_default_bindings, "1.26.0", Some(42640)),
     /// Allows `impl Trait` with multiple unrelated lifetimes.
-    (accepted, member_constraints, "1.54.0", Some(61997), None),
+    (accepted, member_constraints, "1.54.0", Some(61997)),
     /// Allows the definition of `const fn` functions.
-    (accepted, min_const_fn, "1.31.0", Some(53555), None),
+    (accepted, min_const_fn, "1.31.0", Some(53555)),
     /// The smallest useful subset of const generics.
-    (accepted, min_const_generics, "1.51.0", Some(74878), None),
+    (accepted, min_const_generics, "1.51.0", Some(74878)),
     /// Allows calling `const unsafe fn` inside `unsafe` blocks in `const fn` functions.
-    (accepted, min_const_unsafe_fn, "1.33.0", Some(55607), None),
+    (accepted, min_const_unsafe_fn, "1.33.0", Some(55607)),
     /// Allows using `Self` and associated types in struct expressions and patterns.
-    (accepted, more_struct_aliases, "1.16.0", Some(37544), None),
+    (accepted, more_struct_aliases, "1.16.0", Some(37544)),
     /// Allows using the MOVBE target feature.
-    (accepted, movbe_target_feature, "1.70.0", Some(44839), None),
+    (accepted, movbe_target_feature, "1.70.0", Some(44839)),
     /// Allows patterns with concurrent by-move and by-ref bindings.
     /// For example, you can write `Foo(a, ref b)` where `a` is by-move and `b` is by-ref.
-    (accepted, move_ref_pattern, "1.49.0", Some(68354), None),
+    (accepted, move_ref_pattern, "1.49.0", Some(68354)),
     /// Allows specifying modifiers in the link attribute: `#[link(modifiers = "...")]`
-    (accepted, native_link_modifiers, "1.61.0", Some(81490), None),
+    (accepted, native_link_modifiers, "1.61.0", Some(81490)),
     /// Allows specifying the bundle link modifier
-    (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490), None),
+    (accepted, native_link_modifiers_bundle, "1.63.0", Some(81490)),
     /// Allows specifying the verbatim link modifier
-    (accepted, native_link_modifiers_verbatim, "1.67.0", Some(81490), None),
+    (accepted, native_link_modifiers_verbatim, "1.67.0", Some(81490)),
     /// Allows specifying the whole-archive link modifier
-    (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490), None),
+    (accepted, native_link_modifiers_whole_archive, "1.61.0", Some(81490)),
     /// Allows using non lexical lifetimes (RFC 2094).
-    (accepted, nll, "1.63.0", Some(43234), None),
+    (accepted, nll, "1.63.0", Some(43234)),
     /// Allows using `#![no_std]`.
-    (accepted, no_std, "1.6.0", None, None),
+    (accepted, no_std, "1.6.0", None),
     /// Allows defining identifiers beyond ASCII.
-    (accepted, non_ascii_idents, "1.53.0", Some(55467), None),
+    (accepted, non_ascii_idents, "1.53.0", Some(55467)),
     /// Allows future-proofing enums/structs with the `#[non_exhaustive]` attribute (RFC 2008).
-    (accepted, non_exhaustive, "1.40.0", Some(44109), None),
+    (accepted, non_exhaustive, "1.40.0", Some(44109)),
     /// Allows `foo.rs` as an alternative to `foo/mod.rs`.
-    (accepted, non_modrs_mods, "1.30.0", Some(44660), None),
+    (accepted, non_modrs_mods, "1.30.0", Some(44660)),
     /// Allows the use of or-patterns (e.g., `0 | 1`).
-    (accepted, or_patterns, "1.53.0", Some(54883), None),
+    (accepted, or_patterns, "1.53.0", Some(54883)),
     /// Allows using `+bundle,+whole-archive` link modifiers with native libs.
-    (accepted, packed_bundled_libs, "1.74.0", Some(108081), None),
+    (accepted, packed_bundled_libs, "1.74.0", Some(108081)),
     /// Allows annotating functions conforming to `fn(&PanicInfo) -> !` with `#[panic_handler]`.
     /// This defines the behavior of panics.
-    (accepted, panic_handler, "1.30.0", Some(44489), None),
+    (accepted, panic_handler, "1.30.0", Some(44489)),
     /// Allows attributes in formal function parameters.
-    (accepted, param_attrs, "1.39.0", Some(60406), None),
+    (accepted, param_attrs, "1.39.0", Some(60406)),
     /// Allows parentheses in patterns.
-    (accepted, pattern_parentheses, "1.31.0", Some(51087), None),
+    (accepted, pattern_parentheses, "1.31.0", Some(51087)),
     /// Allows procedural macros in `proc-macro` crates.
-    (accepted, proc_macro, "1.29.0", Some(38356), None),
+    (accepted, proc_macro, "1.29.0", Some(38356)),
     /// Allows multi-segment paths in attributes and derives.
-    (accepted, proc_macro_path_invoc, "1.30.0", Some(38356), None),
+    (accepted, proc_macro_path_invoc, "1.30.0", Some(38356)),
     /// Allows `pub(restricted)` visibilities (RFC 1422).
-    (accepted, pub_restricted, "1.18.0", Some(32409), None),
+    (accepted, pub_restricted, "1.18.0", Some(32409)),
     /// Allows use of the postfix `?` operator in expressions.
-    (accepted, question_mark, "1.13.0", Some(31436), None),
+    (accepted, question_mark, "1.13.0", Some(31436)),
     /// Allows the use of raw-dylibs (RFC 2627).
-    (accepted, raw_dylib, "1.71.0", Some(58713), None),
+    (accepted, raw_dylib, "1.71.0", Some(58713)),
     /// Allows keywords to be escaped for use as identifiers.
-    (accepted, raw_identifiers, "1.30.0", Some(48589), None),
+    (accepted, raw_identifiers, "1.30.0", Some(48589)),
     /// Allows relaxing the coherence rules such that
     /// `impl<T> ForeignTrait<LocalType> for ForeignType<T>` is permitted.
-    (accepted, re_rebalance_coherence, "1.41.0", Some(55437), None),
+    (accepted, re_rebalance_coherence, "1.41.0", Some(55437)),
     /// Allows numeric fields in struct expressions and patterns.
-    (accepted, relaxed_adts, "1.19.0", Some(35626), None),
+    (accepted, relaxed_adts, "1.19.0", Some(35626)),
     /// Lessens the requirements for structs to implement `Unsize`.
-    (accepted, relaxed_struct_unsize, "1.58.0", Some(81793), None),
+    (accepted, relaxed_struct_unsize, "1.58.0", Some(81793)),
     /// Allows `repr(align(16))` struct attribute (RFC 1358).
-    (accepted, repr_align, "1.25.0", Some(33626), None),
+    (accepted, repr_align, "1.25.0", Some(33626)),
     /// Allows using `#[repr(align(X))]` on enums with equivalent semantics
     /// to wrapping an enum in a wrapper struct with `#[repr(align(X))]`.
-    (accepted, repr_align_enum, "1.37.0", Some(57996), None),
+    (accepted, repr_align_enum, "1.37.0", Some(57996)),
     /// Allows `#[repr(packed(N))]` attribute on structs.
-    (accepted, repr_packed, "1.33.0", Some(33158), None),
+    (accepted, repr_packed, "1.33.0", Some(33158)),
     /// Allows `#[repr(transparent)]` attribute on newtype structs.
-    (accepted, repr_transparent, "1.28.0", Some(43036), None),
+    (accepted, repr_transparent, "1.28.0", Some(43036)),
     /// Allows return-position `impl Trait` in traits.
-    (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611), None),
+    (accepted, return_position_impl_trait_in_trait, "1.75.0", Some(91611)),
     /// Allows code like `let x: &'static u32 = &42` to work (RFC 1414).
-    (accepted, rvalue_static_promotion, "1.21.0", Some(38865), None),
+    (accepted, rvalue_static_promotion, "1.21.0", Some(38865)),
     /// Allows `Self` in type definitions (RFC 2300).
-    (accepted, self_in_typedefs, "1.32.0", Some(49303), None),
+    (accepted, self_in_typedefs, "1.32.0", Some(49303)),
     /// Allows `Self` struct constructor (RFC 2302).
-    (accepted, self_struct_ctor, "1.32.0", Some(51994), None),
+    (accepted, self_struct_ctor, "1.32.0", Some(51994)),
     /// Allows using subslice patterns, `[a, .., b]` and `[a, xs @ .., b]`.
-    (accepted, slice_patterns, "1.42.0", Some(62254), None),
+    (accepted, slice_patterns, "1.42.0", Some(62254)),
     /// Allows use of `&foo[a..b]` as a slicing syntax.
-    (accepted, slicing_syntax, "1.0.0", None, None),
+    (accepted, slicing_syntax, "1.0.0", None),
     /// Allows elision of `'static` lifetimes in `static`s and `const`s.
-    (accepted, static_in_const, "1.17.0", Some(35897), None),
+    (accepted, static_in_const, "1.17.0", Some(35897)),
     /// Allows the definition recursive static items.
-    (accepted, static_recursion, "1.17.0", Some(29719), None),
+    (accepted, static_recursion, "1.17.0", Some(29719)),
     /// Allows attributes on struct literal fields.
-    (accepted, struct_field_attributes, "1.20.0", Some(38814), None),
+    (accepted, struct_field_attributes, "1.20.0", Some(38814)),
     /// Allows struct variants `Foo { baz: u8, .. }` in enums (RFC 418).
-    (accepted, struct_variant, "1.0.0", None, None),
+    (accepted, struct_variant, "1.0.0", None),
     /// Allows `#[target_feature(...)]`.
-    (accepted, target_feature, "1.27.0", None, None),
+    (accepted, target_feature, "1.27.0", None),
     /// Allows `fn main()` with return types which implements `Termination` (RFC 1937).
-    (accepted, termination_trait, "1.26.0", Some(43301), None),
+    (accepted, termination_trait, "1.26.0", Some(43301)),
     /// Allows `#[test]` functions where the return type implements `Termination` (RFC 1937).
-    (accepted, termination_trait_test, "1.27.0", Some(48854), None),
+    (accepted, termination_trait_test, "1.27.0", Some(48854)),
     /// Allows attributes scoped to tools.
-    (accepted, tool_attributes, "1.30.0", Some(44690), None),
+    (accepted, tool_attributes, "1.30.0", Some(44690)),
     /// Allows scoped lints.
-    (accepted, tool_lints, "1.31.0", Some(44690), None),
+    (accepted, tool_lints, "1.31.0", Some(44690)),
     /// Allows `#[track_caller]` to be used which provides
     /// accurate caller location reporting during panic (RFC 2091).
-    (accepted, track_caller, "1.46.0", Some(47809), None),
+    (accepted, track_caller, "1.46.0", Some(47809)),
     /// Allows dyn upcasting trait objects via supertraits.
     /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
-    (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991), None),
+    (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991)),
     /// Allows #[repr(transparent)] on univariant enums (RFC 2645).
-    (accepted, transparent_enums, "1.42.0", Some(60405), None),
+    (accepted, transparent_enums, "1.42.0", Some(60405)),
     /// Allows indexing tuples.
-    (accepted, tuple_indexing, "1.0.0", None, None),
+    (accepted, tuple_indexing, "1.0.0", None),
     /// Allows paths to enum variants on type aliases including `Self`.
-    (accepted, type_alias_enum_variants, "1.37.0", Some(49683), None),
+    (accepted, type_alias_enum_variants, "1.37.0", Some(49683)),
     /// Allows macros to appear in the type position.
-    (accepted, type_macros, "1.13.0", Some(27245), None),
+    (accepted, type_macros, "1.13.0", Some(27245)),
     /// Allows `const _: TYPE = VALUE`.
-    (accepted, underscore_const_names, "1.37.0", Some(54912), None),
+    (accepted, underscore_const_names, "1.37.0", Some(54912)),
     /// Allows `use path as _;` and `extern crate c as _;`.
-    (accepted, underscore_imports, "1.33.0", Some(48216), None),
+    (accepted, underscore_imports, "1.33.0", Some(48216)),
     /// Allows `'_` placeholder lifetimes.
-    (accepted, underscore_lifetimes, "1.26.0", Some(44524), None),
+    (accepted, underscore_lifetimes, "1.26.0", Some(44524)),
     /// Allows `use x::y;` to search `x` in the current scope.
-    (accepted, uniform_paths, "1.32.0", Some(53130), None),
+    (accepted, uniform_paths, "1.32.0", Some(53130)),
     /// Allows `impl Trait` in function arguments.
-    (accepted, universal_impl_trait, "1.26.0", Some(34511), None),
+    (accepted, universal_impl_trait, "1.26.0", Some(34511)),
     /// Allows arbitrary delimited token streams in non-macro attributes.
-    (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208), None),
+    (accepted, unrestricted_attribute_tokens, "1.34.0", Some(55208)),
     /// The `unsafe_op_in_unsafe_fn` lint (allowed by default): no longer treat an unsafe function as an unsafe block.
-    (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668), None),
+    (accepted, unsafe_block_in_unsafe_fn, "1.52.0", Some(71668)),
     /// Allows importing and reexporting macros with `use`,
     /// enables macro modularization in general.
-    (accepted, use_extern_macros, "1.30.0", Some(35896), None),
+    (accepted, use_extern_macros, "1.30.0", Some(35896)),
     /// Allows nested groups in `use` items (RFC 2128).
-    (accepted, use_nested_groups, "1.25.0", Some(44494), None),
+    (accepted, use_nested_groups, "1.25.0", Some(44494)),
     /// Allows `#[used]` to preserve symbols (see llvm.compiler.used).
-    (accepted, used, "1.30.0", Some(40289), None),
+    (accepted, used, "1.30.0", Some(40289)),
     /// Allows the use of `while let` expressions.
-    (accepted, while_let, "1.0.0", None, None),
+    (accepted, while_let, "1.0.0", None),
     /// Allows `#![windows_subsystem]`.
-    (accepted, windows_subsystem, "1.18.0", Some(37499), None),
+    (accepted, windows_subsystem, "1.18.0", Some(37499)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 73d51d9f80e..cd1d9b13daa 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -26,7 +26,7 @@ mod unstable;
 #[cfg(test)]
 mod tests;
 
-use rustc_span::{edition::Edition, symbol::Symbol};
+use rustc_span::symbol::Symbol;
 use std::num::NonZeroU32;
 
 #[derive(Debug, Clone)]
@@ -34,7 +34,6 @@ pub struct Feature {
     pub name: Symbol,
     pub since: &'static str,
     issue: Option<NonZeroU32>,
-    pub edition: Option<Edition>,
 }
 
 #[derive(Copy, Clone, Debug)]
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index c0d3fc3fae0..0d9b8b344cf 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -10,7 +10,7 @@ pub struct RemovedFeature {
 
 macro_rules! declare_features {
     ($(
-        $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, None, $reason:expr),
+        $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr),
     )+) => {
         /// Formerly unstable features that have now been removed.
         pub const REMOVED_FEATURES: &[RemovedFeature] = &[
@@ -19,7 +19,6 @@ macro_rules! declare_features {
                     name: sym::$feature,
                     since: $ver,
                     issue: to_nonzero($issue),
-                    edition: None,
                 },
                 reason: $reason
             }),+
@@ -33,176 +32,178 @@ declare_features! (
     // feature-group-start: removed features
     // -------------------------------------------------------------------------
 
-    (removed, advanced_slice_patterns, "1.0.0", Some(62254), None,
+    (removed, advanced_slice_patterns, "1.0.0", Some(62254),
      Some("merged into `#![feature(slice_patterns)]`")),
-    (removed, allocator, "1.0.0", None, None, None),
+    (removed, allocator, "1.0.0", None, None),
     /// Allows a test to fail without failing the whole suite.
-    (removed, allow_fail, "1.19.0", Some(46488), None, Some("removed due to no clear use cases")),
-    (removed, await_macro, "1.38.0", Some(50547), None,
+    (removed, allow_fail, "1.19.0", Some(46488), Some("removed due to no clear use cases")),
+    (removed, await_macro, "1.38.0", Some(50547),
      Some("subsumed by `.await` syntax")),
     /// Allows using the `box $expr` syntax.
-    (removed, box_syntax, "1.70.0", Some(49733), None, Some("replaced with `#[rustc_box]`")),
+    (removed, box_syntax, "1.70.0", Some(49733), Some("replaced with `#[rustc_box]`")),
     /// Allows capturing disjoint fields in a closure/coroutine (RFC 2229).
-    (removed, capture_disjoint_fields, "1.49.0", Some(53488), None, Some("stabilized in Rust 2021")),
+    (removed, capture_disjoint_fields, "1.49.0", Some(53488), Some("stabilized in Rust 2021")),
     /// Allows comparing raw pointers during const eval.
-    (removed, const_compare_raw_pointers, "1.46.0", Some(53020), None,
+    (removed, const_compare_raw_pointers, "1.46.0", Some(53020),
      Some("cannot be allowed in const eval in any meaningful way")),
     /// Allows limiting the evaluation steps of const expressions
-    (removed, const_eval_limit, "1.43.0", Some(67217), None, Some("removed the limit entirely")),
+    (removed, const_eval_limit, "1.43.0", Some(67217), Some("removed the limit entirely")),
     /// Allows non-trivial generic constants which have to be manually propagated upwards.
-    (removed, const_evaluatable_checked, "1.48.0", Some(76560), None, Some("renamed to `generic_const_exprs`")),
+    (removed, const_evaluatable_checked, "1.48.0", Some(76560), Some("renamed to `generic_const_exprs`")),
     /// Allows the definition of `const` functions with some advanced features.
-    (removed, const_fn, "1.54.0", Some(57563), None,
+    (removed, const_fn, "1.54.0", Some(57563),
      Some("split into finer-grained feature gates")),
     /// Allows const generic types (e.g. `struct Foo<const N: usize>(...);`).
-    (removed, const_generics, "1.34.0", Some(44580), None,
+    (removed, const_generics, "1.34.0", Some(44580),
      Some("removed in favor of `#![feature(adt_const_params)]` and `#![feature(generic_const_exprs)]`")),
     /// Allows `[x; N]` where `x` is a constant (RFC 2203).
-    (removed, const_in_array_repeat_expressions,  "1.37.0", Some(49147), None,
+    (removed, const_in_array_repeat_expressions,  "1.37.0", Some(49147),
      Some("removed due to causing promotable bugs")),
     /// Allows casting raw pointers to `usize` during const eval.
-    (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910), None,
+    (removed, const_raw_ptr_to_usize_cast, "1.55.0", Some(51910),
      Some("at compile-time, pointers do not have an integer value, so these casts cannot be properly supported")),
     /// Allows `T: ?const Trait` syntax in bounds.
-    (removed, const_trait_bound_opt_out, "1.42.0", Some(67794), None,
+    (removed, const_trait_bound_opt_out, "1.42.0", Some(67794),
      Some("Removed in favor of `~const` bound in #![feature(const_trait_impl)]")),
     /// Allows using `crate` as visibility modifier, synonymous with `pub(crate)`.
-    (removed, crate_visibility_modifier, "1.63.0", Some(53120), None, Some("removed in favor of `pub(crate)`")),
+    (removed, crate_visibility_modifier, "1.63.0", Some(53120), Some("removed in favor of `pub(crate)`")),
     /// Allows using custom attributes (RFC 572).
-    (removed, custom_attribute, "1.0.0", Some(29642), None,
+    (removed, custom_attribute, "1.0.0", Some(29642),
      Some("removed in favor of `#![register_tool]` and `#![register_attr]`")),
     /// Allows the use of `#[derive(Anything)]` as sugar for `#[derive_Anything]`.
-    (removed, custom_derive, "1.32.0", Some(29644), None,
+    (removed, custom_derive, "1.32.0", Some(29644),
      Some("subsumed by `#[proc_macro_derive]`")),
     /// Allows using `#[doc(keyword = "...")]`.
-    (removed, doc_keyword, "1.28.0", Some(51315), None,
+    (removed, doc_keyword, "1.28.0", Some(51315),
      Some("merged into `#![feature(rustdoc_internals)]`")),
     /// Allows using `doc(primitive)` without a future-incompat warning.
-    (removed, doc_primitive, "1.56.0", Some(88070), None,
+    (removed, doc_primitive, "1.56.0", Some(88070),
      Some("merged into `#![feature(rustdoc_internals)]`")),
     /// Allows `#[doc(spotlight)]`.
     /// The attribute was renamed to `#[doc(notable_trait)]`
     /// and the feature to `doc_notable_trait`.
-    (removed, doc_spotlight, "1.22.0", Some(45040), None,
+    (removed, doc_spotlight, "1.22.0", Some(45040),
      Some("renamed to `doc_notable_trait`")),
     /// Allows using `#[unsafe_destructor_blind_to_params]` (RFC 1238).
-    (removed, dropck_parametricity, "1.38.0", Some(28498), None, None),
+    (removed, dropck_parametricity, "1.38.0", Some(28498), None),
     /// Allows defining `existential type`s.
-    (removed, existential_type, "1.38.0", Some(63063), None,
+    (removed, existential_type, "1.38.0", Some(63063),
      Some("removed in favor of `#![feature(type_alias_impl_trait)]`")),
     /// Paths of the form: `extern::foo::bar`
-    (removed, extern_in_paths, "1.33.0", Some(55600), None,
+    (removed, extern_in_paths, "1.33.0", Some(55600),
      Some("subsumed by `::foo::bar` paths")),
     /// Allows `#[doc(include = "some-file")]`.
-    (removed, external_doc, "1.54.0", Some(44732), None,
+    (removed, external_doc, "1.54.0", Some(44732),
      Some("use #[doc = include_str!(\"filename\")] instead, which handles macro invocations")),
     /// Allows generators to be cloned.
-    (removed, generator_clone, "1.65.0", Some(95360), None, Some("renamed to `coroutine_clone`")),
+    (removed, generator_clone, "1.65.0", Some(95360), Some("renamed to `coroutine_clone`")),
     /// Allows defining generators.
-    (removed, generators, "1.21.0", Some(43122), None, Some("renamed to `coroutines`")),
+    (removed, generators, "1.21.0", Some(43122), Some("renamed to `coroutines`")),
     /// Allows `impl Trait` in bindings (`let`, `const`, `static`).
-    (removed, impl_trait_in_bindings, "1.55.0", Some(63065), None,
+    (removed, impl_trait_in_bindings, "1.55.0", Some(63065),
      Some("the implementation was not maintainable, the feature may get reintroduced once the current refactorings are done")),
-    (removed, import_shadowing, "1.0.0", None, None, None),
+    (removed, import_shadowing, "1.0.0", None, None),
     /// Allows in-band quantification of lifetime bindings (e.g., `fn foo(x: &'a u8) -> &'a u8`).
-    (removed, in_band_lifetimes, "1.23.0", Some(44524), None,
+    (removed, in_band_lifetimes, "1.23.0", Some(44524),
      Some("removed due to unsolved ergonomic questions and added lifetime resolution complexity")),
     /// Allows inferring `'static` outlives requirements (RFC 2093).
-    (removed, infer_static_outlives_requirements, "1.63.0", Some(54185), None,
+    (removed, infer_static_outlives_requirements, "1.63.0", Some(54185),
      Some("removed as it caused some confusion and discussion was inactive for years")),
     /// Lazily evaluate constants. This allows constants to depend on type parameters.
-    (removed, lazy_normalization_consts, "1.46.0", Some(72219), None, Some("superseded by `generic_const_exprs`")),
+    (removed, lazy_normalization_consts, "1.46.0", Some(72219), Some("superseded by `generic_const_exprs`")),
     /// Allows using the `#[link_args]` attribute.
-    (removed, link_args, "1.53.0", Some(29596), None,
+    (removed, link_args, "1.53.0", Some(29596),
      Some("removed in favor of using `-C link-arg=ARG` on command line, \
            which is available from cargo build scripts with `cargo:rustc-link-arg` now")),
-    (removed, macro_reexport, "1.0.0", Some(29638), None,
+    (removed, macro_reexport, "1.0.0", Some(29638),
      Some("subsumed by `pub use`")),
     /// Allows using `#[main]` to replace the entrypoint `#[lang = "start"]` calls.
-    (removed, main, "1.53.0", Some(29634), None, None),
-    (removed, managed_boxes, "1.0.0", None, None, None),
+    (removed, main, "1.53.0", Some(29634), None),
+    (removed, managed_boxes, "1.0.0", None, None),
     /// Allows the use of type alias impl trait in function return positions
-    (removed, min_type_alias_impl_trait, "1.56.0", Some(63063), None,
+    (removed, min_type_alias_impl_trait, "1.56.0", Some(63063),
      Some("removed in favor of full type_alias_impl_trait")),
-    (removed, needs_allocator, "1.4.0", Some(27389), None,
+    (removed, needs_allocator, "1.4.0", Some(27389),
      Some("subsumed by `#![feature(allocator_internals)]`")),
     /// Allows use of unary negate on unsigned integers, e.g., -e for e: u8
-    (removed, negate_unsigned, "1.0.0", Some(29645), None, None),
+    (removed, negate_unsigned, "1.0.0", Some(29645), None),
     /// Allows `#[no_coverage]` on functions.
     /// The feature was renamed to `coverage_attribute` and the attribute to `#[coverage(on|off)]`
-    (removed, no_coverage, "1.74.0", Some(84605), None, Some("renamed to `coverage_attribute`")),
+    (removed, no_coverage, "1.74.0", Some(84605), Some("renamed to `coverage_attribute`")),
     /// Allows `#[no_debug]`.
-    (removed, no_debug, "1.43.0", Some(29721), None, Some("removed due to lack of demand")),
+    (removed, no_debug, "1.43.0", Some(29721), Some("removed due to lack of demand")),
     /// Note: this feature was previously recorded in a separate
     /// `STABLE_REMOVED` list because it, uniquely, was once stable but was
     /// then removed. But there was no utility storing it separately, so now
     /// it's in this list.
-    (removed, no_stack_check, "1.0.0", None, None, None),
+    (removed, no_stack_check, "1.0.0", None, None),
     /// Allows using `#[on_unimplemented(..)]` on traits.
     /// (Moved to `rustc_attrs`.)
-    (removed, on_unimplemented, "1.40.0", None, None, None),
+    (removed, on_unimplemented, "1.40.0", None, None),
     /// A way to temporarily opt out of opt-in copy. This will *never* be accepted.
-    (removed, opt_out_copy, "1.0.0", None, None, None),
+    (removed, opt_out_copy, "1.0.0", None, None),
     /// Allows features specific to OIBIT (now called auto traits).
     /// Renamed to `auto_traits`.
-    (removed, optin_builtin_traits, "1.0.0", Some(13231), None,
+    (removed, optin_builtin_traits, "1.0.0", Some(13231),
      Some("renamed to `auto_traits`")),
     /// Allows overlapping impls of marker traits.
-    (removed, overlapping_marker_traits, "1.42.0", Some(29864), None,
+    (removed, overlapping_marker_traits, "1.42.0", Some(29864),
      Some("removed in favor of `#![feature(marker_trait_attr)]`")),
-    (removed, panic_implementation, "1.28.0", Some(44489), None,
+    (removed, panic_implementation, "1.28.0", Some(44489),
      Some("subsumed by `#[panic_handler]`")),
     /// Allows using `#![plugin(myplugin)]`.
-    (removed, plugin, "1.75.0", Some(29597), None,
+    (removed, plugin, "1.75.0", Some(29597),
      Some("plugins are no longer supported")),
     /// Allows using `#[plugin_registrar]` on functions.
-    (removed, plugin_registrar, "1.54.0", Some(29597), None,
+    (removed, plugin_registrar, "1.54.0", Some(29597),
      Some("plugins are no longer supported")),
     /// Allows exhaustive integer pattern matching with `usize::MAX`/`isize::MIN`/`isize::MAX`.
-    (removed, precise_pointer_size_matching, "1.32.0", Some(56354), None,
+    (removed, precise_pointer_size_matching, "1.32.0", Some(56354),
      Some("removed in favor of half-open ranges")),
-    (removed, proc_macro_expr, "1.27.0", Some(54727), None,
+    (removed, proc_macro_expr, "1.27.0", Some(54727),
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
-    (removed, proc_macro_gen, "1.27.0", Some(54727), None,
+    (removed, proc_macro_gen, "1.27.0", Some(54727),
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
-    (removed, proc_macro_mod, "1.27.0", Some(54727), None,
+    (removed, proc_macro_mod, "1.27.0", Some(54727),
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
-    (removed, proc_macro_non_items, "1.27.0", Some(54727), None,
+    (removed, proc_macro_non_items, "1.27.0", Some(54727),
      Some("subsumed by `#![feature(proc_macro_hygiene)]`")),
-    (removed, pub_macro_rules, "1.53.0", Some(78855), None,
+    (removed, pub_macro_rules, "1.53.0", Some(78855),
      Some("removed due to being incomplete, in particular it does not work across crates")),
-    (removed, pushpop_unsafe, "1.2.0", None, None, None),
-    (removed, quad_precision_float, "1.0.0", None, None, None),
-    (removed, quote, "1.33.0", Some(29601), None, None),
-    (removed, reflect, "1.0.0", Some(27749), None, None),
+    (removed, pushpop_unsafe, "1.2.0", None, None),
+    (removed, quad_precision_float, "1.0.0", None, None),
+    (removed, quote, "1.33.0", Some(29601), None),
+    (removed, reflect, "1.0.0", Some(27749), None),
     /// Allows using the `#[register_attr]` attribute.
-    (removed, register_attr, "1.65.0", Some(66080), None,
+    (removed, register_attr, "1.65.0", Some(66080),
      Some("removed in favor of `#![register_tool]`")),
+    (removed, rust_2018_preview, "CURRENT_RUSTC_VERSION", None,
+     Some("2018 Edition preview is no longer relevant")),
     /// Allows using the macros:
     /// + `__diagnostic_used`
     /// + `__register_diagnostic`
     /// +`__build_diagnostic_array`
-    (removed, rustc_diagnostic_macros, "1.38.0", None, None, None),
+    (removed, rustc_diagnostic_macros, "1.38.0", None, None),
     /// Allows identifying crates that contain sanitizer runtimes.
-    (removed, sanitizer_runtime, "1.17.0", None, None, None),
-    (removed, simd, "1.0.0", Some(27731), None,
+    (removed, sanitizer_runtime, "1.17.0", None, None),
+    (removed, simd, "1.0.0", Some(27731),
      Some("removed in favor of `#[repr(simd)]`")),
     /// Allows `#[link(kind = "static-nobundle", ...)]`.
-    (removed, static_nobundle, "1.16.0", Some(37403), None,
+    (removed, static_nobundle, "1.16.0", Some(37403),
      Some(r#"subsumed by `#[link(kind = "static", modifiers = "-bundle", ...)]`"#)),
-    (removed, struct_inherit, "1.0.0", None, None, None),
-    (removed, test_removed_feature, "1.0.0", None, None, None),
+    (removed, struct_inherit, "1.0.0", None, None),
+    (removed, test_removed_feature, "1.0.0", None, None),
     /// Allows using items which are missing stability attributes
-    (removed, unmarked_api, "1.0.0", None, None, None),
-    (removed, unsafe_no_drop_flag, "1.0.0", None, None, None),
+    (removed, unmarked_api, "1.0.0", None, None),
+    (removed, unsafe_no_drop_flag, "1.0.0", None, None),
     /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
-    (removed, untagged_unions, "1.13.0", Some(55149), None,
+    (removed, untagged_unions, "1.13.0", Some(55149),
      Some("unions with `Copy` and `ManuallyDrop` fields are stable; there is no intent to stabilize more")),
     /// Allows `#[unwind(..)]`.
     ///
     /// Permits specifying whether a function should permit unwinding or abort on unwind.
-    (removed, unwind_attributes, "1.56.0", Some(58760), None, Some("use the C-unwind ABI instead")),
-    (removed, visible_private_types, "1.0.0", None, None, None),
+    (removed, unwind_attributes, "1.56.0", Some(58760), Some("use the C-unwind ABI instead")),
+    (removed, visible_private_types, "1.0.0", None, None),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index e68ab017380..bbf5e031175 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -3,7 +3,6 @@
 use super::{to_nonzero, Feature};
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_span::edition::Edition;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
 
@@ -33,7 +32,7 @@ macro_rules! status_to_enum {
 
 macro_rules! declare_features {
     ($(
-        $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr, $edition:expr),
+        $(#[doc = $doc:tt])* ($status:ident, $feature:ident, $ver:expr, $issue:expr),
     )+) => {
         /// Unstable language features that are being implemented or being
         /// considered for acceptance (stabilization) or removal.
@@ -43,7 +42,6 @@ macro_rules! declare_features {
                     name: sym::$feature,
                     since: $ver,
                     issue: to_nonzero($issue),
-                    edition: $edition,
                 },
                 // Sets this feature's corresponding bool within `features`.
                 set_enabled: |features| features.$feature = true,
@@ -102,8 +100,7 @@ macro_rules! declare_features {
                 self.declared_features.contains(&feature)
             }
 
-            /// Is the given feature active, i.e. declared or automatically
-            /// enabled due to the edition?
+            /// Is the given feature active (enabled by the user)?
             ///
             /// Panics if the symbol doesn't correspond to a declared feature.
             pub fn active(&self, feature: Symbol) -> bool {
@@ -179,56 +176,56 @@ declare_features! (
     // no-tracking-issue-start
 
     /// Allows using the `unadjusted` ABI; perma-unstable.
-    (internal, abi_unadjusted, "1.16.0", None, None),
+    (internal, abi_unadjusted, "1.16.0", None),
     /// Allows using the `vectorcall` ABI.
-    (unstable, abi_vectorcall, "1.7.0", None, None),
+    (unstable, abi_vectorcall, "1.7.0", None),
     /// Allows using `#![needs_allocator]`, an implementation detail of `#[global_allocator]`.
-    (internal, allocator_internals, "1.20.0", None, None),
+    (internal, allocator_internals, "1.20.0", None),
     /// Allows using `#[allow_internal_unsafe]`. This is an
     /// attribute on `macro_rules!` and can't use the attribute handling
     /// below (it has to be checked before expansion possibly makes
     /// macros disappear).
-    (internal, allow_internal_unsafe, "1.0.0", None, None),
+    (internal, allow_internal_unsafe, "1.0.0", None),
     /// Allows using `#[allow_internal_unstable]`. This is an
     /// attribute on `macro_rules!` and can't use the attribute handling
     /// below (it has to be checked before expansion possibly makes
     /// macros disappear).
-    (internal, allow_internal_unstable, "1.0.0", None, None),
+    (internal, allow_internal_unstable, "1.0.0", None),
     /// Allows using anonymous lifetimes in argument-position impl-trait.
-    (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None, None),
+    (unstable, anonymous_lifetime_in_impl_trait, "1.63.0", None),
     /// Allows identifying the `compiler_builtins` crate.
-    (internal, compiler_builtins, "1.13.0", None, None),
+    (internal, compiler_builtins, "1.13.0", None),
     /// Allows writing custom MIR
-    (internal, custom_mir, "1.65.0", None, None),
+    (internal, custom_mir, "1.65.0", None),
     /// Outputs useful `assert!` messages
-    (unstable, generic_assert, "1.63.0", None, None),
+    (unstable, generic_assert, "1.63.0", None),
     /// Allows using the `rust-intrinsic`'s "ABI".
-    (internal, intrinsics, "1.0.0", None, None),
+    (internal, intrinsics, "1.0.0", None),
     /// Allows using `#[lang = ".."]` attribute for linking items to special compiler logic.
-    (internal, lang_items, "1.0.0", None, None),
+    (internal, lang_items, "1.0.0", None),
+    /// Changes `impl Trait` to capture all lifetimes in scope.
+    (unstable, lifetime_capture_rules_2024, "CURRENT_RUSTC_VERSION", None),
     /// Allows `#[link(..., cfg(..))]`; perma-unstable per #37406
-    (unstable, link_cfg, "1.14.0", None, None),
+    (unstable, link_cfg, "1.14.0", None),
     /// Allows the `multiple_supertrait_upcastable` lint.
-    (unstable, multiple_supertrait_upcastable, "1.69.0", None, None),
+    (unstable, multiple_supertrait_upcastable, "1.69.0", None),
     /// Allow negative trait bounds. This is an internal-only feature for testing the trait solver!
-    (incomplete, negative_bounds, "1.71.0", None, None),
+    (incomplete, negative_bounds, "1.71.0", None),
     /// Allows using `#[omit_gdb_pretty_printer_section]`.
-    (internal, omit_gdb_pretty_printer_section, "1.5.0", None, None),
+    (internal, omit_gdb_pretty_printer_section, "1.5.0", None),
     /// Allows using `#[prelude_import]` on glob `use` items.
-    (internal, prelude_import, "1.2.0", None, None),
+    (internal, prelude_import, "1.2.0", None),
     /// Used to identify crates that contain the profiler runtime.
-    (internal, profiler_runtime, "1.18.0", None, None),
+    (internal, profiler_runtime, "1.18.0", None),
     /// Allows using `rustc_*` attributes (RFC 572).
-    (internal, rustc_attrs, "1.0.0", None, None),
+    (internal, rustc_attrs, "1.0.0", None),
     /// Allows using the `#[stable]` and `#[unstable]` attributes.
-    (internal, staged_api, "1.0.0", None, None),
-    /// Added for testing E0705; perma-unstable.
-    (internal, test_2018_feature, "1.31.0", None, Some(Edition::Edition2018)),
+    (internal, staged_api, "1.0.0", None),
     /// Added for testing unstable lints; perma-unstable.
-    (internal, test_unstable_lint, "1.60.0", None, None),
+    (internal, test_unstable_lint, "1.60.0", None),
     /// Use for stable + negative coherence and strict coherence depending on trait's
     /// rustc_strict_coherence value.
-    (unstable, with_negative_coherence, "1.60.0", None, None),
+    (unstable, with_negative_coherence, "1.60.0", None),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
@@ -244,44 +241,44 @@ declare_features! (
 
     /// Allows features specific to auto traits.
     /// Renamed from `optin_builtin_traits`.
-    (unstable, auto_traits, "1.50.0", Some(13231), None),
+    (unstable, auto_traits, "1.50.0", Some(13231)),
     /// Allows using `box` in patterns (RFC 469).
-    (unstable, box_patterns, "1.0.0", Some(29641), None),
+    (unstable, box_patterns, "1.0.0", Some(29641)),
     /// Allows `#[doc(notable_trait)]`.
     /// Renamed from `doc_spotlight`.
-    (unstable, doc_notable_trait, "1.52.0", Some(45040), None),
+    (unstable, doc_notable_trait, "1.52.0", Some(45040)),
     /// Allows using the `may_dangle` attribute (RFC 1327).
-    (unstable, dropck_eyepatch, "1.10.0", Some(34761), None),
+    (unstable, dropck_eyepatch, "1.10.0", Some(34761)),
     /// Allows using the `#[fundamental]` attribute.
-    (unstable, fundamental, "1.0.0", Some(29635), None),
+    (unstable, fundamental, "1.0.0", Some(29635)),
     /// Allows using `#[link_name="llvm.*"]`.
-    (internal, link_llvm_intrinsics, "1.0.0", Some(29602), None),
+    (internal, link_llvm_intrinsics, "1.0.0", Some(29602)),
     /// Allows using the `#[linkage = ".."]` attribute.
-    (unstable, linkage, "1.0.0", Some(29603), None),
+    (unstable, linkage, "1.0.0", Some(29603)),
     /// Allows declaring with `#![needs_panic_runtime]` that a panic runtime is needed.
-    (internal, needs_panic_runtime, "1.10.0", Some(32837), None),
+    (internal, needs_panic_runtime, "1.10.0", Some(32837)),
     /// Allows using the `#![panic_runtime]` attribute.
-    (internal, panic_runtime, "1.10.0", Some(32837), None),
+    (internal, panic_runtime, "1.10.0", Some(32837)),
     /// Allows `extern "platform-intrinsic" { ... }`.
-    (internal, platform_intrinsics, "1.4.0", Some(27731), None),
+    (internal, platform_intrinsics, "1.4.0", Some(27731)),
     /// Allows using `#[rustc_allow_const_fn_unstable]`.
     /// This is an attribute on `const fn` for the same
     /// purpose as `#[allow_internal_unstable]`.
-    (internal, rustc_allow_const_fn_unstable, "1.49.0", Some(69399), None),
+    (internal, rustc_allow_const_fn_unstable, "1.49.0", Some(69399)),
     /// Allows using compiler's own crates.
-    (unstable, rustc_private, "1.0.0", Some(27812), None),
+    (unstable, rustc_private, "1.0.0", Some(27812)),
     /// Allows using internal rustdoc features like `doc(keyword)`.
-    (internal, rustdoc_internals, "1.58.0", Some(90418), None),
+    (internal, rustdoc_internals, "1.58.0", Some(90418)),
     /// Allows using the `rustdoc::missing_doc_code_examples` lint
-    (unstable, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730), None),
+    (unstable, rustdoc_missing_doc_code_examples, "1.31.0", Some(101730)),
     /// Allows using `#[start]` on a function indicating that it is the program entrypoint.
-    (unstable, start, "1.0.0", Some(29633), None),
+    (unstable, start, "1.0.0", Some(29633)),
     /// Allows using `#[structural_match]` which indicates that a type is structurally matchable.
     /// FIXME: Subsumed by trait `StructuralPartialEq`, cannot move to removed until a library
     /// feature with the same name exists.
-    (unstable, structural_match, "1.8.0", Some(31434), None),
+    (unstable, structural_match, "1.8.0", Some(31434)),
     /// Allows using the `rust-call` ABI.
-    (unstable, unboxed_closures, "1.0.0", Some(29625), None),
+    (unstable, unboxed_closures, "1.0.0", Some(29625)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
@@ -297,21 +294,21 @@ declare_features! (
     // FIXME: Document these and merge with the list below.
 
     // Unstable `#[target_feature]` directives.
-    (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839), None),
-    (unstable, arm_target_feature, "1.27.0", Some(44839), None),
-    (unstable, avx512_target_feature, "1.27.0", Some(44839), None),
-    (unstable, bpf_target_feature, "1.54.0", Some(44839), None),
-    (unstable, csky_target_feature, "1.73.0", Some(44839), None),
-    (unstable, ermsb_target_feature, "1.49.0", Some(44839), None),
-    (unstable, hexagon_target_feature, "1.27.0", Some(44839), None),
-    (unstable, loongarch_target_feature, "1.73.0", Some(44839), None),
-    (unstable, mips_target_feature, "1.27.0", Some(44839), None),
-    (unstable, powerpc_target_feature, "1.27.0", Some(44839), None),
-    (unstable, riscv_target_feature, "1.45.0", Some(44839), None),
-    (unstable, rtm_target_feature, "1.35.0", Some(44839), None),
-    (unstable, sse4a_target_feature, "1.27.0", Some(44839), None),
-    (unstable, tbm_target_feature, "1.27.0", Some(44839), None),
-    (unstable, wasm_target_feature, "1.30.0", Some(44839), None),
+    (unstable, aarch64_ver_target_feature, "1.27.0", Some(44839)),
+    (unstable, arm_target_feature, "1.27.0", Some(44839)),
+    (unstable, avx512_target_feature, "1.27.0", Some(44839)),
+    (unstable, bpf_target_feature, "1.54.0", Some(44839)),
+    (unstable, csky_target_feature, "1.73.0", Some(44839)),
+    (unstable, ermsb_target_feature, "1.49.0", Some(44839)),
+    (unstable, hexagon_target_feature, "1.27.0", Some(44839)),
+    (unstable, loongarch_target_feature, "1.73.0", Some(44839)),
+    (unstable, mips_target_feature, "1.27.0", Some(44839)),
+    (unstable, powerpc_target_feature, "1.27.0", Some(44839)),
+    (unstable, riscv_target_feature, "1.45.0", Some(44839)),
+    (unstable, rtm_target_feature, "1.35.0", Some(44839)),
+    (unstable, sse4a_target_feature, "1.27.0", Some(44839)),
+    (unstable, tbm_target_feature, "1.27.0", Some(44839)),
+    (unstable, wasm_target_feature, "1.30.0", Some(44839)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
@@ -325,295 +322,295 @@ declare_features! (
     // -------------------------------------------------------------------------
 
     /// Allows using the `amdgpu-kernel` ABI.
-    (unstable, abi_amdgpu_kernel, "1.29.0", Some(51575), None),
+    (unstable, abi_amdgpu_kernel, "1.29.0", Some(51575)),
     /// Allows `extern "avr-interrupt" fn()` and `extern "avr-non-blocking-interrupt" fn()`.
-    (unstable, abi_avr_interrupt, "1.45.0", Some(69664), None),
+    (unstable, abi_avr_interrupt, "1.45.0", Some(69664)),
     /// Allows `extern "C-cmse-nonsecure-call" fn()`.
-    (unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391), None),
+    (unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)),
     /// Allows `extern "msp430-interrupt" fn()`.
-    (unstable, abi_msp430_interrupt, "1.16.0", Some(38487), None),
+    (unstable, abi_msp430_interrupt, "1.16.0", Some(38487)),
     /// Allows `extern "ptx-*" fn()`.
-    (unstable, abi_ptx, "1.15.0", Some(38788), None),
+    (unstable, abi_ptx, "1.15.0", Some(38788)),
     /// Allows `extern "riscv-interrupt-m" fn()` and `extern "riscv-interrupt-s" fn()`.
-    (unstable, abi_riscv_interrupt, "1.73.0", Some(111889), None),
+    (unstable, abi_riscv_interrupt, "1.73.0", Some(111889)),
     /// Allows `extern "x86-interrupt" fn()`.
-    (unstable, abi_x86_interrupt, "1.17.0", Some(40180), None),
+    (unstable, abi_x86_interrupt, "1.17.0", Some(40180)),
     /// Allows additional const parameter types, such as `&'static str` or user defined types
-    (incomplete, adt_const_params, "1.56.0", Some(95174), None),
+    (incomplete, adt_const_params, "1.56.0", Some(95174)),
     /// Allows defining an `#[alloc_error_handler]`.
-    (unstable, alloc_error_handler, "1.29.0", Some(51540), None),
+    (unstable, alloc_error_handler, "1.29.0", Some(51540)),
     /// Allows trait methods with arbitrary self types.
-    (unstable, arbitrary_self_types, "1.23.0", Some(44874), None),
+    (unstable, arbitrary_self_types, "1.23.0", Some(44874)),
     /// Allows using `const` operands in inline assembly.
-    (unstable, asm_const, "1.58.0", Some(93332), None),
+    (unstable, asm_const, "1.58.0", Some(93332)),
     /// Enables experimental inline assembly support for additional architectures.
-    (unstable, asm_experimental_arch, "1.58.0", Some(93335), None),
+    (unstable, asm_experimental_arch, "1.58.0", Some(93335)),
     /// Allows the `may_unwind` option in inline assembly.
-    (unstable, asm_unwind, "1.58.0", Some(93334), None),
+    (unstable, asm_unwind, "1.58.0", Some(93334)),
     /// Allows users to enforce equality of associated constants `TraitImpl<AssocConst=3>`.
-    (unstable, associated_const_equality, "1.58.0", Some(92827), None),
+    (unstable, associated_const_equality, "1.58.0", Some(92827)),
     /// Allows the user of associated type bounds.
-    (unstable, associated_type_bounds, "1.34.0", Some(52662), None),
+    (unstable, associated_type_bounds, "1.34.0", Some(52662)),
     /// Allows associated type defaults.
-    (unstable, associated_type_defaults, "1.2.0", Some(29661), None),
+    (unstable, associated_type_defaults, "1.2.0", Some(29661)),
     /// Allows `async || body` closures.
-    (unstable, async_closure, "1.37.0", Some(62290), None),
+    (unstable, async_closure, "1.37.0", Some(62290)),
     /// Allows `#[track_caller]` on async functions.
-    (unstable, async_fn_track_caller, "1.73.0", Some(110011), None),
+    (unstable, async_fn_track_caller, "1.73.0", Some(110011)),
     /// Allows builtin # foo() syntax
-    (unstable, builtin_syntax, "1.71.0", Some(110680), None),
+    (unstable, builtin_syntax, "1.71.0", Some(110680)),
     /// Treat `extern "C"` function as nounwind.
-    (unstable, c_unwind, "1.52.0", Some(74990), None),
+    (unstable, c_unwind, "1.52.0", Some(74990)),
     /// Allows using C-variadics.
-    (unstable, c_variadic, "1.34.0", Some(44930), None),
+    (unstable, c_variadic, "1.34.0", Some(44930)),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
-    (unstable, cfg_overflow_checks, "1.71.0", Some(111466), None),
+    (unstable, cfg_overflow_checks, "1.71.0", Some(111466)),
     /// Provides the relocation model information as cfg entry
-    (unstable, cfg_relocation_model, "1.73.0", Some(114929), None),
+    (unstable, cfg_relocation_model, "1.73.0", Some(114929)),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
-    (unstable, cfg_sanitize, "1.41.0", Some(39699), None),
+    (unstable, cfg_sanitize, "1.41.0", Some(39699)),
     /// Allows `cfg(target_abi = "...")`.
-    (unstable, cfg_target_abi, "1.55.0", Some(80970), None),
+    (unstable, cfg_target_abi, "1.55.0", Some(80970)),
     /// Allows `cfg(target(abi = "..."))`.
-    (unstable, cfg_target_compact, "1.63.0", Some(96901), None),
+    (unstable, cfg_target_compact, "1.63.0", Some(96901)),
     /// Allows `cfg(target_has_atomic_load_store = "...")`.
-    (unstable, cfg_target_has_atomic, "1.60.0", Some(94039), None),
+    (unstable, cfg_target_has_atomic, "1.60.0", Some(94039)),
     /// Allows `cfg(target_has_atomic_equal_alignment = "...")`.
-    (unstable, cfg_target_has_atomic_equal_alignment, "1.60.0", Some(93822), None),
+    (unstable, cfg_target_has_atomic_equal_alignment, "1.60.0", Some(93822)),
     /// Allows `cfg(target_thread_local)`.
-    (unstable, cfg_target_thread_local, "1.7.0", Some(29594), None),
+    (unstable, cfg_target_thread_local, "1.7.0", Some(29594)),
     /// Allow conditional compilation depending on rust version
-    (unstable, cfg_version, "1.45.0", Some(64796), None),
+    (unstable, cfg_version, "1.45.0", Some(64796)),
     /// Allows to use the `#[cfi_encoding = ""]` attribute.
-    (unstable, cfi_encoding, "1.71.0", Some(89653), None),
+    (unstable, cfi_encoding, "1.71.0", Some(89653)),
     /// Allows `for<...>` on closures and coroutines.
-    (unstable, closure_lifetime_binder, "1.64.0", Some(97362), None),
+    (unstable, closure_lifetime_binder, "1.64.0", Some(97362)),
     /// Allows `#[track_caller]` on closures and coroutines.
-    (unstable, closure_track_caller, "1.57.0", Some(87417), None),
+    (unstable, closure_track_caller, "1.57.0", Some(87417)),
     /// Allows to use the `#[cmse_nonsecure_entry]` attribute.
-    (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835), None),
+    (unstable, cmse_nonsecure_entry, "1.48.0", Some(75835)),
     /// Allows use of the `#[collapse_debuginfo]` attribute.
-    (unstable, collapse_debuginfo, "1.65.0", Some(100758), None),
+    (unstable, collapse_debuginfo, "1.65.0", Some(100758)),
     /// Allows `async {}` expressions in const contexts.
-    (unstable, const_async_blocks, "1.53.0", Some(85368), None),
+    (unstable, const_async_blocks, "1.53.0", Some(85368)),
     /// Allows `const || {}` closures in const contexts.
-    (incomplete, const_closures, "1.68.0", Some(106003), None),
+    (incomplete, const_closures, "1.68.0", Some(106003)),
     /// Allows the definition of `const extern fn` and `const unsafe extern fn`.
-    (unstable, const_extern_fn, "1.40.0", Some(64926), None),
+    (unstable, const_extern_fn, "1.40.0", Some(64926)),
     /// Allows basic arithmetic on floating point types in a `const fn`.
-    (unstable, const_fn_floating_point_arithmetic, "1.48.0", Some(57241), None),
+    (unstable, const_fn_floating_point_arithmetic, "1.48.0", Some(57241)),
     /// Allows `for _ in _` loops in const contexts.
-    (unstable, const_for, "1.56.0", Some(87575), None),
+    (unstable, const_for, "1.56.0", Some(87575)),
     /// Allows using `&mut` in constant functions.
-    (unstable, const_mut_refs, "1.41.0", Some(57349), None),
+    (unstable, const_mut_refs, "1.41.0", Some(57349)),
     /// Be more precise when looking for live drops in a const context.
-    (unstable, const_precise_live_drops, "1.46.0", Some(73255), None),
+    (unstable, const_precise_live_drops, "1.46.0", Some(73255)),
     /// Allows references to types with interior mutability within constants
-    (unstable, const_refs_to_cell, "1.51.0", Some(80384), None),
+    (unstable, const_refs_to_cell, "1.51.0", Some(80384)),
     /// Allows `impl const Trait for T` syntax.
-    (unstable, const_trait_impl, "1.42.0", Some(67792), None),
+    (unstable, const_trait_impl, "1.42.0", Some(67792)),
     /// Allows the `?` operator in const contexts.
-    (unstable, const_try, "1.56.0", Some(74935), None),
+    (unstable, const_try, "1.56.0", Some(74935)),
     /// Allows coroutines to be cloned.
-    (unstable, coroutine_clone, "1.65.0", Some(95360), None),
+    (unstable, coroutine_clone, "1.65.0", Some(95360)),
     /// Allows defining coroutines.
-    (unstable, coroutines, "1.21.0", Some(43122), None),
+    (unstable, coroutines, "1.21.0", Some(43122)),
     /// Allows function attribute `#[coverage(on/off)]`, to control coverage
     /// instrumentation of that function.
-    (unstable, coverage_attribute, "1.74.0", Some(84605), None),
+    (unstable, coverage_attribute, "1.74.0", Some(84605)),
     /// Allows users to provide classes for fenced code block using `class:classname`.
-    (unstable, custom_code_classes_in_docs, "1.74.0", Some(79483), None),
+    (unstable, custom_code_classes_in_docs, "1.74.0", Some(79483)),
     /// Allows non-builtin attributes in inner attribute position.
-    (unstable, custom_inner_attributes, "1.30.0", Some(54726), None),
+    (unstable, custom_inner_attributes, "1.30.0", Some(54726)),
     /// Allows custom test frameworks with `#![test_runner]` and `#[test_case]`.
-    (unstable, custom_test_frameworks, "1.30.0", Some(50297), None),
+    (unstable, custom_test_frameworks, "1.30.0", Some(50297)),
     /// Allows declarative macros 2.0 (`macro`).
-    (unstable, decl_macro, "1.17.0", Some(39412), None),
+    (unstable, decl_macro, "1.17.0", Some(39412)),
     /// Allows default type parameters to influence type inference.
-    (unstable, default_type_parameter_fallback, "1.3.0", Some(27336), None),
+    (unstable, default_type_parameter_fallback, "1.3.0", Some(27336)),
     /// Allows using `#[deprecated_safe]` to deprecate the safeness of a function or trait
-    (unstable, deprecated_safe, "1.61.0", Some(94978), None),
+    (unstable, deprecated_safe, "1.61.0", Some(94978)),
     /// Allows having using `suggestion` in the `#[deprecated]` attribute.
-    (unstable, deprecated_suggestion, "1.61.0", Some(94785), None),
+    (unstable, deprecated_suggestion, "1.61.0", Some(94785)),
     /// Allows using the `#[diagnostic]` attribute tool namespace
-    (unstable, diagnostic_namespace, "1.73.0", Some(111996), None),
+    (unstable, diagnostic_namespace, "1.73.0", Some(111996)),
     /// Controls errors in trait implementations.
-    (unstable, do_not_recommend, "1.67.0", Some(51992), None),
+    (unstable, do_not_recommend, "1.67.0", Some(51992)),
     /// Tells rustdoc to automatically generate `#[doc(cfg(...))]`.
-    (unstable, doc_auto_cfg, "1.58.0", Some(43781), None),
+    (unstable, doc_auto_cfg, "1.58.0", Some(43781)),
     /// Allows `#[doc(cfg(...))]`.
-    (unstable, doc_cfg, "1.21.0", Some(43781), None),
+    (unstable, doc_cfg, "1.21.0", Some(43781)),
     /// Allows `#[doc(cfg_hide(...))]`.
-    (unstable, doc_cfg_hide, "1.57.0", Some(43781), None),
+    (unstable, doc_cfg_hide, "1.57.0", Some(43781)),
     /// Allows `#[doc(masked)]`.
-    (unstable, doc_masked, "1.21.0", Some(44027), None),
+    (unstable, doc_masked, "1.21.0", Some(44027)),
     /// Allows `dyn* Trait` objects.
-    (incomplete, dyn_star, "1.65.0", Some(102425), None),
+    (incomplete, dyn_star, "1.65.0", Some(102425)),
     // Uses generic effect parameters for ~const bounds
-    (unstable, effects, "1.72.0", Some(102090), None),
+    (unstable, effects, "1.72.0", Some(102090)),
     /// Allows `X..Y` patterns.
-    (unstable, exclusive_range_pattern, "1.11.0", Some(37854), None),
+    (unstable, exclusive_range_pattern, "1.11.0", Some(37854)),
     /// Allows exhaustive pattern matching on types that contain uninhabited types.
-    (unstable, exhaustive_patterns, "1.13.0", Some(51085), None),
+    (unstable, exhaustive_patterns, "1.13.0", Some(51085)),
     /// Allows explicit tail calls via `become` expression.
-    (incomplete, explicit_tail_calls, "1.72.0", Some(112788), None),
+    (incomplete, explicit_tail_calls, "1.72.0", Some(112788)),
     /// Allows using `efiapi`, `sysv64` and `win64` as calling convention
     /// for functions with varargs.
-    (unstable, extended_varargs_abi_support, "1.65.0", Some(100189), None),
+    (unstable, extended_varargs_abi_support, "1.65.0", Some(100189)),
     /// Allows defining `extern type`s.
-    (unstable, extern_types, "1.23.0", Some(43467), None),
+    (unstable, extern_types, "1.23.0", Some(43467)),
     /// Allows the use of `#[ffi_const]` on foreign functions.
-    (unstable, ffi_const, "1.45.0", Some(58328), None),
+    (unstable, ffi_const, "1.45.0", Some(58328)),
     /// Allows the use of `#[ffi_pure]` on foreign functions.
-    (unstable, ffi_pure, "1.45.0", Some(58329), None),
+    (unstable, ffi_pure, "1.45.0", Some(58329)),
     /// Allows using `#[ffi_returns_twice]` on foreign functions.
-    (unstable, ffi_returns_twice, "1.34.0", Some(58314), None),
+    (unstable, ffi_returns_twice, "1.34.0", Some(58314)),
     /// Allows using `#[repr(align(...))]` on function items
-    (unstable, fn_align, "1.53.0", Some(82232), None),
+    (unstable, fn_align, "1.53.0", Some(82232)),
     /// Support delegating implementation of functions to other already implemented functions.
-    (incomplete, fn_delegation, "CURRENT_RUSTC_VERSION", Some(118212), None),
+    (incomplete, fn_delegation, "CURRENT_RUSTC_VERSION", Some(118212)),
     /// Allows defining gen blocks and `gen fn`.
-    (unstable, gen_blocks, "1.75.0", Some(117078), None),
+    (unstable, gen_blocks, "1.75.0", Some(117078)),
     /// Infer generic args for both consts and types.
-    (unstable, generic_arg_infer, "1.55.0", Some(85077), None),
+    (unstable, generic_arg_infer, "1.55.0", Some(85077)),
     /// An extension to the `generic_associated_types` feature, allowing incomplete features.
-    (incomplete, generic_associated_types_extended, "1.61.0", Some(95451), None),
+    (incomplete, generic_associated_types_extended, "1.61.0", Some(95451)),
     /// Allows non-trivial generic constants which have to have wfness manually propagated to callers
-    (incomplete, generic_const_exprs, "1.56.0", Some(76560), None),
+    (incomplete, generic_const_exprs, "1.56.0", Some(76560)),
     /// Allows generic parameters and where-clauses on free & associated const items.
-    (incomplete, generic_const_items, "1.73.0", Some(113521), None),
+    (incomplete, generic_const_items, "1.73.0", Some(113521)),
     /// Allows using `..=X` as a patterns in slices.
-    (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264), None),
+    (unstable, half_open_range_patterns_in_slices, "1.66.0", Some(67264)),
     /// Allows `if let` guard in match arms.
-    (unstable, if_let_guard, "1.47.0", Some(51114), None),
+    (unstable, if_let_guard, "1.47.0", Some(51114)),
     /// Allows `impl Trait` to be used inside associated types (RFC 2515).
-    (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063), None),
+    (unstable, impl_trait_in_assoc_type, "1.70.0", Some(63063)),
     /// Allows `impl Trait` as output type in `Fn` traits in return position of functions.
-    (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697), None),
+    (unstable, impl_trait_in_fn_trait_return, "1.64.0", Some(99697)),
     /// Allows using imported `main` function
-    (unstable, imported_main, "1.53.0", Some(28937), None),
+    (unstable, imported_main, "1.53.0", Some(28937)),
     /// Allows associated types in inherent impls.
-    (incomplete, inherent_associated_types, "1.52.0", Some(8995), None),
+    (incomplete, inherent_associated_types, "1.52.0", Some(8995)),
     /// Allow anonymous constants from an inline `const` block
-    (unstable, inline_const, "1.49.0", Some(76001), None),
+    (unstable, inline_const, "1.49.0", Some(76001)),
     /// Allow anonymous constants from an inline `const` block in pattern position
-    (incomplete, inline_const_pat, "1.58.0", Some(76001), None),
+    (incomplete, inline_const_pat, "1.58.0", Some(76001)),
     /// Allows using `pointer` and `reference` in intra-doc links
-    (unstable, intra_doc_pointers, "1.51.0", Some(80896), None),
+    (unstable, intra_doc_pointers, "1.51.0", Some(80896)),
     // Allows setting the threshold for the `large_assignments` lint.
-    (unstable, large_assignments, "1.52.0", Some(83518), None),
+    (unstable, large_assignments, "1.52.0", Some(83518)),
     /// Allow to have type alias types for inter-crate use.
-    (incomplete, lazy_type_alias, "1.72.0", Some(112792), None),
+    (incomplete, lazy_type_alias, "1.72.0", Some(112792)),
     /// Allows `if/while p && let q = r && ...` chains.
-    (unstable, let_chains, "1.37.0", Some(53667), None),
+    (unstable, let_chains, "1.37.0", Some(53667)),
     /// Allows using `#[link(kind = "link-arg", name = "...")]`
     /// to pass custom arguments to the linker.
-    (unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427), None),
+    (unstable, link_arg_attribute, "CURRENT_RUSTC_VERSION", Some(99427)),
     /// Allows using `reason` in lint attributes and the `#[expect(lint)]` lint check.
-    (unstable, lint_reasons, "1.31.0", Some(54503), None),
+    (unstable, lint_reasons, "1.31.0", Some(54503)),
     /// Give access to additional metadata about declarative macro meta-variables.
-    (unstable, macro_metavar_expr, "1.61.0", Some(83527), None),
+    (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Allows `#[marker]` on certain traits allowing overlapping implementations.
-    (unstable, marker_trait_attr, "1.30.0", Some(29864), None),
+    (unstable, marker_trait_attr, "1.30.0", Some(29864)),
     /// A minimal, sound subset of specialization intended to be used by the
     /// standard library until the soundness issues with specialization
     /// are fixed.
-    (unstable, min_specialization, "1.7.0", Some(31844), None),
+    (unstable, min_specialization, "1.7.0", Some(31844)),
     /// Allows qualified paths in struct expressions, struct patterns and tuple struct patterns.
-    (unstable, more_qualified_paths, "1.54.0", Some(86935), None),
+    (unstable, more_qualified_paths, "1.54.0", Some(86935)),
     /// Allows the `#[must_not_suspend]` attribute.
-    (unstable, must_not_suspend, "1.57.0", Some(83310), None),
+    (unstable, must_not_suspend, "1.57.0", Some(83310)),
     /// Allows using `#[naked]` on functions.
-    (unstable, naked_functions, "1.9.0", Some(32408), None),
+    (unstable, naked_functions, "1.9.0", Some(32408)),
     /// Allows specifying the as-needed link modifier
-    (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490), None),
+    (unstable, native_link_modifiers_as_needed, "1.53.0", Some(81490)),
     /// Allow negative trait implementations.
-    (unstable, negative_impls, "1.44.0", Some(68318), None),
+    (unstable, negative_impls, "1.44.0", Some(68318)),
     /// Allows the `!` pattern.
-    (incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155), None),
+    (incomplete, never_patterns, "CURRENT_RUSTC_VERSION", Some(118155)),
     /// Allows the `!` type. Does not imply 'exhaustive_patterns' (below) any more.
-    (unstable, never_type, "1.13.0", Some(35121), None),
+    (unstable, never_type, "1.13.0", Some(35121)),
     /// Allows diverging expressions to fall back to `!` rather than `()`.
-    (unstable, never_type_fallback, "1.41.0", Some(65992), None),
+    (unstable, never_type_fallback, "1.41.0", Some(65992)),
     /// Allows `#![no_core]`.
-    (unstable, no_core, "1.3.0", Some(29639), None),
+    (unstable, no_core, "1.3.0", Some(29639)),
     /// Allows the use of `no_sanitize` attribute.
-    (unstable, no_sanitize, "1.42.0", Some(39699), None),
+    (unstable, no_sanitize, "1.42.0", Some(39699)),
     /// Allows using the `non_exhaustive_omitted_patterns` lint.
-    (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554), None),
+    (unstable, non_exhaustive_omitted_patterns_lint, "1.57.0", Some(89554)),
     /// Allows `for<T>` binders in where-clauses
-    (incomplete, non_lifetime_binders, "1.69.0", Some(108185), None),
+    (incomplete, non_lifetime_binders, "1.69.0", Some(108185)),
     /// Allows making `dyn Trait` well-formed even if `Trait` is not object safe.
     /// In that case, `dyn Trait: Trait` does not hold. Moreover, coercions and
     /// casts in safe Rust to `dyn Trait` for such a `Trait` is also forbidden.
-    (unstable, object_safe_for_dispatch, "1.40.0", Some(43561), None),
+    (unstable, object_safe_for_dispatch, "1.40.0", Some(43561)),
     /// Allows using enums in offset_of!
-    (unstable, offset_of_enum, "1.75.0", Some(106655), None),
+    (unstable, offset_of_enum, "1.75.0", Some(106655)),
     /// Allows using `#[optimize(X)]`.
-    (unstable, optimize_attribute, "1.34.0", Some(54882), None),
+    (unstable, optimize_attribute, "1.34.0", Some(54882)),
     /// Allows macro attributes on expressions, statements and non-inline modules.
-    (unstable, proc_macro_hygiene, "1.30.0", Some(54727), None),
+    (unstable, proc_macro_hygiene, "1.30.0", Some(54727)),
     /// Allows `&raw const $place_expr` and `&raw mut $place_expr` expressions.
-    (unstable, raw_ref_op, "1.41.0", Some(64490), None),
+    (unstable, raw_ref_op, "1.41.0", Some(64490)),
     /// Allows using the `#[register_tool]` attribute.
-    (unstable, register_tool, "1.41.0", Some(66079), None),
+    (unstable, register_tool, "1.41.0", Some(66079)),
     /// Allows the `#[repr(i128)]` attribute for enums.
-    (incomplete, repr128, "1.16.0", Some(56071), None),
+    (incomplete, repr128, "1.16.0", Some(56071)),
     /// Allows `repr(simd)` and importing the various simd intrinsics.
-    (unstable, repr_simd, "1.4.0", Some(27731), None),
+    (unstable, repr_simd, "1.4.0", Some(27731)),
     /// Allows bounding the return type of AFIT/RPITIT.
-    (incomplete, return_type_notation, "1.70.0", Some(109417), None),
+    (incomplete, return_type_notation, "1.70.0", Some(109417)),
     /// Allows `extern "rust-cold"`.
-    (unstable, rust_cold_cc, "1.63.0", Some(97544), None),
+    (unstable, rust_cold_cc, "1.63.0", Some(97544)),
     /// Allows the use of SIMD types in functions declared in `extern` blocks.
-    (unstable, simd_ffi, "1.0.0", Some(27731), None),
+    (unstable, simd_ffi, "1.0.0", Some(27731)),
     /// Allows specialization of implementations (RFC 1210).
-    (incomplete, specialization, "1.7.0", Some(31844), None),
+    (incomplete, specialization, "1.7.0", Some(31844)),
     /// Allows attributes on expressions and non-item statements.
-    (unstable, stmt_expr_attributes, "1.6.0", Some(15701), None),
+    (unstable, stmt_expr_attributes, "1.6.0", Some(15701)),
     /// Allows lints part of the strict provenance effort.
-    (unstable, strict_provenance, "1.61.0", Some(95228), None),
+    (unstable, strict_provenance, "1.61.0", Some(95228)),
     /// Allows string patterns to dereference values to match them.
-    (unstable, string_deref_patterns, "1.67.0", Some(87121), None),
+    (unstable, string_deref_patterns, "1.67.0", Some(87121)),
     /// Allows the use of `#[target_feature]` on safe functions.
-    (unstable, target_feature_11, "1.45.0", Some(69098), None),
+    (unstable, target_feature_11, "1.45.0", Some(69098)),
     /// Allows using `#[thread_local]` on `static` items.
-    (unstable, thread_local, "1.0.0", Some(29594), None),
+    (unstable, thread_local, "1.0.0", Some(29594)),
     /// Allows defining `trait X = A + B;` alias items.
-    (unstable, trait_alias, "1.24.0", Some(41517), None),
+    (unstable, trait_alias, "1.24.0", Some(41517)),
     /// Allows for transmuting between arrays with sizes that contain generic consts.
-    (unstable, transmute_generic_consts, "1.70.0", Some(109929), None),
+    (unstable, transmute_generic_consts, "1.70.0", Some(109929)),
     /// Allows #[repr(transparent)] on unions (RFC 2645).
-    (unstable, transparent_unions, "1.37.0", Some(60405), None),
+    (unstable, transparent_unions, "1.37.0", Some(60405)),
     /// Allows inconsistent bounds in where clauses.
-    (unstable, trivial_bounds, "1.28.0", Some(48214), None),
+    (unstable, trivial_bounds, "1.28.0", Some(48214)),
     /// Allows using `try {...}` expressions.
-    (unstable, try_blocks, "1.29.0", Some(31436), None),
+    (unstable, try_blocks, "1.29.0", Some(31436)),
     /// Allows `impl Trait` to be used inside type aliases (RFC 2515).
-    (unstable, type_alias_impl_trait, "1.38.0", Some(63063), None),
+    (unstable, type_alias_impl_trait, "1.38.0", Some(63063)),
     /// Allows the use of type ascription in expressions.
-    (unstable, type_ascription, "1.6.0", Some(23416), None),
+    (unstable, type_ascription, "1.6.0", Some(23416)),
     /// Allows creation of instances of a struct by moving fields that have
     /// not changed from prior instances of the same struct (RFC #2528)
-    (unstable, type_changing_struct_update, "1.58.0", Some(86555), None),
+    (unstable, type_changing_struct_update, "1.58.0", Some(86555)),
     /// Allows using type privacy lints (`private_interfaces`, `private_bounds`, `unnameable_types`).
-    (unstable, type_privacy_lints, "1.72.0", Some(48054), None),
+    (unstable, type_privacy_lints, "1.72.0", Some(48054)),
     /// Enables rustc to generate code that instructs libstd to NOT ignore SIGPIPE.
-    (unstable, unix_sigpipe, "1.65.0", Some(97889), None),
+    (unstable, unix_sigpipe, "1.65.0", Some(97889)),
     /// Allows unnamed fields of struct and union type
-    (incomplete, unnamed_fields, "1.74.0", Some(49804), None),
+    (incomplete, unnamed_fields, "1.74.0", Some(49804)),
     /// Allows unsized fn parameters.
-    (unstable, unsized_fn_params, "1.49.0", Some(48055), None),
+    (unstable, unsized_fn_params, "1.49.0", Some(48055)),
     /// Allows unsized rvalues at arguments and parameters.
-    (incomplete, unsized_locals, "1.30.0", Some(48055), None),
+    (incomplete, unsized_locals, "1.30.0", Some(48055)),
     /// Allows unsized tuple coercion.
-    (unstable, unsized_tuple_coercion, "1.20.0", Some(42877), None),
+    (unstable, unsized_tuple_coercion, "1.20.0", Some(42877)),
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
-    (unstable, used_with_arg, "1.60.0", Some(93798), None),
+    (unstable, used_with_arg, "1.60.0", Some(93798)),
     /// Allows `extern "wasm" fn`
-    (unstable, wasm_abi, "1.53.0", Some(83788), None),
+    (unstable, wasm_abi, "1.53.0", Some(83788)),
     /// Allows `do yeet` expressions
-    (unstable, yeet_expr, "1.62.0", Some(96373), None),
+    (unstable, yeet_expr, "1.62.0", Some(96373)),
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
     // Features are listed in alphabetical order. Tidy will fail if you don't keep it this way.
     // !!!!    !!!!    !!!!    !!!!   !!!!    !!!!    !!!!    !!!!    !!!!    !!!!    !!!!
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 56e272b14bd..ec589e2dbbc 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -1,5 +1,5 @@
 use crate::check::intrinsicck::InlineAsmCtxt;
-use crate::errors::{self, LinkageType};
+use crate::errors::LinkageType;
 
 use super::compare_impl_item::check_type_bounds;
 use super::compare_impl_item::{compare_impl_method, compare_impl_ty};
@@ -8,9 +8,8 @@ use rustc_attr as attr;
 use rustc_errors::{ErrorGuaranteed, MultiSpan};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorKind, DefKind};
-use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId};
+use rustc_hir::def_id::LocalModDefId;
 use rustc_hir::Node;
-use rustc_infer::infer::outlives::env::OutlivesEnvironment;
 use rustc_infer::infer::{RegionVariableOrigin, TyCtxtInferExt};
 use rustc_infer::traits::{Obligation, TraitEngineExt as _};
 use rustc_lint_defs::builtin::REPR_TRANSPARENT_EXTERNAL_PRIVATE_FIELDS;
@@ -21,18 +20,15 @@ use rustc_middle::ty::layout::{LayoutError, MAX_SIMD_LANES};
 use rustc_middle::ty::util::{Discr, IntTypeExt};
 use rustc_middle::ty::GenericArgKind;
 use rustc_middle::ty::{
-    self, AdtDef, ParamEnv, RegionKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable,
-    TypeVisitableExt,
+    AdtDef, ParamEnv, RegionKind, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
 use rustc_session::lint::builtin::{UNINHABITED_STATIC, UNSUPPORTED_CALLING_CONVENTIONS};
 use rustc_span::symbol::sym;
-use rustc_span::{self, Span};
 use rustc_target::abi::FieldIdx;
-use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::traits::error_reporting::on_unimplemented::OnUnimplementedDirective;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
 use rustc_trait_selection::traits::outlives_bounds::InferCtxtExt as _;
-use rustc_trait_selection::traits::{self, ObligationCtxt, TraitEngine, TraitEngineExt as _};
+use rustc_trait_selection::traits::{self, TraitEngine, TraitEngineExt as _};
 use rustc_type_ir::fold::TypeFoldable;
 
 use std::ops::ControlFlow;
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 1c4534287eb..8701626058d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -16,7 +16,7 @@ use rustc_hir::{BindingAnnotation, ByRef, GenericArg, GenericParam, GenericParam
 use rustc_hir::{GenericBound, PatKind, RangeEnd, TraitBoundModifier};
 use rustc_span::source_map::SourceMap;
 use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{self, FileName};
+use rustc_span::FileName;
 use rustc_target::spec::abi::Abi;
 
 use std::cell::Cell;
diff --git a/compiler/rustc_hir_typeck/src/callee.rs b/compiler/rustc_hir_typeck/src/callee.rs
index a907acba0e0..512946cc504 100644
--- a/compiler/rustc_hir_typeck/src/callee.rs
+++ b/compiler/rustc_hir_typeck/src/callee.rs
@@ -780,7 +780,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let generics = tcx.generics_of(callee_did);
         let Some(host_effect_index) = generics.host_effect_index else { return };
 
-        let effect = tcx.expected_const_effect_param_for_body(self.body_id);
+        let effect = tcx.expected_host_effect_param_for_body(self.body_id);
 
         trace!(?effect, ?generics, ?callee_args);
 
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 7f56b3850dd..0d3bb0f7e0c 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -58,7 +58,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, GenericArgsRef, Ty, TyCtxt, TypeAndMut};
 use rustc_session::parse::feature_err;
 use rustc_span::symbol::sym;
-use rustc_span::{self, DesugaringKind};
+use rustc_span::DesugaringKind;
 use rustc_target::spec::abi::Abi;
 use rustc_trait_selection::infer::InferCtxtExt as _;
 use rustc_trait_selection::traits::error_reporting::TypeErrCtxtExt as _;
diff --git a/compiler/rustc_hir_typeck/src/diverges.rs b/compiler/rustc_hir_typeck/src/diverges.rs
index 29fcc61cbb5..0b559a0858e 100644
--- a/compiler/rustc_hir_typeck/src/diverges.rs
+++ b/compiler/rustc_hir_typeck/src/diverges.rs
@@ -1,4 +1,4 @@
-use rustc_span::{self, Span, DUMMY_SP};
+use rustc_span::{Span, DUMMY_SP};
 use std::{cmp, ops};
 
 /// Tracks whether executing a node may exit normally (versus
diff --git a/compiler/rustc_hir_typeck/src/expectation.rs b/compiler/rustc_hir_typeck/src/expectation.rs
index 35e5fb769a5..ff84e753d70 100644
--- a/compiler/rustc_hir_typeck/src/expectation.rs
+++ b/compiler/rustc_hir_typeck/src/expectation.rs
@@ -1,6 +1,6 @@
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{self, Span};
+use rustc_span::Span;
 
 use super::Expectation::*;
 use super::FnCtxt;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
index e3aca11fd03..9b5459529ff 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/adjust_fulfillment_errors.rs
@@ -4,7 +4,7 @@ use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::DefId;
 use rustc_infer::{infer::type_variable::TypeVariableOriginKind, traits::ObligationCauseCode};
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitor};
-use rustc_span::{self, symbol::kw, Span};
+use rustc_span::{symbol::kw, Span};
 use rustc_trait_selection::traits;
 
 use std::ops::ControlFlow;
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 509596c1e90..bb9b849f03b 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -33,7 +33,7 @@ use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, IsSuggestable, Ty, TyCtxt};
 use rustc_session::Session;
 use rustc_span::symbol::{kw, Ident};
-use rustc_span::{self, sym, BytePos, Span};
+use rustc_span::{sym, BytePos, Span};
 use rustc_trait_selection::traits::{self, ObligationCauseCode, SelectionContext};
 
 use std::iter;
diff --git a/compiler/rustc_hir_typeck/src/inherited.rs b/compiler/rustc_hir_typeck/src/inherited.rs
index 281074a8519..7a6a2b2a010 100644
--- a/compiler/rustc_hir_typeck/src/inherited.rs
+++ b/compiler/rustc_hir_typeck/src/inherited.rs
@@ -9,7 +9,7 @@ use rustc_middle::traits::DefiningAnchor;
 use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::LocalDefIdMap;
-use rustc_span::{self, Span};
+use rustc_span::Span;
 use rustc_trait_selection::traits::query::evaluate_obligation::InferCtxtExt;
 use rustc_trait_selection::traits::{self, PredicateObligation, TraitEngine, TraitEngineExt as _};
 
diff --git a/compiler/rustc_hir_typeck/src/op.rs b/compiler/rustc_hir_typeck/src/op.rs
index 1e9387ef041..59b4b0032f8 100644
--- a/compiler/rustc_hir_typeck/src/op.rs
+++ b/compiler/rustc_hir_typeck/src/op.rs
@@ -4,7 +4,7 @@ use super::method::MethodCallee;
 use super::{has_expected_num_generic_args, FnCtxt};
 use crate::Expectation;
 use rustc_ast as ast;
-use rustc_errors::{self, struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
+use rustc_errors::{struct_span_err, Applicability, Diagnostic, DiagnosticBuilder};
 use rustc_hir as hir;
 use rustc_infer::infer::type_variable::{TypeVariableOrigin, TypeVariableOriginKind};
 use rustc_infer::traits::ObligationCauseCode;
diff --git a/compiler/rustc_incremental/src/persist/dirty_clean.rs b/compiler/rustc_incremental/src/persist/dirty_clean.rs
index eaf83b7ee5f..0f2194139df 100644
--- a/compiler/rustc_incremental/src/persist/dirty_clean.rs
+++ b/compiler/rustc_incremental/src/persist/dirty_clean.rs
@@ -32,7 +32,6 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::TyCtxt;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::Span;
-use std::iter::FromIterator;
 use thin_vec::ThinVec;
 
 const LOADED_FROM_DISK: Symbol = sym::loaded_from_disk;
diff --git a/compiler/rustc_infer/src/errors/note_and_explain.rs b/compiler/rustc_infer/src/errors/note_and_explain.rs
index 3ee4710bdef..68bf36a1615 100644
--- a/compiler/rustc_infer/src/errors/note_and_explain.rs
+++ b/compiler/rustc_infer/src/errors/note_and_explain.rs
@@ -1,6 +1,6 @@
 use crate::fluent_generated as fluent;
 use crate::infer::error_reporting::nice_region_error::find_anon_type;
-use rustc_errors::{self, AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
+use rustc_errors::{AddToDiagnostic, Diagnostic, IntoDiagnosticArg, SubdiagnosticMessage};
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::{symbol::kw, Span};
 
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 09d92c2dfc0..9b59ead0463 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -22,7 +22,7 @@ use rustc_middle::ty::{self, GlobalCtxt, RegisteredTools, TyCtxt};
 use rustc_middle::util::Providers;
 use rustc_mir_build as mir_build;
 use rustc_parse::{parse_crate_from_file, parse_crate_from_source_str, validate_attr};
-use rustc_passes::{self, abi_test, hir_stats, layout_test};
+use rustc_passes::{abi_test, hir_stats, layout_test};
 use rustc_resolve::Resolver;
 use rustc_session::code_stats::VTableSizeInfo;
 use rustc_session::config::{CrateType, Input, OutFileName, OutputFilenames, OutputType};
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 2db610d640c..40e6b1b579f 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -1,3 +1,7 @@
+lint_ambiguous_wide_pointer_comparisons = ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+    .addr_metadata_suggestion = use explicit `std::ptr::eq` method to compare metadata and addresses
+    .addr_suggestion = use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+
 lint_array_into_iter =
     this method call resolves to `<&{$target} as IntoIterator>::into_iter` (due to backwards compatibility), but will resolve to <{$target} as IntoIterator>::into_iter in Rust 2021
     .use_iter_suggestion = use `.iter()` instead of `.into_iter()` to avoid ambiguity
diff --git a/compiler/rustc_lint/src/builtin.rs b/compiler/rustc_lint/src/builtin.rs
index 64de5e92abf..32eb67ba3a1 100644
--- a/compiler/rustc_lint/src/builtin.rs
+++ b/compiler/rustc_lint/src/builtin.rs
@@ -40,7 +40,6 @@ use crate::{
     },
     EarlyContext, EarlyLintPass, LateContext, LateLintPass, Level, LintContext,
 };
-use rustc_ast::attr;
 use rustc_ast::tokenstream::{TokenStream, TokenTree};
 use rustc_ast::visit::{FnCtxt, FnKind};
 use rustc_ast::{self as ast, *};
@@ -1836,7 +1835,7 @@ impl KeywordIdents {
                         self.check_ident_token(cx, UnderMacro(true), ident);
                     }
                 }
-                TokenTree::Delimited(_, _, tts) => self.check_tokens(cx, tts),
+                TokenTree::Delimited(.., tts) => self.check_tokens(cx, tts),
             }
         }
     }
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 8e95a71e11f..83414ee702f 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -94,9 +94,6 @@ pub use array_into_iter::ARRAY_INTO_ITER;
 use rustc_hir::def_id::LocalModDefId;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::TyCtxt;
-use rustc_session::lint::builtin::{
-    BARE_TRAIT_OBJECTS, ELIDED_LIFETIMES_IN_PATHS, EXPLICIT_OUTLIVES_REQUIREMENTS,
-};
 
 use array_into_iter::ArrayIntoIter;
 use async_fn_in_trait::AsyncFnInTrait;
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 9fda53c2533..d0b895f7354 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -1574,6 +1574,76 @@ pub enum InvalidNanComparisonsSuggestion {
     Spanless,
 }
 
+#[derive(LintDiagnostic)]
+pub enum AmbiguousWidePointerComparisons<'a> {
+    #[diag(lint_ambiguous_wide_pointer_comparisons)]
+    Spanful {
+        #[subdiagnostic]
+        addr_suggestion: AmbiguousWidePointerComparisonsAddrSuggestion<'a>,
+        #[subdiagnostic]
+        addr_metadata_suggestion: Option<AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a>>,
+    },
+    #[diag(lint_ambiguous_wide_pointer_comparisons)]
+    #[help(lint_addr_metadata_suggestion)]
+    #[help(lint_addr_suggestion)]
+    Spanless,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(
+    lint_addr_metadata_suggestion,
+    style = "verbose",
+    applicability = "machine-applicable"
+)]
+pub struct AmbiguousWidePointerComparisonsAddrMetadataSuggestion<'a> {
+    pub ne: &'a str,
+    pub deref_left: &'a str,
+    pub deref_right: &'a str,
+    #[suggestion_part(code = "{ne}std::ptr::eq({deref_left}")]
+    pub left: Span,
+    #[suggestion_part(code = ", {deref_right}")]
+    pub middle: Span,
+    #[suggestion_part(code = ")")]
+    pub right: Span,
+}
+
+#[derive(Subdiagnostic)]
+pub enum AmbiguousWidePointerComparisonsAddrSuggestion<'a> {
+    #[multipart_suggestion(
+        lint_addr_suggestion,
+        style = "verbose",
+        applicability = "machine-applicable"
+    )]
+    AddrEq {
+        ne: &'a str,
+        deref_left: &'a str,
+        deref_right: &'a str,
+        #[suggestion_part(code = "{ne}std::ptr::addr_eq({deref_left}")]
+        left: Span,
+        #[suggestion_part(code = ", {deref_right}")]
+        middle: Span,
+        #[suggestion_part(code = ")")]
+        right: Span,
+    },
+    #[multipart_suggestion(
+        lint_addr_suggestion,
+        style = "verbose",
+        applicability = "machine-applicable"
+    )]
+    Cast {
+        deref_left: &'a str,
+        deref_right: &'a str,
+        #[suggestion_part(code = "{deref_left}")]
+        left_before: Option<Span>,
+        #[suggestion_part(code = " as *const ()")]
+        left: Span,
+        #[suggestion_part(code = "{deref_right}")]
+        right_before: Option<Span>,
+        #[suggestion_part(code = " as *const ()")]
+        right: Span,
+    },
+}
+
 pub struct ImproperCTypes<'a> {
     pub ty: Ty<'a>,
     pub desc: &'a str,
diff --git a/compiler/rustc_lint/src/types.rs b/compiler/rustc_lint/src/types.rs
index bae63ae1716..810d691d16a 100644
--- a/compiler/rustc_lint/src/types.rs
+++ b/compiler/rustc_lint/src/types.rs
@@ -1,12 +1,13 @@
 use crate::{
     fluent_generated as fluent,
     lints::{
-        AtomicOrderingFence, AtomicOrderingLoad, AtomicOrderingStore, ImproperCTypes,
-        InvalidAtomicOrderingDiag, InvalidNanComparisons, InvalidNanComparisonsSuggestion,
-        OnlyCastu8ToChar, OverflowingBinHex, OverflowingBinHexSign, OverflowingBinHexSignBitSub,
-        OverflowingBinHexSub, OverflowingInt, OverflowingIntHelp, OverflowingLiteral,
-        OverflowingUInt, RangeEndpointOutOfRange, UnusedComparisons, UseInclusiveRange,
-        VariantSizeDifferencesDiag,
+        AmbiguousWidePointerComparisons, AmbiguousWidePointerComparisonsAddrMetadataSuggestion,
+        AmbiguousWidePointerComparisonsAddrSuggestion, AtomicOrderingFence, AtomicOrderingLoad,
+        AtomicOrderingStore, ImproperCTypes, InvalidAtomicOrderingDiag, InvalidNanComparisons,
+        InvalidNanComparisonsSuggestion, OnlyCastu8ToChar, OverflowingBinHex,
+        OverflowingBinHexSign, OverflowingBinHexSignBitSub, OverflowingBinHexSub, OverflowingInt,
+        OverflowingIntHelp, OverflowingLiteral, OverflowingUInt, RangeEndpointOutOfRange,
+        UnusedComparisons, UseInclusiveRange, VariantSizeDifferencesDiag,
     },
 };
 use crate::{LateContext, LateLintPass, LintContext};
@@ -17,10 +18,10 @@ use rustc_errors::DiagnosticMessage;
 use rustc_hir as hir;
 use rustc_hir::{is_range_literal, Expr, ExprKind, Node};
 use rustc_middle::ty::layout::{IntegerExt, LayoutOf, SizeSkeleton};
-use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{
     self, AdtKind, Ty, TyCtxt, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
+use rustc_middle::ty::{GenericArgsRef, TypeAndMut};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::source_map;
 use rustc_span::symbol::sym;
@@ -28,6 +29,7 @@ use rustc_span::{Span, Symbol};
 use rustc_target::abi::{Abi, Size, WrappingRange};
 use rustc_target::abi::{Integer, TagEncoding, Variants};
 use rustc_target::spec::abi::Abi as SpecAbi;
+use rustc_type_ir::DynKind;
 
 use std::iter;
 use std::ops::ControlFlow;
@@ -136,6 +138,37 @@ declare_lint! {
     "detects invalid floating point NaN comparisons"
 }
 
+declare_lint! {
+    /// The `ambiguous_wide_pointer_comparisons` lint checks comparison
+    /// of `*const/*mut ?Sized` as the operands.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # struct A;
+    /// # struct B;
+    ///
+    /// # trait T {}
+    /// # impl T for A {}
+    /// # impl T for B {}
+    ///
+    /// let ab = (A, B);
+    /// let a = &ab.0 as *const dyn T;
+    /// let b = &ab.1 as *const dyn T;
+    ///
+    /// let _ = a == b;
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// The comparison includes metadata which may not be expected.
+    AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+    Warn,
+    "detects ambiguous wide pointer comparisons"
+}
+
 #[derive(Copy, Clone)]
 pub struct TypeLimits {
     /// Id of the last visited negated expression
@@ -144,7 +177,12 @@ pub struct TypeLimits {
     negated_expr_span: Option<Span>,
 }
 
-impl_lint_pass!(TypeLimits => [UNUSED_COMPARISONS, OVERFLOWING_LITERALS, INVALID_NAN_COMPARISONS]);
+impl_lint_pass!(TypeLimits => [
+    UNUSED_COMPARISONS,
+    OVERFLOWING_LITERALS,
+    INVALID_NAN_COMPARISONS,
+    AMBIGUOUS_WIDE_POINTER_COMPARISONS
+]);
 
 impl TypeLimits {
     pub fn new() -> TypeLimits {
@@ -620,6 +658,106 @@ fn lint_nan<'tcx>(
     cx.emit_spanned_lint(INVALID_NAN_COMPARISONS, e.span, lint);
 }
 
+fn lint_wide_pointer<'tcx>(
+    cx: &LateContext<'tcx>,
+    e: &'tcx hir::Expr<'tcx>,
+    binop: hir::BinOpKind,
+    l: &'tcx hir::Expr<'tcx>,
+    r: &'tcx hir::Expr<'tcx>,
+) {
+    let ptr_unsized = |mut ty: Ty<'tcx>| -> Option<(usize, bool)> {
+        let mut refs = 0;
+        // here we remove any "implicit" references and count the number
+        // of them to correctly suggest the right number of deref
+        while let ty::Ref(_, inner_ty, _) = ty.kind() {
+            ty = *inner_ty;
+            refs += 1;
+        }
+        match ty.kind() {
+            ty::RawPtr(TypeAndMut { mutbl: _, ty }) => (!ty.is_sized(cx.tcx, cx.param_env))
+                .then(|| (refs, matches!(ty.kind(), ty::Dynamic(_, _, DynKind::Dyn)))),
+            _ => None,
+        }
+    };
+
+    // PartialEq::{eq,ne} takes references, remove any explicit references
+    let l = l.peel_borrows();
+    let r = r.peel_borrows();
+
+    let Some(l_ty) = cx.typeck_results().expr_ty_opt(l) else {
+        return;
+    };
+    let Some(r_ty) = cx.typeck_results().expr_ty_opt(r) else {
+        return;
+    };
+
+    let Some((l_ty_refs, l_inner_ty_is_dyn)) = ptr_unsized(l_ty) else {
+        return;
+    };
+    let Some((r_ty_refs, r_inner_ty_is_dyn)) = ptr_unsized(r_ty) else {
+        return;
+    };
+
+    let (Some(l_span), Some(r_span)) =
+        (l.span.find_ancestor_inside(e.span), r.span.find_ancestor_inside(e.span))
+    else {
+        return cx.emit_spanned_lint(
+            AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+            e.span,
+            AmbiguousWidePointerComparisons::Spanless,
+        );
+    };
+
+    let ne = if binop == hir::BinOpKind::Ne { "!" } else { "" };
+    let is_eq_ne = matches!(binop, hir::BinOpKind::Eq | hir::BinOpKind::Ne);
+    let is_dyn_comparison = l_inner_ty_is_dyn && r_inner_ty_is_dyn;
+
+    let left = e.span.shrink_to_lo().until(l_span.shrink_to_lo());
+    let middle = l_span.shrink_to_hi().until(r_span.shrink_to_lo());
+    let right = r_span.shrink_to_hi().until(e.span.shrink_to_hi());
+
+    let deref_left = &*"*".repeat(l_ty_refs);
+    let deref_right = &*"*".repeat(r_ty_refs);
+
+    cx.emit_spanned_lint(
+        AMBIGUOUS_WIDE_POINTER_COMPARISONS,
+        e.span,
+        AmbiguousWidePointerComparisons::Spanful {
+            addr_metadata_suggestion: (is_eq_ne && !is_dyn_comparison).then(|| {
+                AmbiguousWidePointerComparisonsAddrMetadataSuggestion {
+                    ne,
+                    deref_left,
+                    deref_right,
+                    left,
+                    middle,
+                    right,
+                }
+            }),
+            addr_suggestion: if is_eq_ne {
+                AmbiguousWidePointerComparisonsAddrSuggestion::AddrEq {
+                    ne,
+                    deref_left,
+                    deref_right,
+                    left,
+                    middle,
+                    right,
+                }
+            } else {
+                AmbiguousWidePointerComparisonsAddrSuggestion::Cast {
+                    deref_left,
+                    deref_right,
+                    // those two Options are required for correctness as having
+                    // an empty span and an empty suggestion is not permitted
+                    left_before: (l_ty_refs != 0).then_some(left),
+                    right_before: (r_ty_refs != 0).then(|| r_span.shrink_to_lo()),
+                    left: l_span.shrink_to_hi(),
+                    right,
+                }
+            },
+        },
+    );
+}
+
 impl<'tcx> LateLintPass<'tcx> for TypeLimits {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx hir::Expr<'tcx>) {
         match e.kind {
@@ -636,10 +774,26 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                         cx.emit_spanned_lint(UNUSED_COMPARISONS, e.span, UnusedComparisons);
                     } else {
                         lint_nan(cx, e, binop, l, r);
+                        lint_wide_pointer(cx, e, binop.node, l, r);
                     }
                 }
             }
             hir::ExprKind::Lit(lit) => lint_literal(cx, self, e, lit),
+            hir::ExprKind::Call(path, [l, r])
+                if let ExprKind::Path(ref qpath) = path.kind
+                    && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                    && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+                    && let Some(binop) = partialeq_binop(diag_item) =>
+            {
+                lint_wide_pointer(cx, e, binop, l, r);
+            }
+            hir::ExprKind::MethodCall(_, l, [r], _)
+                if let Some(def_id) = cx.typeck_results().type_dependent_def_id(e.hir_id)
+                    && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+                    && let Some(binop) = partialeq_binop(diag_item) =>
+            {
+                lint_wide_pointer(cx, e, binop, l, r);
+            }
             _ => {}
         };
 
@@ -722,6 +876,16 @@ impl<'tcx> LateLintPass<'tcx> for TypeLimits {
                     | hir::BinOpKind::Gt
             )
         }
+
+        fn partialeq_binop(diag_item: Symbol) -> Option<hir::BinOpKind> {
+            if diag_item == sym::cmp_partialeq_eq {
+                Some(hir::BinOpKind::Eq)
+            } else if diag_item == sym::cmp_partialeq_ne {
+                Some(hir::BinOpKind::Ne)
+            } else {
+                None
+            }
+        }
     }
 }
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
index 55e1c84c8a2..2601d96b8c8 100644
--- a/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/PassWrapper.cpp
@@ -841,7 +841,11 @@ LLVMRustOptimize(
         // cargo run tests in multhreading mode by default
         // so use atomics for coverage counters
         Options.Atomic = true;
+#if LLVM_VERSION_GE(18, 0)
+        MPM.addPass(InstrProfilingLoweringPass(Options, false));
+#else
         MPM.addPass(InstrProfiling(Options, false));
+#endif
       }
     );
   }
diff --git a/compiler/rustc_macros/src/hash_stable.rs b/compiler/rustc_macros/src/hash_stable.rs
index 2893937fc4a..a6396ba687d 100644
--- a/compiler/rustc_macros/src/hash_stable.rs
+++ b/compiler/rustc_macros/src/hash_stable.rs
@@ -1,6 +1,6 @@
-use proc_macro2::{self, Ident};
+use proc_macro2::Ident;
 use quote::quote;
-use syn::{self, parse_quote};
+use syn::parse_quote;
 
 struct Attributes {
     ignore: bool,
diff --git a/compiler/rustc_macros/src/lift.rs b/compiler/rustc_macros/src/lift.rs
index ad7ac740417..3dedd88fb19 100644
--- a/compiler/rustc_macros/src/lift.rs
+++ b/compiler/rustc_macros/src/lift.rs
@@ -1,5 +1,5 @@
 use quote::quote;
-use syn::{self, parse_quote};
+use syn::parse_quote;
 
 pub fn lift_derive(mut s: synstructure::Structure<'_>) -> proc_macro2::TokenStream {
     s.add_bounds(synstructure::AddBounds::Generics);
diff --git a/compiler/rustc_metadata/src/locator.rs b/compiler/rustc_metadata/src/locator.rs
index bcc124524eb..f9219d12afd 100644
--- a/compiler/rustc_metadata/src/locator.rs
+++ b/compiler/rustc_metadata/src/locator.rs
@@ -783,8 +783,8 @@ fn get_metadata_section<'p>(
                 loader.get_dylib_metadata(target, filename).map_err(MetadataError::LoadFailure)?;
             // The header is uncompressed
             let header_len = METADATA_HEADER.len();
-            // header + u32 length of data
-            let data_start = header_len + 4;
+            // header + u64 length of data
+            let data_start = header_len + 8;
 
             debug!("checking {} bytes of metadata-version stamp", header_len);
             let header = &buf[..cmp::min(header_len, buf.len())];
@@ -797,13 +797,13 @@ fn get_metadata_section<'p>(
 
             // Length of the compressed stream - this allows linkers to pad the section if they want
             let Ok(len_bytes) =
-                <[u8; 4]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
+                <[u8; 8]>::try_from(&buf[header_len..cmp::min(data_start, buf.len())])
             else {
                 return Err(MetadataError::LoadFailure(
                     "invalid metadata length found".to_string(),
                 ));
             };
-            let compressed_len = u32::from_be_bytes(len_bytes) as usize;
+            let compressed_len = u64::from_le_bytes(len_bytes) as usize;
 
             // Header is okay -> inflate the actual metadata
             let compressed_bytes = buf.slice(|buf| &buf[data_start..(data_start + compressed_len)]);
diff --git a/compiler/rustc_metadata/src/rmeta/decoder.rs b/compiler/rustc_metadata/src/rmeta/decoder.rs
index 5725a759fef..24ab4f94d5c 100644
--- a/compiler/rustc_metadata/src/rmeta/decoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/decoder.rs
@@ -1,44 +1,34 @@
 // Decoding metadata from a single crate's metadata
 
-use crate::creader::{CStore, CrateMetadataRef};
+use crate::creader::CStore;
 use crate::rmeta::table::IsDefault;
 use crate::rmeta::*;
 
 use rustc_ast as ast;
 use rustc_data_structures::captures::Captures;
-use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::owned_slice::OwnedSlice;
-use rustc_data_structures::svh::Svh;
 use rustc_data_structures::sync::{AppendOnlyVec, AtomicBool, Lock, Lrc, OnceLock};
 use rustc_data_structures::unhash::UnhashMap;
 use rustc_expand::base::{SyntaxExtension, SyntaxExtensionKind};
 use rustc_expand::proc_macro::{AttrProcMacro, BangProcMacro, DeriveProcMacro};
-use rustc_hir::def::{CtorKind, DefKind, DocLinkResMap, Res};
-use rustc_hir::def_id::{CrateNum, DefId, DefIndex, CRATE_DEF_INDEX, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPath, DefPathData, DefPathHash};
+use rustc_hir::def::Res;
+use rustc_hir::def_id::{CRATE_DEF_INDEX, LOCAL_CRATE};
+use rustc_hir::definitions::{DefPath, DefPathData};
 use rustc_hir::diagnostic_items::DiagnosticItems;
-use rustc_index::{Idx, IndexVec};
-use rustc_middle::metadata::ModChild;
-use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
-use rustc_middle::middle::exported_symbols::{ExportedSymbol, SymbolExportInfo};
+use rustc_index::Idx;
 use rustc_middle::middle::lib_features::LibFeatures;
 use rustc_middle::mir::interpret::{AllocDecodingSession, AllocDecodingState};
 use rustc_middle::ty::codec::TyDecoder;
-use rustc_middle::ty::fast_reject::SimplifiedType;
-use rustc_middle::ty::{self, ParameterizedOverTcx, Ty, TyCtxt, Visibility};
+use rustc_middle::ty::Visibility;
 use rustc_serialize::opaque::MemDecoder;
 use rustc_serialize::{Decodable, Decoder};
-use rustc_session::cstore::{
-    CrateSource, ExternCrate, ForeignModule, LinkagePreference, NativeLib,
-};
+use rustc_session::cstore::{CrateSource, ExternCrate};
 use rustc_session::Session;
-use rustc_span::hygiene::ExpnIndex;
-use rustc_span::symbol::{kw, Ident, Symbol};
-use rustc_span::{self, BytePos, ExpnId, Pos, Span, SpanData, SyntaxContext, DUMMY_SP};
+use rustc_span::symbol::kw;
+use rustc_span::{BytePos, Pos, SpanData, SyntaxContext, DUMMY_SP};
 
 use proc_macro::bridge::client::ProcMacro;
 use std::iter::TrustedLen;
-use std::num::NonZeroUsize;
 use std::path::Path;
 use std::sync::atomic::Ordering;
 use std::{io, iter, mem};
@@ -700,28 +690,25 @@ impl MetadataBlob {
     }
 
     pub(crate) fn get_rustc_version(&self) -> String {
-        LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 4).unwrap())
+        LazyValue::<String>::from_position(NonZeroUsize::new(METADATA_HEADER.len() + 8).unwrap())
             .decode(self)
     }
 
-    pub(crate) fn get_header(&self) -> CrateHeader {
-        let slice = &self.blob()[..];
+    fn root_pos(&self) -> NonZeroUsize {
         let offset = METADATA_HEADER.len();
+        let pos_bytes = self.blob()[offset..][..8].try_into().unwrap();
+        let pos = u64::from_le_bytes(pos_bytes);
+        NonZeroUsize::new(pos as usize).unwrap()
+    }
 
-        let pos_bytes = slice[offset..][..4].try_into().unwrap();
-        let pos = u32::from_be_bytes(pos_bytes) as usize;
-
-        LazyValue::<CrateHeader>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
+    pub(crate) fn get_header(&self) -> CrateHeader {
+        let pos = self.root_pos();
+        LazyValue::<CrateHeader>::from_position(pos).decode(self)
     }
 
     pub(crate) fn get_root(&self) -> CrateRoot {
-        let slice = &self.blob()[..];
-        let offset = METADATA_HEADER.len();
-
-        let pos_bytes = slice[offset..][..4].try_into().unwrap();
-        let pos = u32::from_be_bytes(pos_bytes) as usize;
-
-        LazyValue::<CrateRoot>::from_position(NonZeroUsize::new(pos).unwrap()).decode(self)
+        let pos = self.root_pos();
+        LazyValue::<CrateRoot>::from_position(pos).decode(self)
     }
 
     pub(crate) fn list_crate_metadata(
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index ffb2375a734..143e439bd57 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -1,51 +1,37 @@
 use crate::errors::{FailCreateFileEncoder, FailWriteFile};
-use crate::rmeta::def_path_hash_map::DefPathHashMapRef;
-use crate::rmeta::table::TableBuilder;
 use crate::rmeta::*;
 
-use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::Attribute;
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
+use rustc_data_structures::fx::FxIndexSet;
 use rustc_data_structures::memmap::{Mmap, MmapMut};
 use rustc_data_structures::stable_hasher::{Hash128, HashStable, StableHasher};
 use rustc_data_structures::sync::{join, par_for_each_in, Lrc};
 use rustc_data_structures::temp_dir::MaybeTempDir;
 use rustc_hir as hir;
-use rustc_hir::def::DefKind;
-use rustc_hir::def_id::{
-    CrateNum, DefId, DefIndex, LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX,
-    LOCAL_CRATE,
-};
+use rustc_hir::def_id::{LocalDefId, LocalDefIdSet, CRATE_DEF_ID, CRATE_DEF_INDEX, LOCAL_CRATE};
 use rustc_hir::definitions::DefPathData;
-use rustc_hir::lang_items::LangItem;
 use rustc_hir_pretty::id_to_string;
-use rustc_middle::middle::debugger_visualizer::DebuggerVisualizerFile;
 use rustc_middle::middle::dependency_format::Linkage;
-use rustc_middle::middle::exported_symbols::{
-    metadata_symbol_name, ExportedSymbol, SymbolExportInfo,
-};
-use rustc_middle::middle::lib_features::FeatureStability;
+use rustc_middle::middle::exported_symbols::metadata_symbol_name;
 use rustc_middle::mir::interpret;
 use rustc_middle::query::LocalCrate;
 use rustc_middle::query::Providers;
 use rustc_middle::traits::specialization_graph;
 use rustc_middle::ty::codec::TyEncoder;
-use rustc_middle::ty::fast_reject::{self, SimplifiedType, TreatParams};
-use rustc_middle::ty::{self, AssocItemContainer, SymbolName, Ty, TyCtxt};
+use rustc_middle::ty::fast_reject::{self, TreatParams};
+use rustc_middle::ty::{AssocItemContainer, SymbolName};
 use rustc_middle::util::common::to_readable_str;
 use rustc_serialize::{opaque, Decodable, Decoder, Encodable, Encoder};
 use rustc_session::config::{CrateType, OptLevel};
-use rustc_session::cstore::{ForeignModule, LinkagePreference, NativeLib};
-use rustc_span::hygiene::{ExpnIndex, HygieneEncodeContext, MacroKind};
-use rustc_span::symbol::{sym, Symbol};
-use rustc_span::{self, ExternalSource, FileName, SourceFile, Span, SpanData, SyntaxContext};
+use rustc_span::hygiene::HygieneEncodeContext;
+use rustc_span::symbol::sym;
+use rustc_span::{ExternalSource, FileName, SourceFile, SpanData, SyntaxContext};
 use std::borrow::Borrow;
 use std::collections::hash_map::Entry;
 use std::fs::File;
 use std::hash::Hash;
 use std::io::{Read, Seek, Write};
-use std::num::NonZeroUsize;
 use std::path::{Path, PathBuf};
 
 pub(super) struct EncodeContext<'a, 'tcx> {
@@ -2204,7 +2190,7 @@ pub fn encode_metadata(tcx: TyCtxt<'_>, path: &Path) {
     encoder.emit_raw_bytes(METADATA_HEADER);
 
     // Will be filled with the root position after encoding everything.
-    encoder.emit_raw_bytes(&[0, 0, 0, 0]);
+    encoder.emit_raw_bytes(&0u64.to_le_bytes());
 
     let source_map_files = tcx.sess.source_map().files();
     let source_file_cache = (source_map_files[0].clone(), 0);
@@ -2260,7 +2246,7 @@ fn encode_root_position(mut file: &File, pos: usize) -> Result<(), std::io::Erro
     // Encode the root position.
     let header = METADATA_HEADER.len();
     file.seek(std::io::SeekFrom::Start(header as u64))?;
-    file.write_all(&[(pos >> 24) as u8, (pos >> 16) as u8, (pos >> 8) as u8, (pos >> 0) as u8])?;
+    file.write_all(&pos.to_le_bytes())?;
 
     // Return to the position where we are before writing the root position.
     file.seek(std::io::SeekFrom::Start(pos_before_seek))?;
diff --git a/compiler/rustc_metadata/src/rmeta/mod.rs b/compiler/rustc_metadata/src/rmeta/mod.rs
index ea8ef50460e..a8582284898 100644
--- a/compiler/rustc_metadata/src/rmeta/mod.rs
+++ b/compiler/rustc_metadata/src/rmeta/mod.rs
@@ -57,12 +57,12 @@ pub(crate) fn rustc_version(cfg_version: &'static str) -> String {
 /// Metadata encoding version.
 /// N.B., increment this if you change the format of metadata such that
 /// the rustc version can't be found to compare with `rustc_version()`.
-const METADATA_VERSION: u8 = 8;
+const METADATA_VERSION: u8 = 9;
 
 /// Metadata header which includes `METADATA_VERSION`.
 ///
 /// This header is followed by the length of the compressed data, then
-/// the position of the `CrateRoot`, which is encoded as a 32-bit big-endian
+/// the position of the `CrateRoot`, which is encoded as a 64-bit little-endian
 /// unsigned integer, and further followed by the rustc version string.
 pub const METADATA_HEADER: &[u8] = &[b'r', b'u', b's', b't', 0, 0, 0, METADATA_VERSION];
 
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index 7cdbcd9193c..3fc6d9db331 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -1,13 +1,8 @@
 use crate::rmeta::*;
 
 use rustc_data_structures::fingerprint::Fingerprint;
-use rustc_hir::def::{CtorKind, CtorOf};
+use rustc_hir::def::CtorOf;
 use rustc_index::Idx;
-use rustc_middle::ty::{ParameterizedOverTcx, UnusedGenericParams};
-use rustc_serialize::opaque::FileEncoder;
-use rustc_span::hygiene::MacroKind;
-use std::marker::PhantomData;
-use std::num::NonZeroUsize;
 
 pub(super) trait IsDefault: Default {
     fn is_default(&self) -> bool;
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index f407d30ac82..4af886a9718 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::sync::{par_for_each_in, try_par_for_each_in, DynSend,
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{DefId, LocalDefId, LocalModDefId, LOCAL_CRATE};
 use rustc_hir::definitions::{DefKey, DefPath, DefPathHash};
-use rustc_hir::intravisit::{self, Visitor};
+use rustc_hir::intravisit::Visitor;
 use rustc_hir::*;
 use rustc_index::Idx;
 use rustc_middle::hir::nested_filter;
@@ -336,7 +336,8 @@ impl<'hir> Map<'hir> {
     /// Returns the `BodyOwnerKind` of this `LocalDefId`.
     ///
     /// Panics if `LocalDefId` does not have an associated body.
-    pub fn body_owner_kind(self, def_id: LocalDefId) -> BodyOwnerKind {
+    pub fn body_owner_kind(self, def_id: impl Into<DefId>) -> BodyOwnerKind {
+        let def_id = def_id.into();
         match self.tcx.def_kind(def_id) {
             DefKind::Const | DefKind::AssocConst | DefKind::AnonConst => {
                 BodyOwnerKind::Const { inline: false }
@@ -356,20 +357,17 @@ impl<'hir> Map<'hir> {
     /// This should only be used for determining the context of a body, a return
     /// value of `Some` does not always suggest that the owner of the body is `const`,
     /// just that it has to be checked as if it were.
-    pub fn body_const_context(self, def_id: LocalDefId) -> Option<ConstContext> {
+    pub fn body_const_context(self, def_id: impl Into<DefId>) -> Option<ConstContext> {
+        let def_id = def_id.into();
         let ccx = match self.body_owner_kind(def_id) {
             BodyOwnerKind::Const { inline } => ConstContext::Const { inline },
             BodyOwnerKind::Static(mt) => ConstContext::Static(mt),
 
-            BodyOwnerKind::Fn if self.tcx.is_constructor(def_id.to_def_id()) => return None,
-            BodyOwnerKind::Fn | BodyOwnerKind::Closure
-                if self.tcx.is_const_fn_raw(def_id.to_def_id()) =>
-            {
-                ConstContext::ConstFn
-            }
-            BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id.to_def_id()) => {
+            BodyOwnerKind::Fn if self.tcx.is_constructor(def_id) => return None,
+            BodyOwnerKind::Fn | BodyOwnerKind::Closure if self.tcx.is_const_fn_raw(def_id) => {
                 ConstContext::ConstFn
             }
+            BodyOwnerKind::Fn if self.tcx.is_const_default_method(def_id) => ConstContext::ConstFn,
             BodyOwnerKind::Fn | BodyOwnerKind::Closure => return None,
         };
 
diff --git a/compiler/rustc_middle/src/middle/limits.rs b/compiler/rustc_middle/src/middle/limits.rs
index d4f023958d6..b29be92ae26 100644
--- a/compiler/rustc_middle/src/middle/limits.rs
+++ b/compiler/rustc_middle/src/middle/limits.rs
@@ -8,7 +8,6 @@
 //! this via an attribute on the crate like `#![recursion_limit="22"]`. This pass
 //! just peeks and looks for that attribute.
 
-use crate::bug;
 use crate::error::LimitInvalid;
 use crate::query::Providers;
 use rustc_ast::Attribute;
diff --git a/compiler/rustc_middle/src/mir/consts.rs b/compiler/rustc_middle/src/mir/consts.rs
index 26138157b74..2c38f998c95 100644
--- a/compiler/rustc_middle/src/mir/consts.rs
+++ b/compiler/rustc_middle/src/mir/consts.rs
@@ -1,6 +1,5 @@
 use std::fmt::{self, Debug, Display, Formatter};
 
-use rustc_hir;
 use rustc_hir::def_id::DefId;
 use rustc_session::RemapFileNameExt;
 use rustc_span::Span;
diff --git a/compiler/rustc_middle/src/mir/generic_graph.rs b/compiler/rustc_middle/src/mir/generic_graph.rs
index d1753427e74..51e26ab7984 100644
--- a/compiler/rustc_middle/src/mir/generic_graph.rs
+++ b/compiler/rustc_middle/src/mir/generic_graph.rs
@@ -1,7 +1,5 @@
 use gsgdt::{Edge, Graph, Node, NodeStyle};
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
 
 /// Convert an MIR function into a gsgdt Graph
 pub fn mir_fn_to_generic_graph<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'_>) -> Graph {
diff --git a/compiler/rustc_middle/src/mir/graphviz.rs b/compiler/rustc_middle/src/mir/graphviz.rs
index 5c7de864430..96bef40dac5 100644
--- a/compiler/rustc_middle/src/mir/graphviz.rs
+++ b/compiler/rustc_middle/src/mir/graphviz.rs
@@ -1,9 +1,6 @@
 use gsgdt::GraphvizSettings;
 use rustc_graphviz as dot;
-use rustc_hir::def_id::DefId;
 use rustc_middle::mir::*;
-use rustc_middle::ty::{self, TyCtxt};
-use std::fmt::Debug;
 use std::io::{self, Write};
 
 use super::generic_graph::mir_fn_to_generic_graph;
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index eb4aa9eb95c..b81e9fa1aab 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -1,7 +1,4 @@
-use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::*;
-use rustc_middle::ty::Ty;
-use rustc_span::Span;
 
 /// This struct represents a patch to MIR, which can add
 /// new statements and basic blocks and patch over block
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index bfaa0d88fc0..071c6a75583 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -1,23 +1,18 @@
 use std::collections::BTreeSet;
-use std::fmt::{self, Debug, Display, Write as _};
+use std::fmt::{Display, Write as _};
 use std::fs;
 use std::io::{self, Write as _};
 use std::path::{Path, PathBuf};
 
 use super::graphviz::write_mir_fn_graphviz;
 use super::spanview::write_mir_fn_spanview;
-use either::Either;
 use rustc_ast::InlineAsmTemplatePiece;
-use rustc_data_structures::fx::FxHashMap;
-use rustc_hir::def_id::DefId;
-use rustc_index::Idx;
 use rustc_middle::mir::interpret::{
-    alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, ConstAllocation, GlobalAlloc,
-    Pointer, Provenance,
+    alloc_range, read_target_uint, AllocBytes, AllocId, Allocation, GlobalAlloc, Pointer,
+    Provenance,
 };
 use rustc_middle::mir::visit::Visitor;
 use rustc_middle::mir::{self, *};
-use rustc_middle::ty::{self, TyCtxt};
 use rustc_target::abi::Size;
 
 const INDENT: &str = "    ";
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 46e5c74c73c..cb9fc0d37f2 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -1,9 +1,7 @@
-use rustc_hir::def_id::DefId;
 use rustc_middle::hir;
 use rustc_middle::mir::*;
-use rustc_middle::ty::TyCtxt;
 use rustc_session::config::MirSpanview;
-use rustc_span::{BytePos, Pos, Span};
+use rustc_span::{BytePos, Pos};
 
 use std::cmp;
 use std::io::{self, Write};
diff --git a/compiler/rustc_middle/src/mir/tcx.rs b/compiler/rustc_middle/src/mir/tcx.rs
index 0fc12586948..f9b2a6ee8aa 100644
--- a/compiler/rustc_middle/src/mir/tcx.rs
+++ b/compiler/rustc_middle/src/mir/tcx.rs
@@ -4,9 +4,7 @@
  */
 
 use crate::mir::*;
-use crate::ty::{self, Ty, TyCtxt};
 use rustc_hir as hir;
-use rustc_target::abi::{FieldIdx, VariantIdx};
 
 #[derive(Copy, Clone, Debug, TypeFoldable, TypeVisitable)]
 pub struct PlaceTy<'tcx> {
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index aa4cb36c5ce..98e3a1f604e 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -2,9 +2,8 @@
 use rustc_hir::LangItem;
 use smallvec::SmallVec;
 
-use super::{BasicBlock, InlineAsmOperand, Operand, SourceInfo, TerminatorKind, UnwindAction};
+use super::TerminatorKind;
 use rustc_macros::HashStable;
-use std::iter;
 use std::slice;
 
 use super::*;
diff --git a/compiler/rustc_middle/src/mir/type_foldable.rs b/compiler/rustc_middle/src/mir/type_foldable.rs
index d5c81b6cd79..ea6b44d62b0 100644
--- a/compiler/rustc_middle/src/mir/type_foldable.rs
+++ b/compiler/rustc_middle/src/mir/type_foldable.rs
@@ -3,7 +3,6 @@
 use rustc_ast::InlineAsmTemplatePiece;
 
 use super::*;
-use crate::ty;
 
 TrivialTypeTraversalImpls! {
     BlockTailInfo,
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index d47cfd5712f..9059936f495 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -63,9 +63,7 @@
 //! `is_cleanup` above.
 
 use crate::mir::*;
-use crate::ty::GenericArgsRef;
-use crate::ty::{self, CanonicalUserTypeAnnotation, Ty};
-use rustc_span::Span;
+use crate::ty::CanonicalUserTypeAnnotation;
 
 macro_rules! make_mir_visitor {
     ($visitor_trait_name:ident, $($mutability:ident)?) => {
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index fa68923b2c1..63f4bab7914 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -10,7 +10,7 @@ use rustc_data_structures::intern::Interned;
 use rustc_errors::{DiagnosticArgValue, IntoDiagnosticArg};
 use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
-use rustc_serialize::{self, Decodable, Encodable};
+use rustc_serialize::{Decodable, Encodable};
 use rustc_type_ir::WithCachedTypeInfo;
 use smallvec::SmallVec;
 
diff --git a/compiler/rustc_middle/src/ty/generics.rs b/compiler/rustc_middle/src/ty/generics.rs
index 8316f9c3058..c3699b114c4 100644
--- a/compiler/rustc_middle/src/ty/generics.rs
+++ b/compiler/rustc_middle/src/ty/generics.rs
@@ -326,6 +326,8 @@ impl<'tcx> Generics {
             own_params.start = 1;
         }
 
+        let verbose = tcx.sess.verbose();
+
         // Filter the default arguments.
         //
         // This currently uses structural equality instead
@@ -340,6 +342,8 @@ impl<'tcx> Generics {
                 param.default_value(tcx).is_some_and(|default| {
                     default.instantiate(tcx, args) == args[param.index as usize]
                 })
+                // filter out trailing effect params, if we're not in `-Zverbose`.
+                || (!verbose && matches!(param.kind, GenericParamDefKind::Const { is_host_effect: true, .. }))
             })
             .count();
 
diff --git a/compiler/rustc_middle/src/ty/layout.rs b/compiler/rustc_middle/src/ty/layout.rs
index e1d1f361091..5fcdd5d4d2e 100644
--- a/compiler/rustc_middle/src/ty/layout.rs
+++ b/compiler/rustc_middle/src/ty/layout.rs
@@ -2,7 +2,7 @@ use crate::error::UnsupportedFnAbi;
 use crate::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use crate::query::TyCtxtAt;
 use crate::ty::normalize_erasing_regions::NormalizationError;
-use crate::ty::{self, ConstKind, ReprOptions, Ty, TyCtxt, TypeVisitableExt};
+use crate::ty::{self, ConstKind, Ty, TyCtxt, TypeVisitableExt};
 use rustc_error_messages::DiagnosticMessage;
 use rustc_errors::{
     DiagnosticArgValue, DiagnosticBuilder, Handler, IntoDiagnostic, IntoDiagnosticArg,
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index bd9f0fd3ea9..39adfac55ce 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2,24 +2,22 @@ use crate::mir::interpret::{AllocRange, GlobalAlloc, Pointer, Provenance, Scalar
 use crate::query::IntoQueryParam;
 use crate::query::Providers;
 use crate::traits::util::supertraits_for_pretty_printing;
+use crate::ty::GenericArgKind;
 use crate::ty::{
-    self, ConstInt, ParamConst, ScalarInt, Term, TermKind, Ty, TyCtxt, TypeFoldable,
-    TypeSuperFoldable, TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
+    ConstInt, ParamConst, ScalarInt, Term, TermKind, TypeFoldable, TypeSuperFoldable,
+    TypeSuperVisitable, TypeVisitable, TypeVisitableExt,
 };
-use crate::ty::{GenericArg, GenericArgKind};
 use rustc_apfloat::ieee::{Double, Single};
 use rustc_apfloat::Float;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_data_structures::sso::SsoHashSet;
 use rustc_hir as hir;
 use rustc_hir::def::{self, CtorKind, DefKind, Namespace};
-use rustc_hir::def_id::{DefId, DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
-use rustc_hir::definitions::{DefKey, DefPathData, DefPathDataName, DisambiguatedDefPathData};
+use rustc_hir::def_id::{DefIdSet, ModDefId, CRATE_DEF_ID, LOCAL_CRATE};
+use rustc_hir::definitions::{DefKey, DefPathDataName};
 use rustc_hir::LangItem;
 use rustc_session::config::TrimmedDefPaths;
 use rustc_session::cstore::{ExternCrate, ExternCrateSource};
 use rustc_session::Limit;
-use rustc_span::sym;
 use rustc_span::symbol::{kw, Ident, Symbol};
 use rustc_span::FileNameDisplayPreference;
 use rustc_target::abi::Size;
@@ -2034,37 +2032,11 @@ impl<'tcx> Printer<'tcx> for FmtPrinter<'_, 'tcx> {
     ) -> Result<(), PrintError> {
         print_prefix(self)?;
 
-        let tcx = self.tcx;
-
-        let args = args.iter().copied();
-
-        let args: Vec<_> = if !tcx.sess.verbose() {
-            // skip host param as those are printed as `~const`
-            args.filter(|arg| match arg.unpack() {
-                // FIXME(effects) there should be a better way than just matching the name
-                GenericArgKind::Const(c)
-                    if tcx.features().effects
-                        && matches!(
-                            c.kind(),
-                            ty::ConstKind::Param(ty::ParamConst { name: sym::host, .. })
-                        ) =>
-                {
-                    false
-                }
-                _ => true,
-            })
-            .collect()
-        } else {
-            // If -Zverbose is passed, we should print the host parameter instead
-            // of eating it.
-            args.collect()
-        };
-
         if !args.is_empty() {
             if self.in_value {
                 write!(self, "::")?;
             }
-            self.generic_delimiters(|cx| cx.comma_sep(args.into_iter()))
+            self.generic_delimiters(|cx| cx.comma_sep(args.iter().copied()))
         } else {
             Ok(())
         }
@@ -2894,11 +2866,16 @@ define_print_and_forward_display! {
     }
 
     TraitPredPrintModifiersAndPath<'tcx> {
-        // FIXME(effects) print `~const` here
+        if let Some(idx) = cx.tcx().generics_of(self.0.trait_ref.def_id).host_effect_index
+        {
+            let arg = self.0.trait_ref.args.const_at(idx);
+            if arg != cx.tcx().consts.true_ && !arg.has_infer() {
+                p!("~const ");
+            }
+        }
         if let ty::ImplPolarity::Negative = self.0.polarity {
             p!("!")
         }
-
         p!(print(self.0.trait_ref.print_only_trait_path()));
     }
 
@@ -2933,7 +2910,6 @@ define_print_and_forward_display! {
                 p!("~const ");
             }
         }
-        // FIXME(effects) print `~const` here
         if let ty::ImplPolarity::Negative = self.polarity {
             p!("!");
         }
diff --git a/compiler/rustc_middle/src/ty/util.rs b/compiler/rustc_middle/src/ty/util.rs
index b7c3edee9e5..8b1d33848ea 100644
--- a/compiler/rustc_middle/src/ty/util.rs
+++ b/compiler/rustc_middle/src/ty/util.rs
@@ -782,7 +782,8 @@ impl<'tcx> TyCtxt<'tcx> {
             || self.extern_crate(key.as_def_id()).is_some_and(|e| e.is_direct())
     }
 
-    pub fn expected_const_effect_param_for_body(self, def_id: LocalDefId) -> ty::Const<'tcx> {
+    pub fn expected_host_effect_param_for_body(self, def_id: impl Into<DefId>) -> ty::Const<'tcx> {
+        let def_id = def_id.into();
         // FIXME(effects): This is suspicious and should probably not be done,
         // especially now that we enforce host effects and then properly handle
         // effect vars during fallback.
@@ -817,7 +818,7 @@ impl<'tcx> TyCtxt<'tcx> {
     }
 
     /// Constructs generic args for an item, optionally appending a const effect param type
-    pub fn with_opt_const_effect_param(
+    pub fn with_opt_host_effect_param(
         self,
         caller_def_id: LocalDefId,
         callee_def_id: DefId,
@@ -826,9 +827,10 @@ impl<'tcx> TyCtxt<'tcx> {
         let generics = self.generics_of(callee_def_id);
         assert_eq!(generics.parent, None);
 
-        let opt_const_param = generics.host_effect_index.is_some().then(|| {
-            ty::GenericArg::from(self.expected_const_effect_param_for_body(caller_def_id))
-        });
+        let opt_const_param = generics
+            .host_effect_index
+            .is_some()
+            .then(|| ty::GenericArg::from(self.expected_host_effect_param_for_body(caller_def_id)));
 
         self.mk_args_from_iter(args.into_iter().map(|arg| arg.into()).chain(opt_const_param))
     }
diff --git a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
index 2130dbdc033..a5f6bb12ee4 100644
--- a/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
+++ b/compiler/rustc_mir_build/src/build/expr/as_rvalue.rs
@@ -10,8 +10,6 @@ use crate::build::{BlockAnd, BlockAndExtension, Builder, NeedsTemporary};
 use rustc_hir::lang_items::LangItem;
 use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::Scalar;
-use rustc_middle::mir::AssertKind;
-use rustc_middle::mir::Place;
 use rustc_middle::mir::*;
 use rustc_middle::thir::*;
 use rustc_middle::ty::cast::{mir_cast_kind, CastTy};
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 642ac9b49c8..d1952704da3 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -500,7 +500,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.tcx,
             eq_def_id,
             sym::eq,
-            self.tcx.with_opt_const_effect_param(self.def_id, eq_def_id, [ty, ty]),
+            self.tcx.with_opt_host_effect_param(self.def_id, eq_def_id, [ty, ty]),
         );
 
         let bool_ty = self.tcx.types.bool;
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 1f7c6d7875b..62190848dd5 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -2,7 +2,7 @@ use std::borrow::Cow;
 
 use crate::build::ExprCategory;
 use crate::errors::*;
-use rustc_middle::thir::visit::{self, Visitor};
+use rustc_middle::thir::visit::Visitor;
 
 use rustc_errors::DiagnosticArgValue;
 use rustc_hir as hir;
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index e8a972005b0..09e0b30a5c7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -16,7 +16,7 @@ use rustc_hir as hir;
 use rustc_hir::def::*;
 use rustc_hir::def_id::LocalDefId;
 use rustc_hir::HirId;
-use rustc_middle::thir::visit::{self, Visitor};
+use rustc_middle::thir::visit::Visitor;
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index 4e2c932d6c6..391d65b338d 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -272,7 +272,7 @@ impl<'tcx> ConstToPat<'tcx> {
             ty::TraitRef::new(
                 tcx,
                 partial_eq_trait_id,
-                tcx.with_opt_const_effect_param(
+                tcx.with_opt_host_effect_param(
                     tcx.hir().enclosing_body_owner(self.id),
                     partial_eq_trait_id,
                     [ty, ty],
diff --git a/compiler/rustc_mir_dataflow/src/framework/tests.rs b/compiler/rustc_mir_dataflow/src/framework/tests.rs
index 1da5057ff40..6b338efd569 100644
--- a/compiler/rustc_mir_dataflow/src/framework/tests.rs
+++ b/compiler/rustc_mir_dataflow/src/framework/tests.rs
@@ -2,9 +2,7 @@
 
 use std::marker::PhantomData;
 
-use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
-use rustc_middle::mir::{self, BasicBlock, Location};
 use rustc_middle::ty;
 use rustc_span::DUMMY_SP;
 
diff --git a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
index 2b3d423ea61..dfc7a9891f9 100644
--- a/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
+++ b/compiler/rustc_mir_transform/src/abort_unwinding_calls.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_ast::InlineAsmOptions;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout;
diff --git a/compiler/rustc_mir_transform/src/add_call_guards.rs b/compiler/rustc_mir_transform/src/add_call_guards.rs
index b814fbf32b1..a47c8d94bba 100644
--- a/compiler/rustc_mir_transform/src/add_call_guards.rs
+++ b/compiler/rustc_mir_transform/src/add_call_guards.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
index ef2a0c790e9..de6d20ae3e8 100644
--- a/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
+++ b/compiler/rustc_mir_transform/src/add_moves_for_packed_drops.rs
@@ -2,7 +2,6 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
 use crate::util;
-use crate::MirPass;
 use rustc_middle::mir::patch::MirPatch;
 
 /// This pass moves values being dropped that are within a packed
diff --git a/compiler/rustc_mir_transform/src/add_retag.rs b/compiler/rustc_mir_transform/src/add_retag.rs
index 75473ca53fb..94077c63057 100644
--- a/compiler/rustc_mir_transform/src/add_retag.rs
+++ b/compiler/rustc_mir_transform/src/add_retag.rs
@@ -4,7 +4,6 @@
 //! of MIR building, and only after this pass we think of the program has having the
 //! normal MIR semantics.
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 
diff --git a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
index e5be7c0ca76..04204c68f7b 100644
--- a/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
+++ b/compiler/rustc_mir_transform/src/add_subtyping_projections.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::MutVisitor;
diff --git a/compiler/rustc_mir_transform/src/check_alignment.rs b/compiler/rustc_mir_transform/src/check_alignment.rs
index 42b2f18869c..9eec724ef21 100644
--- a/compiler/rustc_mir_transform/src/check_alignment.rs
+++ b/compiler/rustc_mir_transform/src/check_alignment.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_hir::lang_items::LangItem;
 use rustc_index::IndexVec;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/const_goto.rs b/compiler/rustc_mir_transform/src/const_goto.rs
index fd2d37dbea5..3884346076e 100644
--- a/compiler/rustc_mir_transform/src/const_goto.rs
+++ b/compiler/rustc_mir_transform/src/const_goto.rs
@@ -17,7 +17,6 @@
 //! }
 //! ```
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use rustc_middle::{mir::visit::Visitor, ty::ParamEnv};
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index d88b33cc973..e66d5e0a9f9 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -19,7 +19,6 @@ use rustc_target::abi::{self, HasDataLayout, Size, TargetDataLayout};
 use rustc_target::spec::abi::Abi as CallAbi;
 
 use crate::dataflow_const_prop::Patch;
-use crate::MirPass;
 use rustc_const_eval::interpret::{
     self, compile_time_machine, AllocId, ConstAllocation, FnArg, Frame, ImmTy, Immediate, InterpCx,
     InterpResult, MemoryKind, OpTy, PlaceTy, Pointer, Scalar, StackPopCleanup,
diff --git a/compiler/rustc_mir_transform/src/copy_prop.rs b/compiler/rustc_mir_transform/src/copy_prop.rs
index 74009496e75..0119b95cced 100644
--- a/compiler/rustc_mir_transform/src/copy_prop.rs
+++ b/compiler/rustc_mir_transform/src/copy_prop.rs
@@ -6,7 +6,6 @@ use rustc_middle::ty::TyCtxt;
 use rustc_mir_dataflow::impls::borrowed_locals;
 
 use crate::ssa::SsaLocals;
-use crate::MirPass;
 
 /// Unify locals that copy each other.
 ///
diff --git a/compiler/rustc_mir_transform/src/coroutine.rs b/compiler/rustc_mir_transform/src/coroutine.rs
index 737fb6bf612..ed8b4ef3ba4 100644
--- a/compiler/rustc_mir_transform/src/coroutine.rs
+++ b/compiler/rustc_mir_transform/src/coroutine.rs
@@ -55,7 +55,6 @@ use crate::deref_separator::deref_finder;
 use crate::errors;
 use crate::pass_manager as pm;
 use crate::simplify;
-use crate::MirPass;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_errors::pluralize;
 use rustc_hir as hir;
@@ -63,7 +62,6 @@ use rustc_hir::lang_items::LangItem;
 use rustc_hir::CoroutineKind;
 use rustc_index::bit_set::{BitMatrix, BitSet, GrowableBitSet};
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::dump_mir;
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
 use rustc_middle::ty::CoroutineArgs;
@@ -73,7 +71,7 @@ use rustc_mir_dataflow::impls::{
     MaybeBorrowedLocals, MaybeLiveLocals, MaybeRequiresStorage, MaybeStorageLive,
 };
 use rustc_mir_dataflow::storage::always_storage_live_locals;
-use rustc_mir_dataflow::{self, Analysis};
+use rustc_mir_dataflow::Analysis;
 use rustc_span::def_id::{DefId, LocalDefId};
 use rustc_span::symbol::sym;
 use rustc_span::Span;
diff --git a/compiler/rustc_mir_transform/src/coverage/query.rs b/compiler/rustc_mir_transform/src/coverage/query.rs
index 809407f897d..dfc7c3a713b 100644
--- a/compiler/rustc_mir_transform/src/coverage/query.rs
+++ b/compiler/rustc_mir_transform/src/coverage/query.rs
@@ -2,9 +2,9 @@ use super::*;
 
 use rustc_data_structures::captures::Captures;
 use rustc_middle::mir::coverage::*;
-use rustc_middle::mir::{Body, Coverage, CoverageIdsInfo};
+use rustc_middle::mir::{Body, CoverageIdsInfo};
 use rustc_middle::query::Providers;
-use rustc_middle::ty::{self, TyCtxt};
+use rustc_middle::ty::{self};
 
 /// A `query` provider for retrieving coverage information injected into MIR.
 pub(crate) fn provide(providers: &mut Providers) {
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index 302cbf05d78..931bc8e58ff 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -33,7 +33,7 @@ use rustc_data_structures::graph::WithSuccessors;
 use rustc_index::{Idx, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty;
-use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
+use rustc_span::{BytePos, Pos, Span, DUMMY_SP};
 
 fn bcb(index: u32) -> BasicCoverageBlock {
     BasicCoverageBlock::from_u32(index)
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index e9949ebbc87..146cc33e8c6 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -20,7 +20,6 @@ use rustc_span::DUMMY_SP;
 use rustc_target::abi::{Abi, FieldIdx, Size, VariantIdx, FIRST_VARIANT};
 
 use crate::const_prop::throw_machine_stop_str;
-use crate::MirPass;
 
 // These constants are somewhat random guesses and have not been optimized.
 // If `tcx.sess.mir_opt_level() >= 4`, we ignore the limits (this can become very expensive).
diff --git a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
index 666293cbc30..b40b2ec8bfd 100644
--- a/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
+++ b/compiler/rustc_mir_transform/src/deduplicate_blocks.rs
@@ -3,8 +3,6 @@
 
 use std::{collections::hash_map::Entry, hash::Hash, hash::Hasher, iter};
 
-use crate::MirPass;
-
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::visit::MutVisitor;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/deref_separator.rs b/compiler/rustc_mir_transform/src/deref_separator.rs
index 42be7457018..0e2fccc85da 100644
--- a/compiler/rustc_mir_transform/src/deref_separator.rs
+++ b/compiler/rustc_mir_transform/src/deref_separator.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::visit::NonUseContext::VarDebugInfo;
diff --git a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
index 1c917a85c03..96943435bab 100644
--- a/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_box_derefs.rs
@@ -2,7 +2,6 @@
 //!
 //! Box is not actually a pointer so it is incorrect to dereference it directly.
 
-use crate::MirPass;
 use rustc_hir::def_id::DefId;
 use rustc_index::Idx;
 use rustc_middle::mir::patch::MirPatch;
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index f7188ea83fc..c45badbc559 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -1,5 +1,4 @@
 use crate::deref_separator::deref_finder;
-use crate::MirPass;
 use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_middle::mir::patch::MirPatch;
diff --git a/compiler/rustc_mir_transform/src/gvn.rs b/compiler/rustc_mir_transform/src/gvn.rs
index 1a5979ef714..b21988e179d 100644
--- a/compiler/rustc_mir_transform/src/gvn.rs
+++ b/compiler/rustc_mir_transform/src/gvn.rs
@@ -103,7 +103,6 @@ use std::borrow::Cow;
 
 use crate::dataflow_const_prop::DummyMachine;
 use crate::ssa::{AssignedValue, SsaLocals};
-use crate::MirPass;
 use either::Either;
 
 pub struct GVN;
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index 8fa26713184..8ad804bf3e7 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -17,7 +17,6 @@ use rustc_target::spec::abi::Abi;
 use crate::cost_checker::CostChecker;
 use crate::simplify::{remove_dead_blocks, CfgSimplifier};
 use crate::util;
-use crate::MirPass;
 use std::iter;
 use std::ops::{Range, RangeFrom};
 
diff --git a/compiler/rustc_mir_transform/src/instsimplify.rs b/compiler/rustc_mir_transform/src/instsimplify.rs
index 7a844b01707..4f0f63d22a4 100644
--- a/compiler/rustc_mir_transform/src/instsimplify.rs
+++ b/compiler/rustc_mir_transform/src/instsimplify.rs
@@ -1,8 +1,6 @@
 //! Performs various peephole optimizations.
 
 use crate::simplify::simplify_duplicate_switch_targets;
-use crate::MirPass;
-use rustc_hir::Mutability;
 use rustc_middle::mir::*;
 use rustc_middle::ty::layout::ValidityRequirement;
 use rustc_middle::ty::{self, GenericArgsRef, ParamEnv, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/jump_threading.rs b/compiler/rustc_mir_transform/src/jump_threading.rs
index 5754dd08164..36a15f47276 100644
--- a/compiler/rustc_mir_transform/src/jump_threading.rs
+++ b/compiler/rustc_mir_transform/src/jump_threading.rs
@@ -45,7 +45,6 @@ use rustc_middle::ty::{self, ScalarInt, Ty, TyCtxt};
 use rustc_mir_dataflow::value_analysis::{Map, PlaceIndex, State, TrackElem};
 
 use crate::cost_checker::CostChecker;
-use crate::MirPass;
 
 pub struct JumpThreading;
 
diff --git a/compiler/rustc_mir_transform/src/large_enums.rs b/compiler/rustc_mir_transform/src/large_enums.rs
index 0a8b13d6677..1d788a55ff8 100644
--- a/compiler/rustc_mir_transform/src/large_enums.rs
+++ b/compiler/rustc_mir_transform/src/large_enums.rs
@@ -1,5 +1,4 @@
 use crate::rustc_middle::ty::util::IntTypeExt;
-use crate::MirPass;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/lower_intrinsics.rs b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
index 249e0fc633e..18f588dccf6 100644
--- a/compiler/rustc_mir_transform/src/lower_intrinsics.rs
+++ b/compiler/rustc_mir_transform/src/lower_intrinsics.rs
@@ -1,6 +1,5 @@
 //! Lowers intrinsic calls
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use rustc_span::symbol::sym;
diff --git a/compiler/rustc_mir_transform/src/lower_slice_len.rs b/compiler/rustc_mir_transform/src/lower_slice_len.rs
index ae487841179..daeb56666f4 100644
--- a/compiler/rustc_mir_transform/src/lower_slice_len.rs
+++ b/compiler/rustc_mir_transform/src/lower_slice_len.rs
@@ -1,7 +1,6 @@
 //! This pass lowers calls to core::slice::len to just Len op.
 //! It should run before inlining!
 
-use crate::MirPass;
 use rustc_hir::def_id::DefId;
 use rustc_index::IndexSlice;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/match_branches.rs b/compiler/rustc_mir_transform/src/match_branches.rs
index 3dc627b6146..1c4aa37d57f 100644
--- a/compiler/rustc_mir_transform/src/match_branches.rs
+++ b/compiler/rustc_mir_transform/src/match_branches.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use std::iter;
diff --git a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
index c9b42e75cb2..64749a4b5b6 100644
--- a/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
+++ b/compiler/rustc_mir_transform/src/multiple_return_terminators.rs
@@ -1,7 +1,7 @@
 //! This pass removes jumps to basic blocks containing only a return, and replaces them with a
 //! return instead.
 
-use crate::{simplify, MirPass};
+use crate::simplify;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
diff --git a/compiler/rustc_mir_transform/src/normalize_array_len.rs b/compiler/rustc_mir_transform/src/normalize_array_len.rs
index 206cdf9fe28..128634bd7f2 100644
--- a/compiler/rustc_mir_transform/src/normalize_array_len.rs
+++ b/compiler/rustc_mir_transform/src/normalize_array_len.rs
@@ -2,7 +2,6 @@
 //! is taken using `.len()` method. Handy to preserve information in MIR for const prop
 
 use crate::ssa::SsaLocals;
-use crate::MirPass;
 use rustc_index::IndexVec;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/prettify.rs b/compiler/rustc_mir_transform/src/prettify.rs
index 745fa30841c..7b77d032353 100644
--- a/compiler/rustc_mir_transform/src/prettify.rs
+++ b/compiler/rustc_mir_transform/src/prettify.rs
@@ -4,7 +4,6 @@
 //! (`-Zmir-enable-passes=+ReorderBasicBlocks,+ReorderLocals`)
 //! to make the MIR easier to read for humans.
 
-use crate::MirPass;
 use rustc_index::{bit_set::BitSet, IndexSlice, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, PlaceContext, Visitor};
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index df39c819ba9..f13ab5b0f1f 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -9,7 +9,6 @@ use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::Analysis;
 
 use crate::ssa::{SsaLocals, StorageLiveLocals};
-use crate::MirPass;
 
 /// Propagate references using SSA analysis.
 ///
diff --git a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
index 54892442c87..095119e2e3f 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_index::bit_set::BitSet;
 use rustc_middle::mir::patch::MirPatch;
 use rustc_middle::mir::*;
diff --git a/compiler/rustc_mir_transform/src/remove_place_mention.rs b/compiler/rustc_mir_transform/src/remove_place_mention.rs
index 8be1c37572d..78335b3b5e0 100644
--- a/compiler/rustc_mir_transform/src/remove_place_mention.rs
+++ b/compiler/rustc_mir_transform/src/remove_place_mention.rs
@@ -1,6 +1,5 @@
 //! This pass removes `PlaceMention` statement, which has no effect at codegen.
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_transform/src/remove_storage_markers.rs b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
index dbe082e9093..795f5232ee3 100644
--- a/compiler/rustc_mir_transform/src/remove_storage_markers.rs
+++ b/compiler/rustc_mir_transform/src/remove_storage_markers.rs
@@ -1,6 +1,5 @@
 //! This pass removes storage markers if they won't be emitted during codegen.
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
index 548879e2e39..7d12bcf2fa1 100644
--- a/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_uninit_drops.rs
@@ -4,9 +4,7 @@ use rustc_middle::ty::GenericArgsRef;
 use rustc_middle::ty::{self, ParamEnv, Ty, TyCtxt, VariantDef};
 use rustc_mir_dataflow::impls::MaybeInitializedPlaces;
 use rustc_mir_dataflow::move_paths::{LookupResult, MoveData, MovePathIndex};
-use rustc_mir_dataflow::{
-    self, move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv,
-};
+use rustc_mir_dataflow::{move_path_children_matching, Analysis, MaybeReachable, MoveDataParamEnv};
 use rustc_target::abi::FieldIdx;
 
 use crate::MirPass;
diff --git a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
index 08b2a6537e9..5d528bed356 100644
--- a/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
+++ b/compiler/rustc_mir_transform/src/remove_unneeded_drops.rs
@@ -4,7 +4,6 @@
 //! useful because (unlike MIR building) it runs after type checking, so it can make use of
 //! `Reveal::All` to provide more precise type information.
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_transform/src/remove_zsts.rs b/compiler/rustc_mir_transform/src/remove_zsts.rs
index 9f59f9d1245..34d57a45301 100644
--- a/compiler/rustc_mir_transform/src/remove_zsts.rs
+++ b/compiler/rustc_mir_transform/src/remove_zsts.rs
@@ -1,6 +1,5 @@
 //! Removes operations on ZST places, and convert ZST operands to constants.
 
-use crate::MirPass;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/reveal_all.rs b/compiler/rustc_mir_transform/src/reveal_all.rs
index 1626cf3c035..4d2eca57840 100644
--- a/compiler/rustc_mir_transform/src/reveal_all.rs
+++ b/compiler/rustc_mir_transform/src/reveal_all.rs
@@ -1,6 +1,5 @@
 //! Normalizes MIR in RevealAll mode.
 
-use crate::MirPass;
 use rustc_middle::mir::visit::*;
 use rustc_middle::mir::*;
 use rustc_middle::ty::{self, Ty, TyCtxt};
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 907cfe7581a..6e22690d8da 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -37,7 +37,6 @@
 //! simplicity rather than completeness (it notably
 //! sometimes duplicates abusively).
 
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 use smallvec::SmallVec;
diff --git a/compiler/rustc_mir_transform/src/simplify.rs b/compiler/rustc_mir_transform/src/simplify.rs
index 97d398fe5c9..856a0f22771 100644
--- a/compiler/rustc_mir_transform/src/simplify.rs
+++ b/compiler/rustc_mir_transform/src/simplify.rs
@@ -27,7 +27,6 @@
 //! naively generate still contains the `_a = ()` write in the unreachable block "after" the
 //! return.
 
-use crate::MirPass;
 use rustc_data_structures::fx::FxIndexSet;
 use rustc_index::{Idx, IndexSlice, IndexVec};
 use rustc_middle::mir::visit::{MutVisitor, MutatingUseContext, PlaceContext, Visitor};
diff --git a/compiler/rustc_mir_transform/src/simplify_branches.rs b/compiler/rustc_mir_transform/src/simplify_branches.rs
index 1f0e605c3b8..35a052166bd 100644
--- a/compiler/rustc_mir_transform/src/simplify_branches.rs
+++ b/compiler/rustc_mir_transform/src/simplify_branches.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_middle::mir::*;
 use rustc_middle::ty::TyCtxt;
 
diff --git a/compiler/rustc_mir_transform/src/sroa.rs b/compiler/rustc_mir_transform/src/sroa.rs
index a4ca2b91e82..06d5e17fdd6 100644
--- a/compiler/rustc_mir_transform/src/sroa.rs
+++ b/compiler/rustc_mir_transform/src/sroa.rs
@@ -1,4 +1,3 @@
-use crate::MirPass;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
 use rustc_index::bit_set::{BitSet, GrowableBitSet};
 use rustc_index::IndexVec;
diff --git a/compiler/rustc_mir_transform/src/unreachable_prop.rs b/compiler/rustc_mir_transform/src/unreachable_prop.rs
index 919e8d6a234..f12a6aa2429 100644
--- a/compiler/rustc_mir_transform/src/unreachable_prop.rs
+++ b/compiler/rustc_mir_transform/src/unreachable_prop.rs
@@ -2,7 +2,6 @@
 //! when all of their successors are unreachable. This is achieved through a
 //! post-order traversal of the blocks.
 
-use crate::MirPass;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_middle::mir::interpret::Scalar;
 use rustc_middle::mir::patch::MirPatch;
diff --git a/compiler/rustc_parse/src/lexer/mod.rs b/compiler/rustc_parse/src/lexer/mod.rs
index 92df2da8710..b1dc1f98777 100644
--- a/compiler/rustc_parse/src/lexer/mod.rs
+++ b/compiler/rustc_parse/src/lexer/mod.rs
@@ -67,7 +67,7 @@ pub(crate) fn parse_token_trees<'a>(
     let (stream, res, unmatched_delims) =
         tokentrees::TokenTreesReader::parse_all_token_trees(string_reader);
     match res {
-        Ok(()) if unmatched_delims.is_empty() => Ok(stream),
+        Ok(_open_spacing) if unmatched_delims.is_empty() => Ok(stream),
         _ => {
             // Return error if there are unmatched delimiters or unclosed delimiters.
             // We emit delimiter mismatch errors first, then emit the unclosing delimiter mismatch
diff --git a/compiler/rustc_parse/src/lexer/tokentrees.rs b/compiler/rustc_parse/src/lexer/tokentrees.rs
index e646f5dfd85..8cbadc26635 100644
--- a/compiler/rustc_parse/src/lexer/tokentrees.rs
+++ b/compiler/rustc_parse/src/lexer/tokentrees.rs
@@ -3,7 +3,7 @@ use super::diagnostics::same_indentation_level;
 use super::diagnostics::TokenTreeDiagInfo;
 use super::{StringReader, UnmatchedDelim};
 use rustc_ast::token::{self, Delimiter, Token};
-use rustc_ast::tokenstream::{DelimSpan, Spacing, TokenStream, TokenTree};
+use rustc_ast::tokenstream::{DelimSpacing, DelimSpan, Spacing, TokenStream, TokenTree};
 use rustc_ast_pretty::pprust::token_to_string;
 use rustc_errors::{Applicability, PErr};
 use rustc_span::symbol::kw;
@@ -25,54 +25,46 @@ impl<'a> TokenTreesReader<'a> {
             token: Token::dummy(),
             diag_info: TokenTreeDiagInfo::default(),
         };
-        let (stream, res) = tt_reader.parse_token_trees(/* is_delimited */ false);
+        let (_open_spacing, stream, res) =
+            tt_reader.parse_token_trees(/* is_delimited */ false);
         (stream, res, tt_reader.diag_info.unmatched_delims)
     }
 
-    // Parse a stream of tokens into a list of `TokenTree`s.
+    // Parse a stream of tokens into a list of `TokenTree`s. The `Spacing` in
+    // the result is that of the opening delimiter.
     fn parse_token_trees(
         &mut self,
         is_delimited: bool,
-    ) -> (TokenStream, Result<(), Vec<PErr<'a>>>) {
-        self.token = self.string_reader.next_token().0;
+    ) -> (Spacing, TokenStream, Result<(), Vec<PErr<'a>>>) {
+        // Move past the opening delimiter.
+        let (_, open_spacing) = self.bump(false);
+
         let mut buf = Vec::new();
         loop {
             match self.token.kind {
                 token::OpenDelim(delim) => {
                     buf.push(match self.parse_token_tree_open_delim(delim) {
                         Ok(val) => val,
-                        Err(errs) => return (TokenStream::new(buf), Err(errs)),
+                        Err(errs) => return (open_spacing, TokenStream::new(buf), Err(errs)),
                     })
                 }
                 token::CloseDelim(delim) => {
                     return (
+                        open_spacing,
                         TokenStream::new(buf),
                         if is_delimited { Ok(()) } else { Err(vec![self.close_delim_err(delim)]) },
                     );
                 }
                 token::Eof => {
                     return (
+                        open_spacing,
                         TokenStream::new(buf),
                         if is_delimited { Err(vec![self.eof_err()]) } else { Ok(()) },
                     );
                 }
                 _ => {
-                    // Get the next normal token. This might require getting multiple adjacent
-                    // single-char tokens and joining them together.
-                    let (this_spacing, next_tok) = loop {
-                        let (next_tok, is_next_tok_preceded_by_whitespace) =
-                            self.string_reader.next_token();
-                        if is_next_tok_preceded_by_whitespace {
-                            break (Spacing::Alone, next_tok);
-                        } else if let Some(glued) = self.token.glue(&next_tok) {
-                            self.token = glued;
-                        } else {
-                            let this_spacing =
-                                if next_tok.is_punct() { Spacing::Joint } else { Spacing::Alone };
-                            break (this_spacing, next_tok);
-                        }
-                    };
-                    let this_tok = std::mem::replace(&mut self.token, next_tok);
+                    // Get the next normal token.
+                    let (this_tok, this_spacing) = self.bump(true);
                     buf.push(TokenTree::Token(this_tok, this_spacing));
                 }
             }
@@ -116,7 +108,7 @@ impl<'a> TokenTreesReader<'a> {
         // Parse the token trees within the delimiters.
         // We stop at any delimiter so we can try to recover if the user
         // uses an incorrect delimiter.
-        let (tts, res) = self.parse_token_trees(/* is_delimited */ true);
+        let (open_spacing, tts, res) = self.parse_token_trees(/* is_delimited */ true);
         if let Err(errs) = res {
             return Err(self.unclosed_delim_err(tts, errs));
         }
@@ -125,7 +117,7 @@ impl<'a> TokenTreesReader<'a> {
         let delim_span = DelimSpan::from_pair(pre_span, self.token.span);
         let sm = self.string_reader.sess.source_map();
 
-        match self.token.kind {
+        let close_spacing = match self.token.kind {
             // Correct delimiter.
             token::CloseDelim(close_delim) if close_delim == open_delim => {
                 let (open_brace, open_brace_span) = self.diag_info.open_braces.pop().unwrap();
@@ -147,7 +139,7 @@ impl<'a> TokenTreesReader<'a> {
                 }
 
                 // Move past the closing delimiter.
-                self.token = self.string_reader.next_token().0;
+                self.bump(false).1
             }
             // Incorrect delimiter.
             token::CloseDelim(close_delim) => {
@@ -191,18 +183,50 @@ impl<'a> TokenTreesReader<'a> {
                 //     bar(baz(
                 // }  // Incorrect delimiter but matches the earlier `{`
                 if !self.diag_info.open_braces.iter().any(|&(b, _)| b == close_delim) {
-                    self.token = self.string_reader.next_token().0;
+                    self.bump(false).1
+                } else {
+                    // The choice of value here doesn't matter.
+                    Spacing::Alone
                 }
             }
             token::Eof => {
                 // Silently recover, the EOF token will be seen again
                 // and an error emitted then. Thus we don't pop from
-                // self.open_braces here.
+                // self.open_braces here. The choice of spacing value here
+                // doesn't matter.
+                Spacing::Alone
             }
             _ => unreachable!(),
-        }
+        };
+
+        let spacing = DelimSpacing::new(open_spacing, close_spacing);
 
-        Ok(TokenTree::Delimited(delim_span, open_delim, tts))
+        Ok(TokenTree::Delimited(delim_span, spacing, open_delim, tts))
+    }
+
+    // Move on to the next token, returning the current token and its spacing.
+    // Will glue adjacent single-char tokens together if `glue` is set.
+    fn bump(&mut self, glue: bool) -> (Token, Spacing) {
+        let (this_spacing, next_tok) = loop {
+            let (next_tok, is_next_tok_preceded_by_whitespace) = self.string_reader.next_token();
+
+            if is_next_tok_preceded_by_whitespace {
+                break (Spacing::Alone, next_tok);
+            } else if glue && let Some(glued) = self.token.glue(&next_tok) {
+                self.token = glued;
+            } else {
+                let this_spacing = if next_tok.is_punct() {
+                    Spacing::Joint
+                } else if next_tok.kind == token::Eof {
+                    Spacing::Alone
+                } else {
+                    Spacing::JointHidden
+                };
+                break (this_spacing, next_tok);
+            }
+        };
+        let this_tok = std::mem::replace(&mut self.token, next_tok);
+        (this_tok, this_spacing)
     }
 
     fn unclosed_delim_err(&mut self, tts: TokenStream, mut errs: Vec<PErr<'a>>) -> Vec<PErr<'a>> {
diff --git a/compiler/rustc_parse/src/parser/attr.rs b/compiler/rustc_parse/src/parser/attr.rs
index 422bb79308d..c9ce896b868 100644
--- a/compiler/rustc_parse/src/parser/attr.rs
+++ b/compiler/rustc_parse/src/parser/attr.rs
@@ -7,7 +7,6 @@ use rustc_ast::attr;
 use rustc_ast::token::{self, Delimiter, Nonterminal};
 use rustc_errors::{error_code, Diagnostic, IntoDiagnostic, PResult};
 use rustc_span::{sym, BytePos, Span};
-use std::convert::TryInto;
 use thin_vec::ThinVec;
 use tracing::debug;
 
diff --git a/compiler/rustc_parse/src/parser/attr_wrapper.rs b/compiler/rustc_parse/src/parser/attr_wrapper.rs
index c66a7176aab..5e8447030f1 100644
--- a/compiler/rustc_parse/src/parser/attr_wrapper.rs
+++ b/compiler/rustc_parse/src/parser/attr_wrapper.rs
@@ -1,7 +1,7 @@
 use super::{Capturing, FlatToken, ForceCollect, Parser, ReplaceRange, TokenCursor, TrailingToken};
 use rustc_ast::token::{self, Delimiter, Token, TokenKind};
-use rustc_ast::tokenstream::{AttrTokenStream, AttributesData, ToAttrTokenStream};
-use rustc_ast::tokenstream::{AttrTokenTree, DelimSpan, LazyAttrTokenStream, Spacing};
+use rustc_ast::tokenstream::{AttrTokenStream, AttrTokenTree, AttributesData, DelimSpacing};
+use rustc_ast::tokenstream::{DelimSpan, LazyAttrTokenStream, Spacing, ToAttrTokenStream};
 use rustc_ast::{self as ast};
 use rustc_ast::{AttrVec, Attribute, HasAttrs, HasTokens};
 use rustc_errors::PResult;
@@ -389,7 +389,7 @@ fn make_token_stream(
     #[derive(Debug)]
     struct FrameData {
         // This is `None` for the first frame, `Some` for all others.
-        open_delim_sp: Option<(Delimiter, Span)>,
+        open_delim_sp: Option<(Delimiter, Span, Spacing)>,
         inner: Vec<AttrTokenTree>,
     }
     let mut stack = vec![FrameData { open_delim_sp: None, inner: vec![] }];
@@ -397,21 +397,23 @@ fn make_token_stream(
     while let Some((token, spacing)) = token_and_spacing {
         match token {
             FlatToken::Token(Token { kind: TokenKind::OpenDelim(delim), span }) => {
-                stack.push(FrameData { open_delim_sp: Some((delim, span)), inner: vec![] });
+                stack
+                    .push(FrameData { open_delim_sp: Some((delim, span, spacing)), inner: vec![] });
             }
             FlatToken::Token(Token { kind: TokenKind::CloseDelim(delim), span }) => {
                 let frame_data = stack
                     .pop()
                     .unwrap_or_else(|| panic!("Token stack was empty for token: {token:?}"));
 
-                let (open_delim, open_sp) = frame_data.open_delim_sp.unwrap();
+                let (open_delim, open_sp, open_spacing) = frame_data.open_delim_sp.unwrap();
                 assert_eq!(
                     open_delim, delim,
                     "Mismatched open/close delims: open={open_delim:?} close={span:?}"
                 );
                 let dspan = DelimSpan::from_pair(open_sp, span);
+                let dspacing = DelimSpacing::new(open_spacing, spacing);
                 let stream = AttrTokenStream::new(frame_data.inner);
-                let delimited = AttrTokenTree::Delimited(dspan, delim, stream);
+                let delimited = AttrTokenTree::Delimited(dspan, dspacing, delim, stream);
                 stack
                     .last_mut()
                     .unwrap_or_else(|| panic!("Bottom token frame is missing for token: {token:?}"))
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index 406a6def019..5b0011e9f70 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -2276,7 +2276,7 @@ impl<'a> Parser<'a> {
         }
 
         if self.token.kind == TokenKind::Semi
-            && matches!(self.token_cursor.stack.last(), Some((_, Delimiter::Parenthesis, _)))
+            && matches!(self.token_cursor.stack.last(), Some((.., Delimiter::Parenthesis)))
             && self.may_recover()
         {
             // It is likely that the closure body is a block but where the
@@ -2918,7 +2918,15 @@ impl<'a> Parser<'a> {
             let mut result = if !is_fat_arrow && !is_almost_fat_arrow {
                 // A pattern without a body, allowed for never patterns.
                 arm_body = None;
-                this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)])
+                this.expect_one_of(&[token::Comma], &[token::CloseDelim(Delimiter::Brace)]).map(
+                    |x| {
+                        // Don't gate twice
+                        if !pat.contains_never_pattern() {
+                            this.sess.gated_spans.gate(sym::never_patterns, pat.span);
+                        }
+                        x
+                    },
+                )
             } else {
                 if let Err(mut err) = this.expect(&token::FatArrow) {
                     // We might have a `=>` -> `=` or `->` typo (issue #89396).
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index d22cc04d182..89919247e82 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -3,18 +3,12 @@ use super::ty::{AllowPlus, RecoverQPath, RecoverReturnSign};
 use super::{AttrWrapper, FollowedByType, ForceCollect, Parser, PathStyle, TrailingToken};
 use crate::errors::{self, MacroExpandsToAdtField};
 use crate::fluent_generated as fluent;
-use ast::StaticItem;
 use rustc_ast::ast::*;
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, TokenKind};
 use rustc_ast::tokenstream::{DelimSpan, TokenStream, TokenTree};
 use rustc_ast::util::case::Case;
-use rustc_ast::MacCall;
-use rustc_ast::{self as ast, AttrVec, Attribute, DUMMY_NODE_ID};
-use rustc_ast::{BindingAnnotation, Block, FnDecl, FnSig, Param, SelfKind};
-use rustc_ast::{Const, Defaultness, IsAuto, Mutability, Unsafe, UseTree, UseTreeKind};
-use rustc_ast::{EnumDef, FieldDef, Generics, TraitRef, Ty, TyKind, Variant, VariantData};
-use rustc_ast::{FnHeader, ForeignItem, Path, PathSegment, Visibility, VisibilityKind};
+use rustc_ast::{self as ast};
 use rustc_ast_pretty::pprust;
 use rustc_errors::{
     struct_span_err, Applicability, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic, PResult,
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index 7a306823ed4..2baedb2766f 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -20,7 +20,7 @@ pub use path::PathStyle;
 
 use rustc_ast::ptr::P;
 use rustc_ast::token::{self, Delimiter, Nonterminal, Token, TokenKind};
-use rustc_ast::tokenstream::{AttributesData, DelimSpan, Spacing};
+use rustc_ast::tokenstream::{AttributesData, DelimSpacing, DelimSpan, Spacing};
 use rustc_ast::tokenstream::{TokenStream, TokenTree, TokenTreeCursor};
 use rustc_ast::util::case::Case;
 use rustc_ast::AttrId;
@@ -130,7 +130,7 @@ pub struct Parser<'a> {
     pub sess: &'a ParseSess,
     /// The current token.
     pub token: Token,
-    /// The spacing for the current token
+    /// The spacing for the current token.
     pub token_spacing: Spacing,
     /// The previous token.
     pub prev_token: Token,
@@ -240,7 +240,7 @@ struct TokenCursor {
     // Token streams surrounding the current one. The delimiters for stack[n]'s
     // tokens are in `stack[n-1]`. `stack[0]` (when present) has no delimiters
     // because it's the outermost token stream which never has delimiters.
-    stack: Vec<(TokenTreeCursor, Delimiter, DelimSpan)>,
+    stack: Vec<(TokenTreeCursor, DelimSpan, DelimSpacing, Delimiter)>,
 }
 
 impl TokenCursor {
@@ -264,24 +264,31 @@ impl TokenCursor {
                         ));
                         return (token.clone(), spacing);
                     }
-                    &TokenTree::Delimited(sp, delim, ref tts) => {
+                    &TokenTree::Delimited(sp, spacing, delim, ref tts) => {
                         let trees = tts.clone().into_trees();
-                        self.stack.push((mem::replace(&mut self.tree_cursor, trees), delim, sp));
+                        self.stack.push((
+                            mem::replace(&mut self.tree_cursor, trees),
+                            sp,
+                            spacing,
+                            delim,
+                        ));
                         if delim != Delimiter::Invisible {
-                            return (Token::new(token::OpenDelim(delim), sp.open), Spacing::Alone);
+                            return (Token::new(token::OpenDelim(delim), sp.open), spacing.open);
                         }
                         // No open delimiter to return; continue on to the next iteration.
                     }
                 };
-            } else if let Some((tree_cursor, delim, span)) = self.stack.pop() {
+            } else if let Some((tree_cursor, span, spacing, delim)) = self.stack.pop() {
                 // We have exhausted this token stream. Move back to its parent token stream.
                 self.tree_cursor = tree_cursor;
                 if delim != Delimiter::Invisible {
-                    return (Token::new(token::CloseDelim(delim), span.close), Spacing::Alone);
+                    return (Token::new(token::CloseDelim(delim), span.close), spacing.close);
                 }
                 // No close delimiter to return; continue on to the next iteration.
             } else {
-                // We have exhausted the outermost token stream.
+                // We have exhausted the outermost token stream. The use of
+                // `Spacing::Alone` is arbitrary and immaterial, because the
+                // `Eof` token's spacing is never used.
                 return (Token::new(token::Eof, DUMMY_SP), Spacing::Alone);
             }
         }
@@ -699,8 +706,8 @@ impl<'a> Parser<'a> {
                 // is not needed (we'll capture the entire 'glued' token),
                 // and `bump` will set this field to `None`
                 self.break_last_token = true;
-                // Use the spacing of the glued token as the spacing
-                // of the unglued second token.
+                // Use the spacing of the glued token as the spacing of the
+                // unglued second token.
                 self.bump_with((Token::new(second, second_span), self.token_spacing));
                 true
             }
@@ -1068,7 +1075,7 @@ impl<'a> Parser<'a> {
             return looker(&self.token);
         }
 
-        if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
+        if let Some(&(_, span, _, delim)) = self.token_cursor.stack.last()
             && delim != Delimiter::Invisible
         {
             // We are not in the outermost token stream, and the token stream
@@ -1077,7 +1084,7 @@ impl<'a> Parser<'a> {
             let tree_cursor = &self.token_cursor.tree_cursor;
             let all_normal = (0..dist).all(|i| {
                 let token = tree_cursor.look_ahead(i);
-                !matches!(token, Some(TokenTree::Delimited(_, Delimiter::Invisible, _)))
+                !matches!(token, Some(TokenTree::Delimited(.., Delimiter::Invisible, _)))
             });
             if all_normal {
                 // There were no skipped delimiters. Do lookahead by plain indexing.
@@ -1086,7 +1093,7 @@ impl<'a> Parser<'a> {
                         // Indexing stayed within the current token stream.
                         match tree {
                             TokenTree::Token(token, _) => looker(token),
-                            TokenTree::Delimited(dspan, delim, _) => {
+                            TokenTree::Delimited(dspan, _, delim, _) => {
                                 looker(&Token::new(token::OpenDelim(*delim), dspan.open))
                             }
                         }
@@ -1264,7 +1271,7 @@ impl<'a> Parser<'a> {
             || self.check(&token::OpenDelim(Delimiter::Brace));
 
         delimited.then(|| {
-            let TokenTree::Delimited(dspan, delim, tokens) = self.parse_token_tree() else {
+            let TokenTree::Delimited(dspan, _, delim, tokens) = self.parse_token_tree() else {
                 unreachable!()
             };
             DelimArgs { dspan, delim, tokens }
@@ -1288,7 +1295,7 @@ impl<'a> Parser<'a> {
             token::OpenDelim(..) => {
                 // Grab the tokens within the delimiters.
                 let stream = self.token_cursor.tree_cursor.stream.clone();
-                let (_, delim, span) = *self.token_cursor.stack.last().unwrap();
+                let (_, span, spacing, delim) = *self.token_cursor.stack.last().unwrap();
 
                 // Advance the token cursor through the entire delimited
                 // sequence. After getting the `OpenDelim` we are *within* the
@@ -1308,12 +1315,13 @@ impl<'a> Parser<'a> {
 
                 // Consume close delimiter
                 self.bump();
-                TokenTree::Delimited(span, delim, stream)
+                TokenTree::Delimited(span, spacing, delim, stream)
             }
             token::CloseDelim(_) | token::Eof => unreachable!(),
             _ => {
+                let prev_spacing = self.token_spacing;
                 self.bump();
-                TokenTree::Token(self.prev_token.clone(), Spacing::Alone)
+                TokenTree::Token(self.prev_token.clone(), prev_spacing)
             }
         }
     }
diff --git a/compiler/rustc_query_system/src/dep_graph/edges.rs b/compiler/rustc_query_system/src/dep_graph/edges.rs
index 400f128d583..63d46f47f5c 100644
--- a/compiler/rustc_query_system/src/dep_graph/edges.rs
+++ b/compiler/rustc_query_system/src/dep_graph/edges.rs
@@ -1,7 +1,6 @@
 use crate::dep_graph::DepNodeIndex;
 use smallvec::SmallVec;
 use std::hash::{Hash, Hasher};
-use std::iter::Extend;
 use std::ops::Deref;
 
 #[derive(Default, Debug)]
diff --git a/compiler/rustc_query_system/src/query/job.rs b/compiler/rustc_query_system/src/query/job.rs
index d933f897833..c431e966e44 100644
--- a/compiler/rustc_query_system/src/query/job.rs
+++ b/compiler/rustc_query_system/src/query/job.rs
@@ -18,7 +18,6 @@ use std::num::NonZeroU64;
 #[cfg(parallel_compiler)]
 use {
     parking_lot::{Condvar, Mutex},
-    rayon_core,
     rustc_data_structures::fx::FxHashSet,
     rustc_data_structures::{defer, jobserver},
     rustc_span::DUMMY_SP,
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index 65901eedb21..213b320ed1a 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -210,6 +210,11 @@ impl<'a, 'tcx> AsMut<Resolver<'a, 'tcx>> for BuildReducedGraphVisitor<'a, '_, 't
 }
 
 impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
+    fn res(&self, def_id: impl Into<DefId>) -> Res {
+        let def_id = def_id.into();
+        Res::Def(self.r.tcx.def_kind(def_id), def_id)
+    }
+
     fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
         self.try_resolve_visibility(vis, true).unwrap_or_else(|err| {
             self.r.report_vis_error(err);
@@ -628,6 +633,8 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         let vis = self.resolve_visibility(&item.vis);
         let local_def_id = self.r.local_def_id(item.id);
         let def_id = local_def_id.to_def_id();
+        let def_kind = self.r.tcx.def_kind(def_id);
+        let res = Res::Def(def_kind, def_id);
 
         self.r.visibilities.insert(local_def_id, vis);
 
@@ -659,7 +666,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             ItemKind::Mod(..) => {
                 let module = self.r.new_module(
                     Some(parent),
-                    ModuleKind::Def(DefKind::Mod, def_id, ident.name),
+                    ModuleKind::Def(def_kind, def_id, ident.name),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude
@@ -672,16 +679,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             // These items live in the value namespace.
-            ItemKind::Static(box ast::StaticItem { mutability, .. }) => {
-                let res = Res::Def(DefKind::Static(mutability), def_id);
+            ItemKind::Static(..) => {
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
             }
             ItemKind::Const(..) => {
-                let res = Res::Def(DefKind::Const, def_id);
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
             }
             ItemKind::Fn(..) => {
-                let res = Res::Def(DefKind::Fn, def_id);
                 self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
 
                 // Functions introducing procedural macros reserve a slot
@@ -691,14 +695,13 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
             // These items live in the type namespace.
             ItemKind::TyAlias(..) => {
-                let res = Res::Def(DefKind::TyAlias, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
             ItemKind::Enum(_, _) => {
                 let module = self.r.new_module(
                     Some(parent),
-                    ModuleKind::Def(DefKind::Enum, def_id, ident.name),
+                    ModuleKind::Def(def_kind, def_id, ident.name),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude,
@@ -708,14 +711,12 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             ItemKind::TraitAlias(..) => {
-                let res = Res::Def(DefKind::TraitAlias, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
             }
 
             // These items live in both the type and value namespaces.
             ItemKind::Struct(ref vdata, _) => {
                 // Define a name in the type namespace.
-                let res = Res::Def(DefKind::Struct, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
@@ -724,7 +725,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
                 // If this is a tuple or unit struct, define a name
                 // in the value namespace as well.
-                if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(vdata) {
+                if let Some(ctor_node_id) = vdata.ctor_node_id() {
                     // If the structure is marked as non_exhaustive then lower the visibility
                     // to within the crate.
                     let mut ctor_vis = if vis.is_public()
@@ -750,8 +751,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                         ret_fields.push(field_vis.to_def_id());
                     }
                     let ctor_def_id = self.r.local_def_id(ctor_node_id);
-                    let ctor_res =
-                        Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id.to_def_id());
+                    let ctor_res = self.res(ctor_def_id);
                     self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
                     self.r.visibilities.insert(ctor_def_id, ctor_vis);
                     // We need the field visibility spans also for the constructor for E0603.
@@ -764,7 +764,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             }
 
             ItemKind::Union(ref vdata, _) => {
-                let res = Res::Def(DefKind::Union, def_id);
                 self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
 
                 // Record field names for error reporting.
@@ -776,7 +775,7 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 // Add all the items within to a new module.
                 let module = self.r.new_module(
                     Some(parent),
-                    ModuleKind::Def(DefKind::Trait, def_id, ident.name),
+                    ModuleKind::Def(def_kind, def_id, ident.name),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude,
@@ -888,17 +887,16 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
     fn build_reduced_graph_for_foreign_item(&mut self, item: &ForeignItem) {
         let local_def_id = self.r.local_def_id(item.id);
         let def_id = local_def_id.to_def_id();
-        let (def_kind, ns) = match item.kind {
-            ForeignItemKind::Fn(..) => (DefKind::Fn, ValueNS),
-            ForeignItemKind::Static(_, mt, _) => (DefKind::Static(mt), ValueNS),
-            ForeignItemKind::TyAlias(..) => (DefKind::ForeignTy, TypeNS),
-            ForeignItemKind::MacCall(_) => unreachable!(),
+        let ns = match item.kind {
+            ForeignItemKind::Fn(..) => ValueNS,
+            ForeignItemKind::Static(..) => ValueNS,
+            ForeignItemKind::TyAlias(..) => TypeNS,
+            ForeignItemKind::MacCall(..) => unreachable!(),
         };
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
-        let res = Res::Def(def_kind, def_id);
-        self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
+        self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
         self.r.visibilities.insert(local_def_id, vis);
     }
 
@@ -1180,24 +1178,21 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         let parent_scope = self.parent_scope;
         let expansion = parent_scope.expansion;
         let def_id = self.r.local_def_id(item.id);
-        let (macro_kind, ident, span, macro_rules) = match &item.kind {
-            ItemKind::MacroDef(def) => {
-                let macro_kind = self.r.macro_map[&def_id.to_def_id()].ext.macro_kind();
-                (macro_kind, item.ident, item.span, def.macro_rules)
-            }
+        let (res, ident, span, macro_rules) = match &item.kind {
+            ItemKind::MacroDef(def) => (self.res(def_id), item.ident, item.span, def.macro_rules),
             ItemKind::Fn(..) => match self.proc_macro_stub(item) {
                 Some((macro_kind, ident, span)) => {
+                    let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
                     let macro_data = MacroData::new(self.r.dummy_ext(macro_kind));
                     self.r.macro_map.insert(def_id.to_def_id(), macro_data);
                     self.r.proc_macro_stubs.insert(def_id);
-                    (macro_kind, ident, span, false)
+                    (res, ident, span, false)
                 }
                 None => return parent_scope.macro_rules,
             },
             _ => unreachable!(),
         };
 
-        let res = Res::Def(DefKind::Macro(macro_kind), def_id.to_def_id());
         self.r.local_macro_def_scopes.insert(def_id, parent_scope.module);
 
         if macro_rules {
@@ -1363,22 +1358,21 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
         }
 
         if ctxt == AssocCtxt::Trait {
-            let (def_kind, ns) = match item.kind {
-                AssocItemKind::Const(..) => (DefKind::AssocConst, ValueNS),
+            let ns = match item.kind {
+                AssocItemKind::Const(..) => ValueNS,
                 AssocItemKind::Fn(box Fn { ref sig, .. }) => {
                     if sig.decl.has_self() {
                         self.r.has_self.insert(local_def_id);
                     }
-                    (DefKind::AssocFn, ValueNS)
+                    ValueNS
                 }
-                AssocItemKind::Type(..) => (DefKind::AssocTy, TypeNS),
+                AssocItemKind::Type(..) => TypeNS,
                 AssocItemKind::MacCall(_) => bug!(), // handled above
             };
 
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
-            let res = Res::Def(def_kind, def_id);
-            self.r.define(parent, item.ident, ns, (res, vis, item.span, expansion));
+            self.r.define(parent, item.ident, ns, (self.res(def_id), vis, item.span, expansion));
         }
 
         visit::walk_assoc_item(self, item, ctxt);
@@ -1457,9 +1451,8 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
 
         // Define a name in the type namespace.
         let def_id = self.r.local_def_id(variant.id);
-        let res = Res::Def(DefKind::Variant, def_id.to_def_id());
         let vis = self.resolve_visibility(&variant.vis);
-        self.r.define(parent, ident, TypeNS, (res, vis, variant.span, expn_id));
+        self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id));
         self.r.visibilities.insert(def_id, vis);
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the crate.
@@ -1471,10 +1464,9 @@ impl<'a, 'b, 'tcx> Visitor<'b> for BuildReducedGraphVisitor<'a, 'b, 'tcx> {
             };
 
         // Define a constructor name in the value namespace.
-        if let Some((ctor_kind, ctor_node_id)) = CtorKind::from_ast(&variant.data) {
+        if let Some(ctor_node_id) = variant.data.ctor_node_id() {
             let ctor_def_id = self.r.local_def_id(ctor_node_id);
-            let ctor_res =
-                Res::Def(DefKind::Ctor(CtorOf::Variant, ctor_kind), ctor_def_id.to_def_id());
+            let ctor_res = self.res(ctor_def_id);
             self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
             self.r.visibilities.insert(ctor_def_id, ctor_vis);
         }
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index ef465f371d2..8dc9a29c2ad 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -8,7 +8,7 @@ use crate::search_paths::SearchPath;
 use crate::utils::{CanonicalizedPath, NativeLib, NativeLibKind};
 use crate::{lint, HashStableContext};
 use crate::{EarlyErrorHandler, Session};
-use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
+use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_errors::emitter::HumanReadableErrorType;
 use rustc_errors::{ColorConfig, DiagnosticArgValue, HandlerFlags, IntoDiagnosticArg};
@@ -1114,6 +1114,7 @@ impl Default for Options {
             pretty: None,
             working_dir: RealFileName::LocalPath(std::env::current_dir().unwrap()),
             color: ColorConfig::Auto,
+            logical_env: FxIndexMap::default(),
         }
     }
 }
@@ -1246,46 +1247,85 @@ pub const fn default_lib_output() -> CrateType {
 }
 
 fn default_configuration(sess: &Session) -> Cfg {
-    // NOTE: This should be kept in sync with `CheckCfg::fill_well_known` below.
-    let end = &sess.target.endian;
-    let arch = &sess.target.arch;
-    let wordsz = sess.target.pointer_width as u64;
-    let os = &sess.target.os;
-    let env = &sess.target.env;
-    let abi = &sess.target.abi;
-    let relocation_model = sess.target.relocation_model.desc_symbol();
-    let vendor = &sess.target.vendor;
-    let min_atomic_width = sess.target.min_atomic_width();
-    let max_atomic_width = sess.target.max_atomic_width();
-    let atomic_cas = sess.target.atomic_cas;
-    let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
-        sess.emit_fatal(err);
-    });
-
     let mut ret = Cfg::default();
-    ret.reserve(7); // the minimum number of insertions
-    // Target bindings.
-    ret.insert((sym::target_os, Some(Symbol::intern(os))));
-    for fam in sess.target.families.as_ref() {
-        ret.insert((sym::target_family, Some(Symbol::intern(fam))));
-        if fam == "windows" {
-            ret.insert((sym::windows, None));
-        } else if fam == "unix" {
-            ret.insert((sym::unix, None));
-        }
-    }
-    ret.insert((sym::target_arch, Some(Symbol::intern(arch))));
-    ret.insert((sym::target_endian, Some(Symbol::intern(end.as_str()))));
-    ret.insert((sym::target_pointer_width, Some(sym::integer(wordsz))));
-    ret.insert((sym::target_env, Some(Symbol::intern(env))));
-    ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
+
+    macro_rules! ins_none {
+        ($key:expr) => {
+            ret.insert(($key, None));
+        };
+    }
+    macro_rules! ins_str {
+        ($key:expr, $val_str:expr) => {
+            ret.insert(($key, Some(Symbol::intern($val_str))));
+        };
+    }
+    macro_rules! ins_sym {
+        ($key:expr, $val_sym:expr) => {
+            ret.insert(($key, Some($val_sym)));
+        };
+    }
+
+    // Symbols are inserted in alphabetical order as much as possible.
+    // The exceptions are where control flow forces things out of order.
+    //
+    // Run `rustc --print cfg` to see the configuration in practice.
+    //
+    // NOTE: These insertions should be kept in sync with
+    // `CheckCfg::fill_well_known` below.
+
+    if sess.opts.debug_assertions {
+        ins_none!(sym::debug_assertions);
+    }
+
+    if sess.overflow_checks() {
+        ins_none!(sym::overflow_checks);
+    }
+
+    ins_sym!(sym::panic, sess.panic_strategy().desc_symbol());
+
+    // JUSTIFICATION: before wrapper fn is available
+    #[allow(rustc::bad_opt_access)]
+    if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
+        ins_none!(sym::proc_macro);
+    }
+
     if sess.is_nightly_build() {
-        ret.insert((sym::relocation_model, Some(relocation_model)));
+        ins_sym!(sym::relocation_model, sess.target.relocation_model.desc_symbol());
     }
-    ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
-    if sess.opts.unstable_opts.has_thread_local.unwrap_or(sess.target.has_thread_local) {
-        ret.insert((sym::target_thread_local, None));
+
+    for mut s in sess.opts.unstable_opts.sanitizer {
+        // KASAN is still ASAN under the hood, so it uses the same attribute.
+        if s == SanitizerSet::KERNELADDRESS {
+            s = SanitizerSet::ADDRESS;
+        }
+        ins_str!(sym::sanitize, &s.to_string());
+    }
+
+    if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
+        ins_none!(sym::sanitizer_cfi_generalize_pointers);
+    }
+    if sess.is_sanitizer_cfi_normalize_integers_enabled() {
+        ins_none!(sym::sanitizer_cfi_normalize_integers);
+    }
+
+    ins_str!(sym::target_abi, &sess.target.abi);
+    ins_str!(sym::target_arch, &sess.target.arch);
+    ins_str!(sym::target_endian, sess.target.endian.as_str());
+    ins_str!(sym::target_env, &sess.target.env);
+
+    for family in sess.target.families.as_ref() {
+        ins_str!(sym::target_family, family);
+        if family == "windows" {
+            ins_none!(sym::windows);
+        } else if family == "unix" {
+            ins_none!(sym::unix);
+        }
     }
+
+    // `target_has_atomic*`
+    let layout = sess.target.parse_data_layout().unwrap_or_else(|err| {
+        sess.emit_fatal(err);
+    });
     let mut has_atomic = false;
     for (i, align) in [
         (8, layout.i8_align.abi),
@@ -1294,63 +1334,46 @@ fn default_configuration(sess: &Session) -> Cfg {
         (64, layout.i64_align.abi),
         (128, layout.i128_align.abi),
     ] {
-        if i >= min_atomic_width && i <= max_atomic_width {
-            has_atomic = true;
+        if i >= sess.target.min_atomic_width() && i <= sess.target.max_atomic_width() {
+            if !has_atomic {
+                has_atomic = true;
+                if sess.is_nightly_build() {
+                    if sess.target.atomic_cas {
+                        ins_none!(sym::target_has_atomic);
+                    }
+                    ins_none!(sym::target_has_atomic_load_store);
+                }
+            }
             let mut insert_atomic = |sym, align: Align| {
-                ret.insert((sym::target_has_atomic_load_store, Some(sym)));
-                if atomic_cas {
-                    ret.insert((sym::target_has_atomic, Some(sym)));
+                if sess.target.atomic_cas {
+                    ins_sym!(sym::target_has_atomic, sym);
                 }
                 if align.bits() == i {
-                    ret.insert((sym::target_has_atomic_equal_alignment, Some(sym)));
+                    ins_sym!(sym::target_has_atomic_equal_alignment, sym);
                 }
+                ins_sym!(sym::target_has_atomic_load_store, sym);
             };
             insert_atomic(sym::integer(i), align);
-            if wordsz == i {
+            if sess.target.pointer_width as u64 == i {
                 insert_atomic(sym::ptr, layout.pointer_align.abi);
             }
         }
     }
-    if sess.is_nightly_build() && has_atomic {
-        ret.insert((sym::target_has_atomic_load_store, None));
-        if atomic_cas {
-            ret.insert((sym::target_has_atomic, None));
-        }
-    }
-
-    let panic_strategy = sess.panic_strategy();
-    ret.insert((sym::panic, Some(panic_strategy.desc_symbol())));
 
-    for mut s in sess.opts.unstable_opts.sanitizer {
-        // KASAN should use the same attribute name as ASAN, as it's still ASAN
-        // under the hood
-        if s == SanitizerSet::KERNELADDRESS {
-            s = SanitizerSet::ADDRESS;
-        }
+    ins_str!(sym::target_os, &sess.target.os);
+    ins_sym!(sym::target_pointer_width, sym::integer(sess.target.pointer_width));
 
-        let symbol = Symbol::intern(&s.to_string());
-        ret.insert((sym::sanitize, Some(symbol)));
+    if sess.opts.unstable_opts.has_thread_local.unwrap_or(sess.target.has_thread_local) {
+        ins_none!(sym::target_thread_local);
     }
 
-    if sess.is_sanitizer_cfi_generalize_pointers_enabled() {
-        ret.insert((sym::sanitizer_cfi_generalize_pointers, None));
-    }
+    ins_str!(sym::target_vendor, &sess.target.vendor);
 
-    if sess.is_sanitizer_cfi_normalize_integers_enabled() {
-        ret.insert((sym::sanitizer_cfi_normalize_integers, None));
+    // If the user wants a test runner, then add the test cfg.
+    if sess.is_test_crate() {
+        ins_none!(sym::test);
     }
 
-    if sess.opts.debug_assertions {
-        ret.insert((sym::debug_assertions, None));
-    }
-    if sess.overflow_checks() {
-        ret.insert((sym::overflow_checks, None));
-    }
-    // JUSTIFICATION: before wrapper fn is available
-    #[allow(rustc::bad_opt_access)]
-    if sess.opts.crate_types.contains(&CrateType::ProcMacro) {
-        ret.insert((sym::proc_macro, None));
-    }
     ret
 }
 
@@ -1421,90 +1444,71 @@ impl CheckCfg {
             ExpectedValues::Some(values)
         };
 
-        // NOTE: This should be kept in sync with `default_configuration`
+        macro_rules! ins {
+            ($name:expr, $values:expr) => {
+                self.expecteds.entry($name).or_insert_with($values)
+            };
+        }
+
+        // Symbols are inserted in alphabetical order as much as possible.
+        // The exceptions are where control flow forces things out of order.
+        //
+        // NOTE: This should be kept in sync with `default_configuration`.
+        // Note that symbols inserted conditionally in `default_configuration`
+        // are inserted unconditionally here.
         //
         // When adding a new config here you should also update
         // `tests/ui/check-cfg/well-known-values.rs`.
 
-        let panic_values = &PanicStrategy::all();
+        ins!(sym::debug_assertions, no_values);
 
-        let atomic_values = &[
-            sym::ptr,
-            sym::integer(8usize),
-            sym::integer(16usize),
-            sym::integer(32usize),
-            sym::integer(64usize),
-            sym::integer(128usize),
-        ];
+        // These three are never set by rustc, but we set them anyway: they
+        // should not trigger a lint because `cargo doc`, `cargo test`, and
+        // `cargo miri run` (respectively) can set them.
+        ins!(sym::doc, no_values);
+        ins!(sym::doctest, no_values);
+        ins!(sym::miri, no_values);
+
+        ins!(sym::overflow_checks, no_values);
+
+        ins!(sym::panic, empty_values).extend(&PanicStrategy::all());
+
+        ins!(sym::proc_macro, no_values);
+
+        ins!(sym::relocation_model, empty_values).extend(RelocModel::all());
 
         let sanitize_values = SanitizerSet::all()
             .into_iter()
             .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
+        ins!(sym::sanitize, empty_values).extend(sanitize_values);
 
-        let relocation_model_values = RelocModel::all();
-
-        // Unknown possible values:
-        //  - `target_feature`
-        for name in [sym::target_feature] {
-            self.expecteds.entry(name).or_insert(ExpectedValues::Any);
-        }
-
-        // No-values
-        for name in [
-            sym::doc,
-            sym::miri,
-            sym::unix,
-            sym::test,
-            sym::doctest,
-            sym::windows,
-            sym::proc_macro,
-            sym::debug_assertions,
-            sym::overflow_checks,
-            sym::target_thread_local,
-        ] {
-            self.expecteds.entry(name).or_insert_with(no_values);
-        }
-
-        // Pre-defined values
-        self.expecteds.entry(sym::panic).or_insert_with(empty_values).extend(panic_values);
-        self.expecteds.entry(sym::sanitize).or_insert_with(empty_values).extend(sanitize_values);
-        self.expecteds
-            .entry(sym::target_has_atomic)
-            .or_insert_with(no_values)
-            .extend(atomic_values);
-        self.expecteds
-            .entry(sym::target_has_atomic_load_store)
-            .or_insert_with(no_values)
-            .extend(atomic_values);
-        self.expecteds
-            .entry(sym::target_has_atomic_equal_alignment)
-            .or_insert_with(no_values)
-            .extend(atomic_values);
-        self.expecteds
-            .entry(sym::relocation_model)
-            .or_insert_with(empty_values)
-            .extend(relocation_model_values);
-
-        // Target specific values
+        ins!(sym::sanitizer_cfi_generalize_pointers, no_values);
+        ins!(sym::sanitizer_cfi_normalize_integers, no_values);
+
+        // rustc_codegen_ssa has a list of known target features and their
+        // stability, but we should allow any target feature as a new target or
+        // rustc version may introduce new target features.
+        ins!(sym::target_feature, || ExpectedValues::Any);
+
+        // sym::target_*
         {
             const VALUES: [&Symbol; 8] = [
-                &sym::target_os,
-                &sym::target_family,
+                &sym::target_abi,
                 &sym::target_arch,
                 &sym::target_endian,
                 &sym::target_env,
-                &sym::target_abi,
-                &sym::target_vendor,
+                &sym::target_family,
+                &sym::target_os,
                 &sym::target_pointer_width,
+                &sym::target_vendor,
             ];
 
             // Initialize (if not already initialized)
             for &e in VALUES {
-                let entry = self.expecteds.entry(e);
                 if !self.exhaustive_values {
-                    entry.or_insert(ExpectedValues::Any);
+                    ins!(e, || ExpectedValues::Any);
                 } else {
-                    entry.or_insert_with(empty_values);
+                    ins!(e, empty_values);
                 }
             }
 
@@ -1512,14 +1516,14 @@ impl CheckCfg {
                 // Get all values map at once otherwise it would be costly.
                 // (8 values * 220 targets ~= 1760 times, at the time of writing this comment).
                 let [
-                    values_target_os,
-                    values_target_family,
+                    values_target_abi,
                     values_target_arch,
                     values_target_endian,
                     values_target_env,
-                    values_target_abi,
-                    values_target_vendor,
+                    values_target_family,
+                    values_target_os,
                     values_target_pointer_width,
+                    values_target_vendor,
                 ] = self
                     .expecteds
                     .get_many_mut(VALUES)
@@ -1530,31 +1534,49 @@ impl CheckCfg {
                     .map(|target| Target::expect_builtin(&TargetTriple::from_triple(target)))
                     .chain(iter::once(current_target.clone()))
                 {
-                    values_target_os.insert(Symbol::intern(&target.options.os));
-                    values_target_family.extend(
-                        target.options.families.iter().map(|family| Symbol::intern(family)),
-                    );
+                    values_target_abi.insert(Symbol::intern(&target.options.abi));
                     values_target_arch.insert(Symbol::intern(&target.arch));
                     values_target_endian.insert(Symbol::intern(target.options.endian.as_str()));
                     values_target_env.insert(Symbol::intern(&target.options.env));
-                    values_target_abi.insert(Symbol::intern(&target.options.abi));
-                    values_target_vendor.insert(Symbol::intern(&target.options.vendor));
+                    values_target_family.extend(
+                        target.options.families.iter().map(|family| Symbol::intern(family)),
+                    );
+                    values_target_os.insert(Symbol::intern(&target.options.os));
                     values_target_pointer_width.insert(sym::integer(target.pointer_width));
+                    values_target_vendor.insert(Symbol::intern(&target.options.vendor));
                 }
             }
         }
+
+        let atomic_values = &[
+            sym::ptr,
+            sym::integer(8usize),
+            sym::integer(16usize),
+            sym::integer(32usize),
+            sym::integer(64usize),
+            sym::integer(128usize),
+        ];
+        for sym in [
+            sym::target_has_atomic,
+            sym::target_has_atomic_equal_alignment,
+            sym::target_has_atomic_load_store,
+        ] {
+            ins!(sym, no_values).extend(atomic_values);
+        }
+
+        ins!(sym::target_thread_local, no_values);
+
+        ins!(sym::test, no_values);
+
+        ins!(sym::unix, no_values);
+        ins!(sym::windows, no_values);
     }
 }
 
 pub fn build_configuration(sess: &Session, mut user_cfg: Cfg) -> Cfg {
     // Combine the configuration requested by the session (command line) with
     // some default and generated configuration items.
-    let default_cfg = default_configuration(sess);
-    // If the user wants a test runner, then add the test cfg.
-    if sess.is_test_crate() {
-        user_cfg.insert((sym::test, None));
-    }
-    user_cfg.extend(default_cfg.iter().cloned());
+    user_cfg.extend(default_configuration(sess).into_iter());
     user_cfg
 }
 
@@ -1813,6 +1835,7 @@ pub fn rustc_optgroups() -> Vec<RustcOptGroup> {
             "Remap source names in all output (compiler messages and output files)",
             "FROM=TO",
         ),
+        opt::multi("", "env", "Inject an environment variable", "VAR=VALUE"),
     ]);
     opts
 }
@@ -2592,6 +2615,23 @@ fn parse_remap_path_prefix(
     mapping
 }
 
+fn parse_logical_env(
+    handler: &mut EarlyErrorHandler,
+    matches: &getopts::Matches,
+) -> FxIndexMap<String, String> {
+    let mut vars = FxIndexMap::default();
+
+    for arg in matches.opt_strs("env") {
+        if let Some((name, val)) = arg.split_once('=') {
+            vars.insert(name.to_string(), val.to_string());
+        } else {
+            handler.early_error(format!("`--env`: specify value for variable `{arg}`"));
+        }
+    }
+
+    vars
+}
+
 // JUSTIFICATION: before wrapper fn is available
 #[allow(rustc::bad_opt_access)]
 pub fn build_session_options(
@@ -2830,6 +2870,8 @@ pub fn build_session_options(
         handler.early_error("can't dump dependency graph without `-Z query-dep-graph`");
     }
 
+    let logical_env = parse_logical_env(handler, matches);
+
     // Try to find a directory containing the Rust `src`, for more details see
     // the doc comment on the `real_rust_source_base_dir` field.
     let tmp_buf;
@@ -2910,6 +2952,7 @@ pub fn build_session_options(
         pretty,
         working_dir,
         color,
+        logical_env,
     }
 }
 
@@ -3184,6 +3227,7 @@ pub(crate) mod dep_tracking {
     };
     use crate::lint;
     use crate::utils::NativeLib;
+    use rustc_data_structures::fx::FxIndexMap;
     use rustc_data_structures::stable_hasher::Hash64;
     use rustc_errors::LanguageIdentifier;
     use rustc_feature::UnstableFeatures;
@@ -3342,6 +3386,21 @@ pub(crate) mod dep_tracking {
         }
     }
 
+    impl<T: DepTrackingHash, V: DepTrackingHash> DepTrackingHash for FxIndexMap<T, V> {
+        fn hash(
+            &self,
+            hasher: &mut DefaultHasher,
+            error_format: ErrorOutputType,
+            for_crate_hash: bool,
+        ) {
+            Hash::hash(&self.len(), hasher);
+            for (key, value) in self.iter() {
+                DepTrackingHash::hash(key, hasher, error_format, for_crate_hash);
+                DepTrackingHash::hash(value, hasher, error_format, for_crate_hash);
+            }
+        }
+    }
+
     impl DepTrackingHash for OutputTypes {
         fn hash(
             &self,
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index b1cf43f471a..d666c5d4d70 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -3,6 +3,7 @@ use crate::config::*;
 use crate::search_paths::SearchPath;
 use crate::utils::NativeLib;
 use crate::{lint, EarlyErrorHandler};
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::profiling::TimePassesFormat;
 use rustc_data_structures::stable_hasher::Hash64;
 use rustc_errors::ColorConfig;
@@ -150,6 +151,9 @@ top_level_options!(
 
         target_triple: TargetTriple [TRACKED],
 
+        /// Effective logical environment used by `env!`/`option_env!` macros
+        logical_env: FxIndexMap<String, String> [TRACKED],
+
         test: bool [TRACKED],
         error_format: ErrorOutputType [UNTRACKED],
         diagnostic_width: Option<usize> [UNTRACKED],
diff --git a/compiler/rustc_smir/src/rustc_smir/context.rs b/compiler/rustc_smir/src/rustc_smir/context.rs
index 341c69e9327..22e9f66ba96 100644
--- a/compiler/rustc_smir/src/rustc_smir/context.rs
+++ b/compiler/rustc_smir/src/rustc_smir/context.rs
@@ -16,7 +16,7 @@ use stable_mir::ty::{
     AdtDef, AdtKind, Allocation, ClosureDef, ClosureKind, Const, FieldDef, FnDef, GenericArgs,
     LineInfo, PolyFnSig, RigidTy, Span, Ty, TyKind, VariantDef,
 };
-use stable_mir::{self, Crate, CrateItem, DefId, Error, Filename, ItemKind, Symbol};
+use stable_mir::{Crate, CrateItem, DefId, Error, Filename, ItemKind, Symbol};
 use std::cell::RefCell;
 
 use crate::rustc_internal::{internal, RustcInternal};
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 4cb48a12c96..ae6cf3fe3e8 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -14,7 +14,7 @@ use rustc_middle::ty::{self, Instance, Ty, TyCtxt};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
 use stable_mir::mir::mono::InstanceDef;
 use stable_mir::ty::{ConstId, Span};
-use stable_mir::{self, ItemKind};
+use stable_mir::ItemKind;
 use tracing::debug;
 
 use crate::rustc_internal::IndexMap;
diff --git a/compiler/rustc_span/src/edition.rs b/compiler/rustc_span/src/edition.rs
index 608b8c24bde..78ac61fa31d 100644
--- a/compiler/rustc_span/src/edition.rs
+++ b/compiler/rustc_span/src/edition.rs
@@ -1,4 +1,3 @@
-use crate::symbol::{sym, Symbol};
 use std::fmt;
 use std::str::FromStr;
 
@@ -58,15 +57,6 @@ impl Edition {
         }
     }
 
-    pub fn feature_name(self) -> Symbol {
-        match self {
-            Edition::Edition2015 => sym::rust_2015_preview,
-            Edition::Edition2018 => sym::rust_2018_preview,
-            Edition::Edition2021 => sym::rust_2021_preview,
-            Edition::Edition2024 => sym::rust_2024_preview,
-        }
-    }
-
     pub fn is_stable(self) -> bool {
         match self {
             Edition::Edition2015 => true,
diff --git a/compiler/rustc_span/src/source_map.rs b/compiler/rustc_span/src/source_map.rs
index dcf346acb33..cb10e6bf2ba 100644
--- a/compiler/rustc_span/src/source_map.rs
+++ b/compiler/rustc_span/src/source_map.rs
@@ -11,13 +11,11 @@
 
 use crate::*;
 use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::stable_hasher::{Hash128, Hash64, StableHasher};
-use rustc_data_structures::sync::{IntoDynSyncSend, Lrc, MappedReadGuard, ReadGuard, RwLock};
-use std::cmp;
+use rustc_data_structures::sync::{IntoDynSyncSend, MappedReadGuard, ReadGuard, RwLock};
 use std::fs;
 use std::hash::Hash;
 use std::io::{self, BorrowedBuf, Read};
-use std::path::{self, Path, PathBuf};
+use std::path::{self};
 
 #[cfg(test)]
 mod tests;
diff --git a/compiler/rustc_span/src/source_map/tests.rs b/compiler/rustc_span/src/source_map/tests.rs
index 5697969ddb8..113ca493d36 100644
--- a/compiler/rustc_span/src/source_map/tests.rs
+++ b/compiler/rustc_span/src/source_map/tests.rs
@@ -1,7 +1,5 @@
 use super::*;
 
-use rustc_data_structures::sync::{FreezeLock, Lrc};
-
 fn init_source_map() -> SourceMap {
     let sm = SourceMap::new(FilePathMapping::empty());
     sm.new_source_file(PathBuf::from("blork.rs").into(), "first line.\nsecond line".to_string());
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 485265e6889..0333b5f04c3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -520,6 +520,8 @@ symbols! {
         cmp,
         cmp_max,
         cmp_min,
+        cmp_partialeq_eq,
+        cmp_partialeq_ne,
         cmpxchg16b_target_feature,
         cmse_nonsecure_entry,
         coerce_unsized,
@@ -933,6 +935,7 @@ symbols! {
         lib,
         libc,
         lifetime,
+        lifetime_capture_rules_2024,
         lifetimes,
         likely,
         line,
@@ -1349,13 +1352,10 @@ symbols! {
         rtm_target_feature,
         rust,
         rust_2015,
-        rust_2015_preview,
         rust_2018,
         rust_2018_preview,
         rust_2021,
-        rust_2021_preview,
         rust_2024,
-        rust_2024_preview,
         rust_begin_unwind,
         rust_cold_cc,
         rust_eh_catch_typeinfo,
diff --git a/compiler/rustc_trait_selection/src/traits/auto_trait.rs b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
index 0b8e6e2ef8b..13a09917c03 100644
--- a/compiler/rustc_trait_selection/src/traits/auto_trait.rs
+++ b/compiler/rustc_trait_selection/src/traits/auto_trait.rs
@@ -5,11 +5,9 @@ use super::*;
 
 use crate::errors::UnableToConstructConstantValue;
 use crate::infer::region_constraints::{Constraint, RegionConstraintData};
-use crate::infer::InferCtxt;
 use crate::traits::project::ProjectAndUnifyResult;
 use rustc_infer::infer::DefineOpaqueTypes;
 use rustc_middle::mir::interpret::ErrorHandled;
-use rustc_middle::ty::visit::TypeVisitableExt;
 use rustc_middle::ty::{ImplPolarity, Region, RegionVid};
 
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexSet};
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 95ffd07e397..f7e8dc62a62 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/suggestions.rs
@@ -3628,17 +3628,19 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
             is_derivable_trait &&
                 // Ensure all fields impl the trait.
                 adt.all_fields().all(|field| {
-                    let field_ty = field.ty(self.tcx, args);
+                    let field_ty = ty::GenericArg::from(field.ty(self.tcx, args));
                     let trait_args = match diagnostic_name {
                         sym::PartialEq | sym::PartialOrd => {
                             Some(field_ty)
                         }
                         _ => None,
                     };
+                    // Also add host param, if present
+                    let host = self.tcx.generics_of(trait_pred.def_id()).host_effect_index.map(|idx| trait_pred.skip_binder().trait_ref.args[idx]);
                     let trait_pred = trait_pred.map_bound_ref(|tr| ty::TraitPredicate {
                         trait_ref: ty::TraitRef::new(self.tcx,
                             trait_pred.def_id(),
-                            [field_ty].into_iter().chain(trait_args),
+                            [field_ty].into_iter().chain(trait_args).chain(host),
                         ),
                         ..*tr
                     });
@@ -3659,6 +3661,7 @@ impl<'tcx> TypeErrCtxtExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     trait_pred.skip_binder().self_ty(),
                     diagnostic_name,
                 ),
+                // FIXME(effects, const_trait_impl) derive_const as suggestion?
                 format!("#[derive({diagnostic_name})]\n"),
                 Applicability::MaybeIncorrect,
             );
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 7599aa9fa41..d896873fadd 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -8,9 +8,7 @@ use rustc_middle::ty::layout::{
     IntegerExt, LayoutCx, LayoutError, LayoutOf, TyAndLayout, MAX_SIMD_LANES,
 };
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{
-    self, AdtDef, EarlyBinder, GenericArgsRef, ReprOptions, Ty, TyCtxt, TypeVisitableExt,
-};
+use rustc_middle::ty::{self, AdtDef, EarlyBinder, GenericArgsRef, Ty, TyCtxt, TypeVisitableExt};
 use rustc_session::{DataTypeKind, FieldInfo, FieldKind, SizeKind, VariantInfo};
 use rustc_span::symbol::Symbol;
 use rustc_span::DUMMY_SP;
@@ -435,7 +433,21 @@ fn layout_of_uncached<'tcx>(
                 .size
                 .checked_mul(e_len, dl)
                 .ok_or_else(|| error(cx, LayoutError::SizeOverflow(ty)))?;
-            let align = dl.vector_align(size);
+
+            let (abi, align) = if def.repr().packed() && !e_len.is_power_of_two() {
+                // Non-power-of-two vectors have padding up to the next power-of-two.
+                // If we're a packed repr, remove the padding while keeping the alignment as close
+                // to a vector as possible.
+                (
+                    Abi::Aggregate { sized: true },
+                    AbiAndPrefAlign {
+                        abi: Align::max_for_offset(size),
+                        pref: dl.vector_align(size).pref,
+                    },
+                )
+            } else {
+                (Abi::Vector { element: e_abi, count: e_len }, dl.vector_align(size))
+            };
             let size = size.align_to(align.abi);
 
             // Compute the placement of the vector fields:
@@ -448,7 +460,7 @@ fn layout_of_uncached<'tcx>(
             tcx.mk_layout(LayoutS {
                 variants: Variants::Single { index: FIRST_VARIANT },
                 fields,
-                abi: Abi::Vector { element: e_abi, count: e_len },
+                abi,
                 largest_niche: e_ly.largest_niche,
                 size,
                 align,
diff --git a/compiler/stable_mir/src/error.rs b/compiler/stable_mir/src/error.rs
index c6da3ae41d3..7085fa937c9 100644
--- a/compiler/stable_mir/src/error.rs
+++ b/compiler/stable_mir/src/error.rs
@@ -4,7 +4,6 @@
 //! - [CompilerError]: This represents errors that can be raised when invoking the compiler.
 //! - [Error]: Generic error that represents the reason why a request that could not be fulfilled.
 
-use std::convert::From;
 use std::fmt::{Debug, Display, Formatter};
 use std::{error, fmt, io};
 
diff --git a/config.example.toml b/config.example.toml
index 49c4ad4c958..14e0b9d521f 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -30,7 +30,7 @@
 #
 # If `change-id` does not match the version that is currently running,
 # `x.py` will prompt you to update it and check the related PR for more details.
-change-id = 117813
+change-id = 118703
 
 # =============================================================================
 # Tweaking how LLVM is compiled
@@ -648,10 +648,12 @@ change-id = 117813
 #lld = false
 
 # Indicates whether LLD will be used to link Rust crates during bootstrap on
-# supported platforms. The LLD from the bootstrap distribution will be used
-# and not the LLD compiled during the bootstrap.
+# supported platforms.
+# If set to `true` or `"external"`, a global `lld` binary that has to be in $PATH
+# will be used.
+# If set to `"self-contained"`, rust-lld from the snapshot compiler will be used.
 #
-# LLD will not be used if we're cross linking.
+# On MSVC, LLD will not be used if we're cross linking.
 #
 # Explicitly setting the linker for a target will override this option when targeting MSVC.
 #use-lld = false
diff --git a/library/alloc/benches/btree/map.rs b/library/alloc/benches/btree/map.rs
index 7d236647750..4fe07eb0213 100644
--- a/library/alloc/benches/btree/map.rs
+++ b/library/alloc/benches/btree/map.rs
@@ -1,6 +1,5 @@
 use std::collections::BTreeMap;
 use std::ops::RangeBounds;
-use std::vec::Vec;
 
 use rand::{seq::SliceRandom, Rng};
 use test::{black_box, Bencher};
diff --git a/library/alloc/benches/str.rs b/library/alloc/benches/str.rs
index 54af389dedc..c148ab6b220 100644
--- a/library/alloc/benches/str.rs
+++ b/library/alloc/benches/str.rs
@@ -1,4 +1,3 @@
-use core::iter::Iterator;
 use test::{black_box, Bencher};
 
 #[bench]
diff --git a/library/alloc/benches/vec_deque.rs b/library/alloc/benches/vec_deque.rs
index 313a97ed1ff..35939f489b4 100644
--- a/library/alloc/benches/vec_deque.rs
+++ b/library/alloc/benches/vec_deque.rs
@@ -1,4 +1,3 @@
-use core::iter::Iterator;
 use std::{
     collections::{vec_deque, VecDeque},
     mem,
diff --git a/library/alloc/src/collections/binary_heap/tests.rs b/library/alloc/src/collections/binary_heap/tests.rs
index 565a7b7975f..d4bc6226a14 100644
--- a/library/alloc/src/collections/binary_heap/tests.rs
+++ b/library/alloc/src/collections/binary_heap/tests.rs
@@ -1,8 +1,6 @@
 use super::*;
 use crate::boxed::Box;
 use crate::testing::crash_test::{CrashTestDummy, Panic};
-use core::mem;
-use std::iter::TrustedLen;
 use std::panic::{catch_unwind, AssertUnwindSafe};
 
 #[test]
diff --git a/library/alloc/src/collections/btree/map/tests.rs b/library/alloc/src/collections/btree/map/tests.rs
index 8681cfcd617..a1b7cfe6b17 100644
--- a/library/alloc/src/collections/btree/map/tests.rs
+++ b/library/alloc/src/collections/btree/map/tests.rs
@@ -1,4 +1,3 @@
-use super::Entry::{Occupied, Vacant};
 use super::*;
 use crate::boxed::Box;
 use crate::fmt::Debug;
@@ -7,13 +6,9 @@ use crate::string::{String, ToString};
 use crate::testing::crash_test::{CrashTestDummy, Panic};
 use crate::testing::ord_chaos::{Cyclic3, Governed, Governor};
 use crate::testing::rng::DeterministicRng;
-use crate::vec::Vec;
 use core::assert_matches::assert_matches;
-use std::cmp::Ordering;
 use std::iter;
-use std::mem;
-use std::ops::Bound::{self, Excluded, Included, Unbounded};
-use std::ops::RangeBounds;
+use std::ops::Bound::{Excluded, Included, Unbounded};
 use std::panic::{catch_unwind, AssertUnwindSafe};
 use std::sync::atomic::{AtomicUsize, Ordering::SeqCst};
 
diff --git a/library/alloc/src/collections/btree/set/tests.rs b/library/alloc/src/collections/btree/set/tests.rs
index e05bf0e2003..8726c5bfead 100644
--- a/library/alloc/src/collections/btree/set/tests.rs
+++ b/library/alloc/src/collections/btree/set/tests.rs
@@ -1,9 +1,6 @@
 use super::*;
 use crate::testing::crash_test::{CrashTestDummy, Panic};
 use crate::testing::rng::DeterministicRng;
-use crate::vec::Vec;
-use std::cmp::Ordering;
-use std::hash::{Hash, Hasher};
 use std::ops::Bound::{Excluded, Included};
 use std::panic::{catch_unwind, AssertUnwindSafe};
 
diff --git a/library/alloc/src/ffi/c_str/tests.rs b/library/alloc/src/ffi/c_str/tests.rs
index 0b7476d5cc7..9f51e17a427 100644
--- a/library/alloc/src/ffi/c_str/tests.rs
+++ b/library/alloc/src/ffi/c_str/tests.rs
@@ -1,6 +1,4 @@
 use super::*;
-use crate::rc::Rc;
-use crate::sync::Arc;
 use core::assert_matches::assert_matches;
 use core::ffi::FromBytesUntilNulError;
 use core::hash::{Hash, Hasher};
diff --git a/library/alloc/src/rc/tests.rs b/library/alloc/src/rc/tests.rs
index 1f221b86f12..c8a40603d9d 100644
--- a/library/alloc/src/rc/tests.rs
+++ b/library/alloc/src/rc/tests.rs
@@ -1,12 +1,7 @@
 use super::*;
 
-use std::boxed::Box;
 use std::cell::RefCell;
 use std::clone::Clone;
-use std::convert::{From, TryInto};
-use std::mem::drop;
-use std::option::Option::{self, None, Some};
-use std::result::Result::{Err, Ok};
 
 #[test]
 fn test_clone() {
diff --git a/library/alloc/src/sync/tests.rs b/library/alloc/src/sync/tests.rs
index 863d58bdf4d..d37e45569cf 100644
--- a/library/alloc/src/sync/tests.rs
+++ b/library/alloc/src/sync/tests.rs
@@ -1,21 +1,12 @@
 use super::*;
 
-use std::boxed::Box;
 use std::clone::Clone;
-use std::convert::{From, TryInto};
-use std::mem::drop;
-use std::ops::Drop;
-use std::option::Option::{self, None, Some};
-use std::sync::atomic::{
-    self,
-    Ordering::{Acquire, SeqCst},
-};
+use std::option::Option::None;
+use std::sync::atomic::Ordering::SeqCst;
 use std::sync::mpsc::channel;
 use std::sync::Mutex;
 use std::thread;
 
-use crate::vec::Vec;
-
 struct Canary(*mut atomic::AtomicUsize);
 
 impl Drop for Canary {
diff --git a/library/alloc/src/tests.rs b/library/alloc/src/tests.rs
index b1d3a9fa8ac..ab256ceaec3 100644
--- a/library/alloc/src/tests.rs
+++ b/library/alloc/src/tests.rs
@@ -1,8 +1,6 @@
 //! Test for `boxed` mod.
 
 use core::any::Any;
-use core::clone::Clone;
-use core::convert::TryInto;
 use core::ops::Deref;
 
 use std::boxed::Box;
diff --git a/library/alloc/tests/arc.rs b/library/alloc/tests/arc.rs
index ce40b5c9b0a..d564a30b103 100644
--- a/library/alloc/tests/arc.rs
+++ b/library/alloc/tests/arc.rs
@@ -1,6 +1,5 @@
 use std::any::Any;
 use std::cell::RefCell;
-use std::cmp::PartialEq;
 use std::iter::TrustedLen;
 use std::mem;
 use std::sync::{Arc, Weak};
diff --git a/library/alloc/tests/borrow.rs b/library/alloc/tests/borrow.rs
index 57976aa6cdf..af7efb7d782 100644
--- a/library/alloc/tests/borrow.rs
+++ b/library/alloc/tests/borrow.rs
@@ -1,4 +1,4 @@
-use std::borrow::{Cow, ToOwned};
+use std::borrow::Cow;
 use std::ffi::{CStr, OsStr};
 use std::path::Path;
 use std::rc::Rc;
diff --git a/library/alloc/tests/rc.rs b/library/alloc/tests/rc.rs
index efb39a60966..499740e738a 100644
--- a/library/alloc/tests/rc.rs
+++ b/library/alloc/tests/rc.rs
@@ -1,6 +1,5 @@
 use std::any::Any;
 use std::cell::RefCell;
-use std::cmp::PartialEq;
 use std::iter::TrustedLen;
 use std::mem;
 use std::rc::{Rc, Weak};
diff --git a/library/alloc/tests/vec.rs b/library/alloc/tests/vec.rs
index 3d3175ba3a9..364dc920187 100644
--- a/library/alloc/tests/vec.rs
+++ b/library/alloc/tests/vec.rs
@@ -1,7 +1,5 @@
-use alloc::vec::Vec;
 use core::alloc::{Allocator, Layout};
 use core::{assert_eq, assert_ne};
-use core::iter::{IntoIterator, Iterator};
 use core::num::NonZeroUsize;
 use core::ptr::NonNull;
 use std::alloc::System;
@@ -1982,7 +1980,7 @@ fn vec_macro_repeating_null_raw_fat_pointer() {
 
     let vec = vec![null_raw_dyn; 1];
     dbg!(ptr_metadata(vec[0]));
-    assert!(vec[0] == null_raw_dyn);
+    assert!(std::ptr::eq(vec[0], null_raw_dyn));
 
     // Polyfill for https://github.com/rust-lang/rfcs/pull/2580
 
diff --git a/library/core/benches/num/flt2dec/mod.rs b/library/core/benches/num/flt2dec/mod.rs
index 1a330ef5fe5..b1a9fc56bae 100644
--- a/library/core/benches/num/flt2dec/mod.rs
+++ b/library/core/benches/num/flt2dec/mod.rs
@@ -6,7 +6,6 @@ mod strategy {
 use core::num::flt2dec::MAX_SIG_DIGITS;
 use core::num::flt2dec::{decode, DecodableFloat, Decoded, FullDecoded};
 use std::io::Write;
-use std::vec::Vec;
 use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
diff --git a/library/core/benches/num/flt2dec/strategy/dragon.rs b/library/core/benches/num/flt2dec/strategy/dragon.rs
index 377c99effd0..babedc6c0ec 100644
--- a/library/core/benches/num/flt2dec/strategy/dragon.rs
+++ b/library/core/benches/num/flt2dec/strategy/dragon.rs
@@ -1,7 +1,6 @@
 use super::super::*;
 use core::num::flt2dec::strategy::dragon::*;
 use std::mem::MaybeUninit;
-use test::{black_box, Bencher};
 
 #[bench]
 fn bench_small_shortest(b: &mut Bencher) {
diff --git a/library/core/benches/num/flt2dec/strategy/grisu.rs b/library/core/benches/num/flt2dec/strategy/grisu.rs
index 17d6b474ad2..b5bddb2c7c7 100644
--- a/library/core/benches/num/flt2dec/strategy/grisu.rs
+++ b/library/core/benches/num/flt2dec/strategy/grisu.rs
@@ -1,7 +1,6 @@
 use super::super::*;
 use core::num::flt2dec::strategy::grisu::*;
 use std::mem::MaybeUninit;
-use test::{black_box, Bencher};
 
 pub fn decode_finite<T: DecodableFloat>(v: T) -> Decoded {
     match decode(v).1 {
diff --git a/library/core/src/array/iter.rs b/library/core/src/array/iter.rs
index 321357a15bf..2b22488b8ff 100644
--- a/library/core/src/array/iter.rs
+++ b/library/core/src/array/iter.rs
@@ -4,7 +4,7 @@ use crate::num::NonZeroUsize;
 use crate::{
     fmt,
     intrinsics::transmute_unchecked,
-    iter::{self, ExactSizeIterator, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce},
+    iter::{self, FusedIterator, TrustedLen, TrustedRandomAccessNoCoerce},
     mem::MaybeUninit,
     ops::{IndexRange, Range},
     ptr,
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 7ce33bdd411..a93b94867ce 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -1,6 +1,5 @@
 //! impl char {}
 
-use crate::ascii;
 use crate::slice;
 use crate::str::from_utf8_unchecked_mut;
 use crate::unicode::printable::is_printable;
diff --git a/library/core/src/clone.rs b/library/core/src/clone.rs
index d7ca9c22dad..ba86334f950 100644
--- a/library/core/src/clone.rs
+++ b/library/core/src/clone.rs
@@ -210,8 +210,6 @@ pub struct AssertParamIsCopy<T: Copy + ?Sized> {
 /// are implemented in `traits::SelectionContext::copy_clone_conditions()`
 /// in `rustc_trait_selection`.
 mod impls {
-    use super::Clone;
-
     macro_rules! impl_clone {
         ($($t:ty)*) => {
             $(
diff --git a/library/core/src/cmp.rs b/library/core/src/cmp.rs
index fadf2fcc9fc..d7c41ac5c06 100644
--- a/library/core/src/cmp.rs
+++ b/library/core/src/cmp.rs
@@ -224,11 +224,13 @@ use self::Ordering::*;
     append_const_msg
 )]
 #[rustc_diagnostic_item = "PartialEq"]
+#[cfg_attr(not(bootstrap), const_trait)]
 pub trait PartialEq<Rhs: ?Sized = Self> {
     /// This method tests for `self` and `other` values to be equal, and is used
     /// by `==`.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_eq")]
     fn eq(&self, other: &Rhs) -> bool;
 
     /// This method tests for `!=`. The default implementation is almost always
@@ -236,6 +238,7 @@ pub trait PartialEq<Rhs: ?Sized = Self> {
     #[inline]
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
+    #[cfg_attr(not(bootstrap), rustc_diagnostic_item = "cmp_partialeq_ne")]
     fn ne(&self, other: &Rhs) -> bool {
         !self.eq(other)
     }
@@ -1414,12 +1417,23 @@ mod impls {
     macro_rules! partial_eq_impl {
         ($($t:ty)*) => ($(
             #[stable(feature = "rust1", since = "1.0.0")]
+            #[cfg(bootstrap)]
             impl PartialEq for $t {
                 #[inline]
                 fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
                 #[inline]
                 fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
             }
+
+            #[stable(feature = "rust1", since = "1.0.0")]
+            #[rustc_const_unstable(feature = "const_cmp", issue = "92391")]
+            #[cfg(not(bootstrap))]
+            impl const PartialEq for $t {
+                #[inline]
+                fn eq(&self, other: &$t) -> bool { (*self) == (*other) }
+                #[inline]
+                fn ne(&self, other: &$t) -> bool { (*self) != (*other) }
+            }
         )*)
     }
 
diff --git a/library/core/src/convert/num.rs b/library/core/src/convert/num.rs
index b048b513592..08dc8f48dfe 100644
--- a/library/core/src/convert/num.rs
+++ b/library/core/src/convert/num.rs
@@ -1,4 +1,4 @@
-use super::{From, TryFrom};
+use super::TryFrom;
 use crate::num::TryFromIntError;
 
 mod private {
diff --git a/library/core/src/future/future.rs b/library/core/src/future/future.rs
index 8c7111cb3ff..71b9464efd2 100644
--- a/library/core/src/future/future.rs
+++ b/library/core/src/future/future.rs
@@ -1,6 +1,5 @@
 #![stable(feature = "futures_api", since = "1.36.0")]
 
-use crate::marker::Unpin;
 use crate::ops;
 use crate::pin::Pin;
 use crate::task::{Context, Poll};
diff --git a/library/core/src/iter/adapters/array_chunks.rs b/library/core/src/iter/adapters/array_chunks.rs
index 319af4408d7..946d0051cce 100644
--- a/library/core/src/iter/adapters/array_chunks.rs
+++ b/library/core/src/iter/adapters/array_chunks.rs
@@ -1,7 +1,7 @@
 use crate::array;
 use crate::iter::adapters::SourceIter;
 use crate::iter::{
-    ByRefSized, FusedIterator, InPlaceIterable, Iterator, TrustedFused, TrustedRandomAccessNoCoerce,
+    ByRefSized, FusedIterator, InPlaceIterable, TrustedFused, TrustedRandomAccessNoCoerce,
 };
 use crate::num::NonZeroUsize;
 use crate::ops::{ControlFlow, NeverShortCircuit, Try};
diff --git a/library/core/src/iter/adapters/chain.rs b/library/core/src/iter/adapters/chain.rs
index 26aa959e6da..c748336cd7f 100644
--- a/library/core/src/iter/adapters/chain.rs
+++ b/library/core/src/iter/adapters/chain.rs
@@ -1,4 +1,4 @@
-use crate::iter::{DoubleEndedIterator, FusedIterator, Iterator, TrustedLen};
+use crate::iter::{FusedIterator, TrustedLen};
 use crate::num::NonZeroUsize;
 use crate::ops::Try;
 
diff --git a/library/core/src/iter/adapters/flatten.rs b/library/core/src/iter/adapters/flatten.rs
index 09428350fd9..6122332da0d 100644
--- a/library/core/src/iter/adapters/flatten.rs
+++ b/library/core/src/iter/adapters/flatten.rs
@@ -1,7 +1,7 @@
 use crate::iter::adapters::SourceIter;
 use crate::iter::{
-    Cloned, Copied, DoubleEndedIterator, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable,
-    Iterator, Map, TrustedFused, TrustedLen,
+    Cloned, Copied, Filter, FilterMap, Fuse, FusedIterator, InPlaceIterable, Map, TrustedFused,
+    TrustedLen,
 };
 use crate::iter::{Once, OnceWith};
 use crate::num::NonZeroUsize;
diff --git a/library/core/src/iter/adapters/fuse.rs b/library/core/src/iter/adapters/fuse.rs
index 3234cade50d..462a7e87733 100644
--- a/library/core/src/iter/adapters/fuse.rs
+++ b/library/core/src/iter/adapters/fuse.rs
@@ -2,8 +2,7 @@ use crate::intrinsics;
 use crate::iter::adapters::zip::try_get_unchecked;
 use crate::iter::adapters::SourceIter;
 use crate::iter::{
-    DoubleEndedIterator, ExactSizeIterator, FusedIterator, TrustedFused, TrustedLen,
-    TrustedRandomAccess, TrustedRandomAccessNoCoerce,
+    FusedIterator, TrustedFused, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce,
 };
 use crate::ops::Try;
 
diff --git a/library/core/src/iter/adapters/map_windows.rs b/library/core/src/iter/adapters/map_windows.rs
index 3c0e80b2559..5f39b245834 100644
--- a/library/core/src/iter/adapters/map_windows.rs
+++ b/library/core/src/iter/adapters/map_windows.rs
@@ -1,6 +1,6 @@
 use crate::{
     fmt,
-    iter::{ExactSizeIterator, FusedIterator},
+    iter::FusedIterator,
     mem::{self, MaybeUninit},
     ptr,
 };
diff --git a/library/core/src/iter/adapters/mod.rs b/library/core/src/iter/adapters/mod.rs
index a691039c789..4037e2e2839 100644
--- a/library/core/src/iter/adapters/mod.rs
+++ b/library/core/src/iter/adapters/mod.rs
@@ -1,4 +1,4 @@
-use crate::iter::{InPlaceIterable, Iterator};
+use crate::iter::InPlaceIterable;
 use crate::num::NonZeroUsize;
 use crate::ops::{ChangeOutputType, ControlFlow, FromResidual, Residual, Try};
 
diff --git a/library/core/src/iter/adapters/zip.rs b/library/core/src/iter/adapters/zip.rs
index e3041519be7..b33400fab47 100644
--- a/library/core/src/iter/adapters/zip.rs
+++ b/library/core/src/iter/adapters/zip.rs
@@ -1,6 +1,6 @@
 use crate::cmp;
 use crate::fmt::{self, Debug};
-use crate::iter::{DoubleEndedIterator, ExactSizeIterator, FusedIterator, Iterator, TrustedFused};
+use crate::iter::{FusedIterator, TrustedFused};
 use crate::iter::{InPlaceIterable, SourceIter, TrustedLen, UncheckedIterator};
 use crate::num::NonZeroUsize;
 
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index bf10ada0176..c1687abb7cb 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -10,7 +10,7 @@ use crate::cmp;
 use crate::fmt;
 use crate::hash;
 use crate::intrinsics;
-use crate::marker::{Copy, DiscriminantKind, Sized};
+use crate::marker::DiscriminantKind;
 use crate::ptr;
 
 mod manually_drop;
diff --git a/library/core/src/ops/coroutine.rs b/library/core/src/ops/coroutine.rs
index 80e2903992e..e58c9068af8 100644
--- a/library/core/src/ops/coroutine.rs
+++ b/library/core/src/ops/coroutine.rs
@@ -1,4 +1,3 @@
-use crate::marker::Unpin;
 use crate::pin::Pin;
 
 /// The result of a coroutine resumption.
diff --git a/library/core/src/pin.rs b/library/core/src/pin.rs
index c3e774e1dab..7d8c881eab8 100644
--- a/library/core/src/pin.rs
+++ b/library/core/src/pin.rs
@@ -381,10 +381,9 @@
 
 #![stable(feature = "pin", since = "1.33.0")]
 
-use crate::cmp::{self, PartialEq, PartialOrd};
+use crate::cmp;
 use crate::fmt;
 use crate::hash::{Hash, Hasher};
-use crate::marker::{Sized, Unpin};
 use crate::ops::{CoerceUnsized, Deref, DerefMut, DispatchFromDyn, Receiver};
 
 /// A pinned pointer.
diff --git a/library/core/src/primitive_docs.rs b/library/core/src/primitive_docs.rs
index e5d7e964381..588f9b865b0 100644
--- a/library/core/src/primitive_docs.rs
+++ b/library/core/src/primitive_docs.rs
@@ -330,7 +330,7 @@ mod prim_never {}
 /// the future ("reserved"); some will never be a character ("noncharacters"); and some may be given
 /// different meanings by different users ("private use").
 ///
-/// `char` is guaranteed to have the same size and alignment as `u32` on all
+/// `char` is guaranteed to have the same size, alignment, and function call ABI as `u32` on all
 /// platforms.
 /// ```
 /// use std::alloc::Layout;
@@ -1557,6 +1557,7 @@ mod prim_ref {}
 ///   Pointee>::Metadata`).
 /// - `usize` is ABI-compatible with the `uN` integer type of the same size, and likewise `isize` is
 ///   ABI-compatible with the `iN` integer type of the same size.
+/// - `char` is ABI-compatible with `u32`.
 /// - Any two `fn` (function pointer) types are ABI-compatible with each other if they have the same
 ///   ABI string or the ABI string only differs in a trailing `-unwind`, independent of the rest of
 ///   their signature. (This means you can pass `fn()` to a function expecting `fn(i32)`, and the
@@ -1585,9 +1586,9 @@ mod prim_ref {}
 /// since it is not portable and not a stable guarantee.
 ///
 /// Noteworthy cases of types *not* being ABI-compatible in general are:
-/// * `bool` vs `u8`, and `i32` vs `u32`: on some targets, the calling conventions for these types
-///   differ in terms of what they guarantee for the remaining bits in the register that are not
-///   used by the value.
+/// * `bool` vs `u8`, `i32` vs `u32`, `char` vs `i32`: on some targets, the calling conventions for
+///   these types differ in terms of what they guarantee for the remaining bits in the register that
+///   are not used by the value.
 /// * `i32` vs `f32` are not compatible either, as has already been mentioned above.
 /// * `struct Foo(u32)` and `u32` are not compatible (without `repr(transparent)`) since structs are
 ///   aggregate types and often passed in a different way than primitives like `i32`.
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 2f47ca29ec5..a444c30c756 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -1,7 +1,7 @@
 use super::*;
-use crate::cmp::Ordering::{self, Equal, Greater, Less};
-use crate::intrinsics::{self, const_eval_select};
-use crate::mem::{self, SizedTypeProperties};
+use crate::cmp::Ordering::{Equal, Greater, Less};
+use crate::intrinsics::const_eval_select;
+use crate::mem::SizedTypeProperties;
 use crate::slice::{self, SliceIndex};
 
 impl<T: ?Sized> *const T {
@@ -1772,6 +1772,7 @@ impl<T> *const [T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *const T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &*const T) -> bool {
         *self == *other
     }
@@ -1784,6 +1785,7 @@ impl<T: ?Sized> Eq for *const T {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Ord for *const T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn cmp(&self, other: &*const T) -> Ordering {
         if self < other {
             Less
@@ -1803,21 +1805,25 @@ impl<T: ?Sized> PartialOrd for *const T {
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn lt(&self, other: &*const T) -> bool {
         *self < *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn le(&self, other: &*const T) -> bool {
         *self <= *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn gt(&self, other: &*const T) -> bool {
         *self > *other
     }
 
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn ge(&self, other: &*const T) -> bool {
         *self >= *other
     }
diff --git a/library/core/src/ptr/mod.rs b/library/core/src/ptr/mod.rs
index 50cf29227ca..d6603681a0b 100644
--- a/library/core/src/ptr/mod.rs
+++ b/library/core/src/ptr/mod.rs
@@ -1897,6 +1897,7 @@ pub(crate) const unsafe fn align_offset<T: Sized>(p: *const T, a: usize) -> usiz
 #[inline(always)]
 #[must_use = "pointer comparison produces a value"]
 #[rustc_diagnostic_item = "ptr_eq"]
+#[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))] // it's actually clear here
 pub fn eq<T: ?Sized>(a: *const T, b: *const T) -> bool {
     a == b
 }
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index 3aaae679a6f..9e7b8ec64ac 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -1,6 +1,6 @@
 use super::*;
-use crate::cmp::Ordering::{self, Equal, Greater, Less};
-use crate::intrinsics::{self, const_eval_select};
+use crate::cmp::Ordering::{Equal, Greater, Less};
+use crate::intrinsics::const_eval_select;
 use crate::mem::SizedTypeProperties;
 use crate::slice::{self, SliceIndex};
 
@@ -2199,6 +2199,7 @@ impl<T> *mut [T] {
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> PartialEq for *mut T {
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &*mut T) -> bool {
         *self == *other
     }
@@ -2210,6 +2211,7 @@ impl<T: ?Sized> Eq for *mut T {}
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<T: ?Sized> Ord for *mut T {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn cmp(&self, other: &*mut T) -> Ordering {
         if self < other {
             Less
@@ -2229,21 +2231,25 @@ impl<T: ?Sized> PartialOrd for *mut T {
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn lt(&self, other: &*mut T) -> bool {
         *self < *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn le(&self, other: &*mut T) -> bool {
         *self <= *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn gt(&self, other: &*mut T) -> bool {
         *self > *other
     }
 
     #[inline(always)]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn ge(&self, other: &*mut T) -> bool {
         *self >= *other
     }
diff --git a/library/core/src/ptr/non_null.rs b/library/core/src/ptr/non_null.rs
index c99fe36de6d..77961506e13 100644
--- a/library/core/src/ptr/non_null.rs
+++ b/library/core/src/ptr/non_null.rs
@@ -1,5 +1,4 @@
 use crate::cmp::Ordering;
-use crate::convert::From;
 use crate::fmt;
 use crate::hash;
 use crate::intrinsics;
@@ -1792,6 +1791,7 @@ impl<T: ?Sized> Eq for NonNull<T> {}
 #[stable(feature = "nonnull", since = "1.25.0")]
 impl<T: ?Sized> PartialEq for NonNull<T> {
     #[inline]
+    #[cfg_attr(not(bootstrap), allow(ambiguous_wide_pointer_comparisons))]
     fn eq(&self, other: &Self) -> bool {
         self.as_ptr() == other.as_ptr()
     }
diff --git a/library/core/src/ptr/unique.rs b/library/core/src/ptr/unique.rs
index bf8b86677d5..067f1541e31 100644
--- a/library/core/src/ptr/unique.rs
+++ b/library/core/src/ptr/unique.rs
@@ -1,4 +1,3 @@
-use crate::convert::From;
 use crate::fmt;
 use crate::marker::{PhantomData, Unsize};
 use crate::ops::{CoerceUnsized, DispatchFromDyn};
diff --git a/library/core/src/slice/iter.rs b/library/core/src/slice/iter.rs
index 5e229bf5244..fc54ea23770 100644
--- a/library/core/src/slice/iter.rs
+++ b/library/core/src/slice/iter.rs
@@ -10,7 +10,7 @@ use crate::intrinsics::assume;
 use crate::iter::{
     FusedIterator, TrustedLen, TrustedRandomAccess, TrustedRandomAccessNoCoerce, UncheckedIterator,
 };
-use crate::marker::{PhantomData, Send, Sized, Sync};
+use crate::marker::PhantomData;
 use crate::mem::{self, SizedTypeProperties};
 use crate::num::NonZeroUsize;
 use crate::ptr::{self, invalid, invalid_mut, NonNull};
diff --git a/library/core/src/slice/mod.rs b/library/core/src/slice/mod.rs
index dec9f194863..b14d9712794 100644
--- a/library/core/src/slice/mod.rs
+++ b/library/core/src/slice/mod.rs
@@ -9,16 +9,11 @@
 use crate::cmp::Ordering::{self, Equal, Greater, Less};
 use crate::fmt;
 use crate::intrinsics::exact_div;
-use crate::marker::Copy;
 use crate::mem::{self, SizedTypeProperties};
 use crate::num::NonZeroUsize;
-use crate::ops::{Bound, FnMut, OneSidedRange, Range, RangeBounds};
-use crate::option::Option;
-use crate::option::Option::{None, Some};
+use crate::ops::{Bound, OneSidedRange, Range, RangeBounds};
 use crate::panic::debug_assert_nounwind;
 use crate::ptr;
-use crate::result::Result;
-use crate::result::Result::{Err, Ok};
 use crate::simd::{self, Simd};
 use crate::slice;
 
diff --git a/library/core/src/task/poll.rs b/library/core/src/task/poll.rs
index 0a0f702f6fb..bfa1cf096e2 100644
--- a/library/core/src/task/poll.rs
+++ b/library/core/src/task/poll.rs
@@ -2,7 +2,6 @@
 
 use crate::convert;
 use crate::ops::{self, ControlFlow};
-use crate::result::Result;
 
 /// Indicates whether a value is available or if the current task has been
 /// scheduled to receive a wakeup instead.
diff --git a/library/core/src/task/wake.rs b/library/core/src/task/wake.rs
index 817e39942c0..1a11291e86b 100644
--- a/library/core/src/task/wake.rs
+++ b/library/core/src/task/wake.rs
@@ -1,7 +1,7 @@
 #![stable(feature = "futures_api", since = "1.36.0")]
 
 use crate::fmt;
-use crate::marker::{PhantomData, Unpin};
+use crate::marker::PhantomData;
 use crate::ptr;
 
 /// A `RawWaker` allows the implementor of a task executor to create a [`Waker`]
diff --git a/library/core/tests/array.rs b/library/core/tests/array.rs
index 81da75d32a1..3656eecca50 100644
--- a/library/core/tests/array.rs
+++ b/library/core/tests/array.rs
@@ -1,5 +1,4 @@
 use core::{array, assert_eq};
-use core::convert::TryFrom;
 use core::num::NonZeroUsize;
 use core::sync::atomic::{AtomicUsize, Ordering};
 
diff --git a/library/core/tests/cell.rs b/library/core/tests/cell.rs
index e084f867943..71b8eb29600 100644
--- a/library/core/tests/cell.rs
+++ b/library/core/tests/cell.rs
@@ -1,6 +1,4 @@
 use core::cell::*;
-use core::default::Default;
-use std::mem::drop;
 
 #[test]
 fn smoketest_unsafe_cell() {
diff --git a/library/core/tests/char.rs b/library/core/tests/char.rs
index 85ba51c9228..6422387e956 100644
--- a/library/core/tests/char.rs
+++ b/library/core/tests/char.rs
@@ -1,4 +1,3 @@
-use std::convert::TryFrom;
 use std::str::FromStr;
 use std::{char, str};
 
diff --git a/library/core/tests/hash/mod.rs b/library/core/tests/hash/mod.rs
index 5268f32c031..addc255de4a 100644
--- a/library/core/tests/hash/mod.rs
+++ b/library/core/tests/hash/mod.rs
@@ -1,6 +1,5 @@
 mod sip;
 
-use std::default::Default;
 use std::hash::{BuildHasher, Hash, Hasher};
 use std::ptr;
 use std::rc::Rc;
diff --git a/library/core/tests/iter/adapters/array_chunks.rs b/library/core/tests/iter/adapters/array_chunks.rs
index ef4a7e53bdd..fb19a519f63 100644
--- a/library/core/tests/iter/adapters/array_chunks.rs
+++ b/library/core/tests/iter/adapters/array_chunks.rs
@@ -1,5 +1,4 @@
-use core::cell::Cell;
-use core::iter::{self, Iterator};
+use core::iter::{self};
 
 use super::*;
 
diff --git a/library/core/tests/iter/mod.rs b/library/core/tests/iter/mod.rs
index 770b6f7601f..5b2769d0469 100644
--- a/library/core/tests/iter/mod.rs
+++ b/library/core/tests/iter/mod.rs
@@ -21,7 +21,6 @@ mod sources;
 mod traits;
 
 use core::cell::Cell;
-use core::convert::TryFrom;
 use core::iter::*;
 
 pub fn is_trusted_len<I: TrustedLen>(_: I) {}
diff --git a/library/core/tests/nonzero.rs b/library/core/tests/nonzero.rs
index 007f8442533..8873d26880c 100644
--- a/library/core/tests/nonzero.rs
+++ b/library/core/tests/nonzero.rs
@@ -1,9 +1,8 @@
-use core::convert::TryFrom;
 use core::num::{
     IntErrorKind, NonZeroI128, NonZeroI16, NonZeroI32, NonZeroI64, NonZeroI8, NonZeroIsize,
     NonZeroU128, NonZeroU16, NonZeroU32, NonZeroU64, NonZeroU8, NonZeroUsize,
 };
-use core::option::Option::{self, None, Some};
+use core::option::Option::None;
 use std::mem::size_of;
 
 #[test]
diff --git a/library/core/tests/num/mod.rs b/library/core/tests/num/mod.rs
index 3f3659ba837..863da9b18a2 100644
--- a/library/core/tests/num/mod.rs
+++ b/library/core/tests/num/mod.rs
@@ -1,11 +1,6 @@
-use core::cmp::PartialEq;
-use core::convert::{TryFrom, TryInto};
 use core::fmt::Debug;
-use core::marker::Copy;
 use core::num::{can_not_overflow, IntErrorKind, ParseIntError, TryFromIntError};
 use core::ops::{Add, Div, Mul, Rem, Sub};
-use core::option::Option;
-use core::option::Option::None;
 use core::str::FromStr;
 
 #[macro_use]
diff --git a/library/core/tests/option.rs b/library/core/tests/option.rs
index 5dc012bab4a..00a308b29d2 100644
--- a/library/core/tests/option.rs
+++ b/library/core/tests/option.rs
@@ -1,5 +1,4 @@
 use core::cell::Cell;
-use core::clone::Clone;
 use core::mem;
 use core::ops::DerefMut;
 use core::option::*;
diff --git a/library/core/tests/slice.rs b/library/core/tests/slice.rs
index 666452ead3f..33a30339856 100644
--- a/library/core/tests/slice.rs
+++ b/library/core/tests/slice.rs
@@ -2,7 +2,6 @@ use core::cell::Cell;
 use core::cmp::Ordering;
 use core::mem::MaybeUninit;
 use core::num::NonZeroUsize;
-use core::result::Result::{Err, Ok};
 use core::slice;
 
 #[test]
diff --git a/library/proc_macro/src/lib.rs b/library/proc_macro/src/lib.rs
index d3f1fba9369..7ebb6810b3e 100644
--- a/library/proc_macro/src/lib.rs
+++ b/library/proc_macro/src/lib.rs
@@ -925,13 +925,12 @@ impl !Sync for Punct {}
 pub enum Spacing {
     /// A `Punct` token can join with the following token to form a multi-character operator.
     ///
-    /// In token streams constructed using proc macro interfaces `Joint` punctuation tokens can be
-    /// followed by any other tokens. \
-    /// However, in token streams parsed from source code compiler will only set spacing to `Joint`
-    /// in the following cases:
-    /// - A `Punct` is immediately followed by another `Punct` without a whitespace. \
-    ///   E.g. `+` is `Joint` in `+=` and `++`.
-    /// - A single quote `'` is immediately followed by an identifier without a whitespace. \
+    /// In token streams constructed using proc macro interfaces, `Joint` punctuation tokens can be
+    /// followed by any other tokens. However, in token streams parsed from source code, the
+    /// compiler will only set spacing to `Joint` in the following cases.
+    /// - When a `Punct` is immediately followed by another `Punct` without a whitespace. E.g. `+`
+    ///   is `Joint` in `+=` and `++`.
+    /// - When a single quote `'` is immediately followed by an identifier without a whitespace.
     ///   E.g. `'` is `Joint` in `'lifetime`.
     ///
     /// This list may be extended in the future to enable more token combinations.
@@ -939,11 +938,10 @@ pub enum Spacing {
     Joint,
     /// A `Punct` token cannot join with the following token to form a multi-character operator.
     ///
-    /// `Alone` punctuation tokens can be followed by any other tokens. \
-    /// In token streams parsed from source code compiler will set spacing to `Alone` in all cases
-    /// not covered by the conditions for `Joint` above. \
-    /// E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`.
-    /// In particular, token not followed by anything  will also be marked as `Alone`.
+    /// `Alone` punctuation tokens can be followed by any other tokens. In token streams parsed
+    /// from source code, the compiler will set spacing to `Alone` in all cases not covered by the
+    /// conditions for `Joint` above. E.g. `+` is `Alone` in `+ =`, `+ident` and `+()`. In
+    /// particular, tokens not followed by anything will be marked as `Alone`.
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     Alone,
 }
@@ -978,8 +976,8 @@ impl Punct {
     }
 
     /// Returns the spacing of this punctuation character, indicating whether it can be potentially
-    /// combined into a multi-character operator with the following token (`Joint`), or the operator
-    /// has certainly ended (`Alone`).
+    /// combined into a multi-character operator with the following token (`Joint`), or whether the
+    /// operator has definitely ended (`Alone`).
     #[stable(feature = "proc_macro_lib2", since = "1.29.0")]
     pub fn spacing(&self) -> Spacing {
         if self.0.joint { Spacing::Joint } else { Spacing::Alone }
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index 7fcf2ee358c..9638f491987 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -96,7 +96,6 @@ use crate::panic::UnwindSafe;
 use crate::sync::atomic::{AtomicUsize, Ordering::Relaxed};
 use crate::sync::LazyLock;
 use crate::sys_common::backtrace::{lock, output_filename, set_image_base};
-use crate::vec::Vec;
 
 /// A captured OS thread stack backtrace.
 ///
diff --git a/library/std/src/backtrace/tests.rs b/library/std/src/backtrace/tests.rs
index 73543a3af54..174d62813bd 100644
--- a/library/std/src/backtrace/tests.rs
+++ b/library/std/src/backtrace/tests.rs
@@ -1,5 +1,5 @@
 use super::*;
-use crate::panic::{RefUnwindSafe, UnwindSafe};
+use crate::panic::RefUnwindSafe;
 
 fn generate_fake_frames() -> Vec<BacktraceFrame> {
     vec![
diff --git a/library/std/src/env/tests.rs b/library/std/src/env/tests.rs
index 55869229581..fc7aee29733 100644
--- a/library/std/src/env/tests.rs
+++ b/library/std/src/env/tests.rs
@@ -1,7 +1,5 @@
 use super::*;
 
-use crate::path::Path;
-
 #[test]
 #[cfg_attr(any(target_os = "emscripten", target_env = "sgx"), ignore)]
 fn test_self_exe_path() {
diff --git a/library/std/src/ffi/os_str/tests.rs b/library/std/src/ffi/os_str/tests.rs
index 2765398d3e6..60cde376d32 100644
--- a/library/std/src/ffi/os_str/tests.rs
+++ b/library/std/src/ffi/os_str/tests.rs
@@ -1,8 +1,4 @@
 use super::*;
-use crate::sys_common::{AsInner, IntoInner};
-
-use crate::rc::Rc;
-use crate::sync::Arc;
 
 #[test]
 fn test_os_string_with_capacity() {
diff --git a/library/std/src/io/error/repr_bitpacked.rs b/library/std/src/io/error/repr_bitpacked.rs
index 6e7366b3635..db175659770 100644
--- a/library/std/src/io/error/repr_bitpacked.rs
+++ b/library/std/src/io/error/repr_bitpacked.rs
@@ -103,7 +103,6 @@
 //! the time.
 
 use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
-use alloc::boxed::Box;
 use core::marker::PhantomData;
 use core::mem::{align_of, size_of};
 use core::ptr::{self, NonNull};
diff --git a/library/std/src/io/error/repr_unpacked.rs b/library/std/src/io/error/repr_unpacked.rs
index 093fde33757..dc8a95577c9 100644
--- a/library/std/src/io/error/repr_unpacked.rs
+++ b/library/std/src/io/error/repr_unpacked.rs
@@ -3,7 +3,6 @@
 //! would have no benefit.
 
 use super::{Custom, ErrorData, ErrorKind, RawOsError, SimpleMessage};
-use alloc::boxed::Box;
 
 type Inner = ErrorData<Box<Custom>>;
 
diff --git a/library/std/src/net/tcp/tests.rs b/library/std/src/net/tcp/tests.rs
index db367cfa0f7..b24b851a645 100644
--- a/library/std/src/net/tcp/tests.rs
+++ b/library/std/src/net/tcp/tests.rs
@@ -1,6 +1,6 @@
 use crate::fmt;
 use crate::io::prelude::*;
-use crate::io::{BorrowedBuf, ErrorKind, IoSlice, IoSliceMut};
+use crate::io::{BorrowedBuf, IoSlice, IoSliceMut};
 use crate::mem::MaybeUninit;
 use crate::net::test::{next_test_ip4, next_test_ip6};
 use crate::net::*;
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index 892fe2ba8ba..0cf99366452 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -1,4 +1,3 @@
-use crate::io::ErrorKind;
 use crate::net::test::{next_test_ip4, next_test_ip6};
 use crate::net::*;
 use crate::sync::mpsc::channel;
diff --git a/library/std/src/path/tests.rs b/library/std/src/path/tests.rs
index dbc0f7d9df3..fde6ed4f0c0 100644
--- a/library/std/src/path/tests.rs
+++ b/library/std/src/path/tests.rs
@@ -1,9 +1,7 @@
 use super::*;
 
 use crate::collections::{BTreeSet, HashSet};
-use crate::hash::{DefaultHasher, Hasher};
-use crate::rc::Rc;
-use crate::sync::Arc;
+use crate::hash::DefaultHasher;
 use core::hint::black_box;
 
 #[allow(unknown_lints, unused_macro_rules)]
diff --git a/library/std/src/sync/mpsc/sync_tests.rs b/library/std/src/sync/mpsc/sync_tests.rs
index 632709fd98d..945de280f40 100644
--- a/library/std/src/sync/mpsc/sync_tests.rs
+++ b/library/std/src/sync/mpsc/sync_tests.rs
@@ -3,7 +3,6 @@ use crate::env;
 use crate::rc::Rc;
 use crate::sync::mpmc::SendTimeoutError;
 use crate::thread;
-use crate::time::Duration;
 
 pub fn stress_factor() -> usize {
     match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/mpsc/tests.rs b/library/std/src/sync/mpsc/tests.rs
index 1e52a4a705c..ac1a804cf9c 100644
--- a/library/std/src/sync/mpsc/tests.rs
+++ b/library/std/src/sync/mpsc/tests.rs
@@ -1,7 +1,6 @@
 use super::*;
 use crate::env;
 use crate::thread;
-use crate::time::{Duration, Instant};
 
 pub fn stress_factor() -> usize {
     match env::var("RUST_TEST_STRESS") {
diff --git a/library/std/src/sync/mutex.rs b/library/std/src/sync/mutex.rs
index b4ae6b7e07e..0c001d7c258 100644
--- a/library/std/src/sync/mutex.rs
+++ b/library/std/src/sync/mutex.rs
@@ -146,7 +146,7 @@ use crate::sys::locks as sys;
 /// let result = data.iter().fold(0, |acc, x| acc + x * 2);
 /// data.push(result);
 /// // We drop the `data` explicitly because it's not necessary anymore and the
-/// // thread still has work to do. This allow other threads to start working on
+/// // thread still has work to do. This allows other threads to start working on
 /// // the data immediately, without waiting for the rest of the unrelated work
 /// // to be done here.
 /// //
diff --git a/library/std/src/sys_common/thread.rs b/library/std/src/sys_common/thread.rs
index 76466b2b37b..8f5624bbce9 100644
--- a/library/std/src/sys_common/thread.rs
+++ b/library/std/src/sys_common/thread.rs
@@ -8,7 +8,7 @@ pub fn min_stack() -> usize {
         0 => {}
         n => return n - 1,
     }
-    let amt = env::var("RUST_MIN_STACK").ok().and_then(|s| s.parse().ok());
+    let amt = env::var_os("RUST_MIN_STACK").and_then(|s| s.to_str().and_then(|s| s.parse().ok()));
     let amt = amt.unwrap_or(imp::DEFAULT_MIN_STACK_SIZE);
 
     // 0 is our sentinel value, so ensure that we'll never see 0 after
diff --git a/library/std/src/sys_common/wtf8/tests.rs b/library/std/src/sys_common/wtf8/tests.rs
index a07bbe6d7e4..28a426648e5 100644
--- a/library/std/src/sys_common/wtf8/tests.rs
+++ b/library/std/src/sys_common/wtf8/tests.rs
@@ -1,5 +1,4 @@
 use super::*;
-use crate::borrow::Cow;
 
 #[test]
 fn code_point_from_u32() {
diff --git a/library/test/src/term/terminfo/parm/tests.rs b/library/test/src/term/terminfo/parm/tests.rs
index c738f3ba04f..e785d84f3fd 100644
--- a/library/test/src/term/terminfo/parm/tests.rs
+++ b/library/test/src/term/terminfo/parm/tests.rs
@@ -1,7 +1,5 @@
 use super::*;
 
-use std::result::Result::Ok;
-
 #[test]
 fn test_basic_setabf() {
     let s = b"\\E[48;5;%p1%dm";
diff --git a/library/test/src/tests.rs b/library/test/src/tests.rs
index 4ef18b14f4c..43a906ad298 100644
--- a/library/test/src/tests.rs
+++ b/library/test/src/tests.rs
@@ -1,34 +1,17 @@
 use super::*;
 
 use crate::{
-    bench::Bencher,
     console::OutputLocation,
     formatters::PrettyFormatter,
-    options::OutputFormat,
     test::{
-        filter_tests,
         parse_opts,
-        run_test,
-        DynTestFn,
-        DynTestName,
         MetricMap,
-        RunIgnored,
-        RunStrategy,
-        ShouldPanic,
-        StaticTestName,
-        TestDesc,
-        TestDescAndFn,
-        TestOpts,
-        TrIgnored,
-        TrOk,
         // FIXME (introduced by #65251)
         // ShouldPanic, StaticTestName, TestDesc, TestDescAndFn, TestOpts, TestTimeOptions,
         // TestType, TrFailedMsg, TrIgnored, TrOk,
     },
     time::{TestTimeOptions, TimeThreshold},
 };
-use std::sync::mpsc::channel;
-use std::time::Duration;
 
 impl TestOpts {
     fn new() -> TestOpts {
diff --git a/src/bootstrap/src/bin/main.rs b/src/bootstrap/src/bin/main.rs
index b3c427721ea..32f6a3f80d0 100644
--- a/src/bootstrap/src/bin/main.rs
+++ b/src/bootstrap/src/bin/main.rs
@@ -10,8 +10,9 @@ use std::io::Write;
 #[cfg(all(any(unix, windows), not(target_os = "solaris")))]
 use std::process;
 use std::{
-    env, fs,
-    io::{self, IsTerminal},
+    env,
+    fs::{self, OpenOptions},
+    io::{self, BufRead, BufReader, IsTerminal},
 };
 
 use bootstrap::{
@@ -79,6 +80,9 @@ fn main() {
     }
 
     let pre_commit = config.src.join(".git").join("hooks").join("pre-commit");
+    let dump_bootstrap_shims = config.dump_bootstrap_shims;
+    let out_dir = config.out.clone();
+
     Build::new(config).build();
 
     if suggest_setup {
@@ -107,6 +111,29 @@ fn main() {
     if suggest_setup || changelog_suggestion.is_some() {
         println!("NOTE: this message was printed twice to make it more likely to be seen");
     }
+
+    if dump_bootstrap_shims {
+        let dump_dir = out_dir.join("bootstrap-shims-dump");
+        assert!(dump_dir.exists());
+
+        for entry in walkdir::WalkDir::new(&dump_dir) {
+            let entry = t!(entry);
+
+            if !entry.file_type().is_file() {
+                continue;
+            }
+
+            let file = t!(fs::File::open(&entry.path()));
+
+            // To ensure deterministic results we must sort the dump lines.
+            // This is necessary because the order of rustc invocations different
+            // almost all the time.
+            let mut lines: Vec<String> = t!(BufReader::new(&file).lines().collect());
+            lines.sort_by_key(|t| t.to_lowercase());
+            let mut file = t!(OpenOptions::new().write(true).truncate(true).open(&entry.path()));
+            t!(file.write_all(lines.join("\n").as_bytes()));
+        }
+    }
 }
 
 fn check_version(config: &Config) -> Option<String> {
diff --git a/src/bootstrap/src/bin/rustc.rs b/src/bootstrap/src/bin/rustc.rs
index af66cb3ffd7..18136635c42 100644
--- a/src/bootstrap/src/bin/rustc.rs
+++ b/src/bootstrap/src/bin/rustc.rs
@@ -32,9 +32,7 @@ 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());
 
-    // We don't use the stage in this shim, but let's parse it to make sure that we're invoked
-    // by bootstrap, or that we provide a helpful error message if not.
-    bin_helpers::parse_rustc_stage();
+    let stage = bin_helpers::parse_rustc_stage();
     let verbose = bin_helpers::parse_rustc_verbose();
 
     // Detect whether or not we're a build script depending on whether --target
@@ -214,6 +212,8 @@ fn main() {
         }
     }
 
+    bin_helpers::maybe_dump(format!("stage{stage}-rustc"), &cmd);
+
     let start = Instant::now();
     let (child, status) = {
         let errmsg = format!("\nFailed to run:\n{cmd:?}\n-------------");
diff --git a/src/bootstrap/src/bin/rustdoc.rs b/src/bootstrap/src/bin/rustdoc.rs
index 90bd822699c..b4d1415189c 100644
--- a/src/bootstrap/src/bin/rustdoc.rs
+++ b/src/bootstrap/src/bin/rustdoc.rs
@@ -62,6 +62,8 @@ fn main() {
     cmd.arg("-Zunstable-options");
     cmd.arg("--check-cfg=cfg(bootstrap)");
 
+    bin_helpers::maybe_dump(format!("stage{stage}-rustdoc"), &cmd);
+
     if verbose > 1 {
         eprintln!(
             "rustdoc command: {:?}={:?} {:?}",
diff --git a/src/bootstrap/src/core/build_steps/clean.rs b/src/bootstrap/src/core/build_steps/clean.rs
index a3fb330ddfb..6372db96afb 100644
--- a/src/bootstrap/src/core/build_steps/clean.rs
+++ b/src/bootstrap/src/core/build_steps/clean.rs
@@ -146,6 +146,7 @@ fn clean_default(build: &Build) {
     rm_rf(&build.out.join("tmp"));
     rm_rf(&build.out.join("dist"));
     rm_rf(&build.out.join("bootstrap").join(".last-warned-change-id"));
+    rm_rf(&build.out.join("bootstrap-shims-dump"));
     rm_rf(&build.out.join("rustfmt.stamp"));
 
     for host in &build.hosts {
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 1ab488ef656..11e789a996a 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -870,7 +870,7 @@ impl Step for Rustc {
         // is already on by default in MSVC optimized builds, which is interpreted as --icf=all:
         // https://github.com/llvm/llvm-project/blob/3329cec2f79185bafd678f310fafadba2a8c76d2/lld/COFF/Driver.cpp#L1746
         // https://github.com/rust-lang/rust/blob/f22819bcce4abaff7d1246a56eec493418f9f4ee/compiler/rustc_codegen_ssa/src/back/linker.rs#L827
-        if builder.config.use_lld && !compiler.host.contains("msvc") {
+        if builder.config.lld_mode.is_used() && !compiler.host.is_msvc() {
             cargo.rustflag("-Clink-args=-Wl,--icf=all");
         }
 
@@ -1089,7 +1089,7 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
     // found. This is to avoid the linker errors about undefined references to
     // `__llvm_profile_instrument_memop` when linking `rustc_driver`.
     let mut llvm_linker_flags = String::new();
-    if builder.config.llvm_profile_generate && target.contains("msvc") {
+    if builder.config.llvm_profile_generate && target.is_msvc() {
         if let Some(ref clang_cl_path) = builder.config.llvm_clang_cl {
             // Add clang's runtime library directory to the search path
             let clang_rt_dir = get_clang_cl_resource_dir(clang_cl_path);
@@ -1114,7 +1114,7 @@ fn rustc_llvm_env(builder: &Builder<'_>, cargo: &mut Cargo, target: TargetSelect
     // not for MSVC or macOS
     if builder.config.llvm_static_stdcpp
         && !target.contains("freebsd")
-        && !target.contains("msvc")
+        && !target.is_msvc()
         && !target.contains("apple")
         && !target.contains("solaris")
     {
diff --git a/src/bootstrap/src/core/build_steps/llvm.rs b/src/bootstrap/src/core/build_steps/llvm.rs
index 7c119b0273b..8de208cd09c 100644
--- a/src/bootstrap/src/core/build_steps/llvm.rs
+++ b/src/bootstrap/src/core/build_steps/llvm.rs
@@ -98,7 +98,7 @@ pub fn prebuilt_llvm_config(
     let out_dir = builder.llvm_out(target);
 
     let mut llvm_config_ret_dir = builder.llvm_out(builder.config.build);
-    if !builder.config.build.contains("msvc") || builder.ninja() {
+    if !builder.config.build.is_msvc() || builder.ninja() {
         llvm_config_ret_dir.push("build");
     }
     llvm_config_ret_dir.push("bin");
@@ -411,7 +411,7 @@ impl Step for Llvm {
             ldflags.shared.push(" -latomic");
         }
 
-        if target.contains("msvc") {
+        if target.is_msvc() {
             cfg.define("LLVM_USE_CRT_DEBUG", "MT");
             cfg.define("LLVM_USE_CRT_RELEASE", "MT");
             cfg.define("LLVM_USE_CRT_RELWITHDEBINFO", "MT");
@@ -644,7 +644,7 @@ fn configure_cmake(
     }
 
     let sanitize_cc = |cc: &Path| {
-        if target.contains("msvc") {
+        if target.is_msvc() {
             OsString::from(cc.to_str().unwrap().replace("\\", "/"))
         } else {
             cc.as_os_str().to_owned()
@@ -654,7 +654,7 @@ fn configure_cmake(
     // MSVC with CMake uses msbuild by default which doesn't respect these
     // vars that we'd otherwise configure. In that case we just skip this
     // entirely.
-    if target.contains("msvc") && !builder.ninja() {
+    if target.is_msvc() && !builder.ninja() {
         return;
     }
 
@@ -664,7 +664,7 @@ fn configure_cmake(
     };
 
     // Handle msvc + ninja + ccache specially (this is what the bots use)
-    if target.contains("msvc") && builder.ninja() && builder.config.ccache.is_some() {
+    if target.is_msvc() && builder.ninja() && builder.config.ccache.is_some() {
         let mut wrap_cc = env::current_exe().expect("failed to get cwd");
         wrap_cc.set_file_name("sccache-plus-cl.exe");
 
@@ -768,7 +768,7 @@ fn configure_cmake(
     // For distribution we want the LLVM tools to be *statically* linked to libstdc++.
     // We also do this if the user explicitly requested static libstdc++.
     if builder.config.llvm_static_stdcpp
-        && !target.contains("msvc")
+        && !target.is_msvc()
         && !target.contains("netbsd")
         && !target.contains("solaris")
     {
@@ -874,7 +874,7 @@ impl Step for Lld {
         // when doing PGO on CI, cmake or clang-cl don't automatically link clang's
         // profiler runtime in. In that case, we need to manually ask cmake to do it, to avoid
         // linking errors, much like LLVM's cmake setup does in that situation.
-        if builder.config.llvm_profile_generate && target.contains("msvc") {
+        if builder.config.llvm_profile_generate && target.is_msvc() {
             if let Some(clang_cl_path) = builder.config.llvm_clang_cl.as_ref() {
                 // Find clang's runtime library directory and push that as a search path to the
                 // cmake linker flags.
diff --git a/src/bootstrap/src/core/build_steps/test.rs b/src/bootstrap/src/core/build_steps/test.rs
index 77a4f2c4cb2..d0f36f99342 100644
--- a/src/bootstrap/src/core/build_steps/test.rs
+++ b/src/bootstrap/src/core/build_steps/test.rs
@@ -29,8 +29,9 @@ use crate::utils;
 use crate::utils::cache::{Interned, INTERNER};
 use crate::utils::exec::BootstrapCommand;
 use crate::utils::helpers::{
-    self, add_link_lib_path, add_rustdoc_cargo_lld_flags, add_rustdoc_lld_flags, dylib_path,
-    dylib_path_var, output, t, target_supports_cranelift_backend, up_to_date, LldThreads,
+    self, add_link_lib_path, add_rustdoc_cargo_linker_args, dylib_path, dylib_path_var,
+    linker_args, linker_flags, output, t, target_supports_cranelift_backend, up_to_date,
+    LldThreads,
 };
 use crate::utils::render_tests::{add_flags_and_try_run_tests, try_run_tests};
 use crate::{envify, CLang, DocTests, GitRepo, Mode};
@@ -277,7 +278,7 @@ impl Step for Cargotest {
             .args(builder.config.test_args())
             .env("RUSTC", builder.rustc(compiler))
             .env("RUSTDOC", builder.rustdoc(compiler));
-        add_rustdoc_cargo_lld_flags(&mut cmd, builder, compiler.host, LldThreads::No);
+        add_rustdoc_cargo_linker_args(&mut cmd, builder, compiler.host, LldThreads::No);
         builder.run_delaying_failure(cmd);
     }
 }
@@ -863,7 +864,7 @@ impl Step for RustdocTheme {
             .env("CFG_RELEASE_CHANNEL", &builder.config.channel)
             .env("RUSTDOC_REAL", builder.rustdoc(self.compiler))
             .env("RUSTC_BOOTSTRAP", "1");
-        add_rustdoc_lld_flags(&mut cmd, builder, self.compiler.host, LldThreads::No);
+        cmd.args(linker_args(builder, self.compiler.host, LldThreads::No));
 
         builder.run_delaying_failure(&mut cmd);
     }
@@ -1039,7 +1040,7 @@ impl Step for RustdocGUI {
         cmd.env("RUSTDOC", builder.rustdoc(self.compiler))
             .env("RUSTC", builder.rustc(self.compiler));
 
-        add_rustdoc_cargo_lld_flags(&mut cmd, builder, self.compiler.host, LldThreads::No);
+        add_rustdoc_cargo_linker_args(&mut cmd, builder, self.compiler.host, LldThreads::No);
 
         for path in &builder.paths {
             if let Some(p) = helpers::is_valid_test_suite_arg(path, "tests/rustdoc-gui", builder) {
@@ -1746,14 +1747,14 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
 
         let mut hostflags = flags.clone();
         hostflags.push(format!("-Lnative={}", builder.test_helpers_out(compiler.host).display()));
-        hostflags.extend(builder.lld_flags(compiler.host));
+        hostflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
         for flag in hostflags {
             cmd.arg("--host-rustcflags").arg(flag);
         }
 
         let mut targetflags = flags;
         targetflags.push(format!("-Lnative={}", builder.test_helpers_out(target).display()));
-        targetflags.extend(builder.lld_flags(target));
+        targetflags.extend(linker_flags(builder, compiler.host, LldThreads::No));
         for flag in targetflags {
             cmd.arg("--target-rustcflags").arg(flag);
         }
@@ -1931,7 +1932,7 @@ NOTE: if you're sure you want to do this, please open an issue as to why. In the
         //
         // Note that if we encounter `PATH` we make sure to append to our own `PATH`
         // rather than stomp over it.
-        if !builder.config.dry_run() && target.contains("msvc") {
+        if !builder.config.dry_run() && target.is_msvc() {
             for &(ref k, ref v) in builder.cc.borrow()[&target].env() {
                 if k != "PATH" {
                     cmd.env(k, v);
@@ -3070,7 +3071,7 @@ impl Step for TestHelpers {
         // We may have found various cross-compilers a little differently due to our
         // extra configuration, so inform cc of these compilers. Note, though, that
         // on MSVC we still need cc's detection of env vars (ugh).
-        if !target.contains("msvc") {
+        if !target.is_msvc() {
             if let Some(ar) = builder.ar(target) {
                 cfg.archiver(ar);
             }
diff --git a/src/bootstrap/src/core/build_steps/tool.rs b/src/bootstrap/src/core/build_steps/tool.rs
index 37cd96e7c63..9942f00a056 100644
--- a/src/bootstrap/src/core/build_steps/tool.rs
+++ b/src/bootstrap/src/core/build_steps/tool.rs
@@ -833,7 +833,7 @@ impl<'a> Builder<'a> {
         // On MSVC a tool may invoke a C compiler (e.g., compiletest in run-make
         // mode) and that C compiler may need some extra PATH modification. Do
         // so here.
-        if compiler.host.contains("msvc") {
+        if compiler.host.is_msvc() {
             let curpaths = env::var_os("PATH").unwrap_or_default();
             let curpaths = env::split_paths(&curpaths).collect::<Vec<_>>();
             for &(ref k, ref v) in self.cc.borrow()[&compiler.host].env() {
diff --git a/src/bootstrap/src/core/builder.rs b/src/bootstrap/src/core/builder.rs
index d018be5f8e1..054c3ab14c0 100644
--- a/src/bootstrap/src/core/builder.rs
+++ b/src/bootstrap/src/core/builder.rs
@@ -18,12 +18,12 @@ use crate::core::build_steps::tool::{self, SourceType};
 use crate::core::build_steps::{check, clean, compile, dist, doc, install, run, setup, test};
 use crate::core::config::flags::{Color, Subcommand};
 use crate::core::config::{DryRun, SplitDebuginfo, TargetSelection};
+use crate::prepare_behaviour_dump_dir;
 use crate::utils::cache::{Cache, Interned, INTERNER};
-use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, add_rustdoc_lld_flags, exe};
-use crate::utils::helpers::{libdir, output, t, LldThreads};
-use crate::Crate;
+use crate::utils::helpers::{self, add_dylib_path, add_link_lib_path, exe, linker_args};
+use crate::utils::helpers::{libdir, linker_flags, output, t, LldThreads};
 use crate::EXTRA_CHECK_CFGS;
-use crate::{Build, CLang, DocTests, GitRepo, Mode};
+use crate::{Build, CLang, Crate, DocTests, GitRepo, Mode};
 
 pub use crate::Compiler;
 
@@ -1174,7 +1174,7 @@ impl<'a> Builder<'a> {
         cmd.env_remove("MAKEFLAGS");
         cmd.env_remove("MFLAGS");
 
-        add_rustdoc_lld_flags(&mut cmd, self, compiler.host, LldThreads::Yes);
+        cmd.args(linker_args(self, compiler.host, LldThreads::Yes));
         cmd
     }
 
@@ -1673,23 +1673,22 @@ impl<'a> Builder<'a> {
             rustflags.arg(&format!("-Zstack-protector={stack_protector}"));
         }
 
-        if let Some(host_linker) = self.linker(compiler.host) {
-            hostflags.arg(format!("-Clinker={}", host_linker.display()));
-        }
-        if self.is_fuse_ld_lld(compiler.host) {
-            hostflags.arg("-Clink-args=-fuse-ld=lld");
+        for arg in linker_args(self, compiler.host, LldThreads::Yes) {
+            hostflags.arg(&arg);
         }
 
         if let Some(target_linker) = self.linker(target) {
             let target = crate::envify(&target.triple);
             cargo.env(&format!("CARGO_TARGET_{target}_LINKER"), target_linker);
         }
-        if self.is_fuse_ld_lld(target) {
-            rustflags.arg("-Clink-args=-fuse-ld=lld");
+        // We want to set -Clinker using Cargo, therefore we only call `linker_flags` and not
+        // `linker_args` here.
+        for flag in linker_flags(self, target, LldThreads::Yes) {
+            rustflags.arg(&flag);
+        }
+        for arg in linker_args(self, target, LldThreads::Yes) {
+            rustdocflags.arg(&arg);
         }
-        self.lld_flags(target).for_each(|flag| {
-            rustdocflags.arg(&flag);
-        });
 
         if !(["build", "check", "clippy", "fix", "rustc"].contains(&cmd)) && want_rustdoc {
             cargo.env("RUSTDOC_LIBDIR", self.rustc_libdir(compiler));
@@ -1729,8 +1728,7 @@ impl<'a> Builder<'a> {
 
         let split_debuginfo_is_stable = target.contains("linux")
             || target.contains("apple")
-            || (target.contains("msvc")
-                && self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
+            || (target.is_msvc() && self.config.rust_split_debuginfo == SplitDebuginfo::Packed)
             || (target.contains("windows")
                 && self.config.rust_split_debuginfo == SplitDebuginfo::Off);
 
@@ -1790,6 +1788,16 @@ impl<'a> Builder<'a> {
 
         // Enable usage of unstable features
         cargo.env("RUSTC_BOOTSTRAP", "1");
+
+        if self.config.dump_bootstrap_shims {
+            prepare_behaviour_dump_dir(&self.build);
+
+            cargo
+                .env("DUMP_BOOTSTRAP_SHIMS", self.build.out.join("bootstrap-shims-dump"))
+                .env("BUILD_OUT", &self.build.out)
+                .env("CARGO_HOME", t!(home::cargo_home()));
+        };
+
         self.add_rust_test_threads(&mut cargo);
 
         // Almost all of the crates that we compile as part of the bootstrap may
@@ -1909,7 +1917,7 @@ impl<'a> Builder<'a> {
         // the options through environment variables that are fetched and understood by both.
         //
         // FIXME: the guard against msvc shouldn't need to be here
-        if target.contains("msvc") {
+        if target.is_msvc() {
             if let Some(ref cl) = self.config.llvm_clang_cl {
                 cargo.env("CC", cl).env("CXX", cl);
             }
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index b5291817e79..c3db5641ea4 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -105,6 +105,39 @@ impl Display for DebuginfoLevel {
     }
 }
 
+/// LLD in bootstrap works like this:
+/// - Self-contained lld: use `rust-lld` from the compiler's sysroot
+/// - External: use an external `lld` binary
+///
+/// It is configured depending on the target:
+/// 1) Everything except MSVC
+/// - Self-contained: `-Clinker-flavor=gnu-lld-cc -Clink-self-contained=+linker`
+/// - External: `-Clinker-flavor=gnu-lld-cc`
+/// 2) MSVC
+/// - Self-contained: `-Clinker=<path to rust-lld>`
+/// - External: `-Clinker=lld`
+#[derive(Default, Copy, Clone)]
+pub enum LldMode {
+    /// Do not use LLD
+    #[default]
+    Unused,
+    /// Use `rust-lld` from the compiler's sysroot
+    SelfContained,
+    /// Use an externally provided `lld` binary.
+    /// Note that the linker name cannot be overridden, the binary has to be named `lld` and it has
+    /// to be in $PATH.
+    External,
+}
+
+impl LldMode {
+    pub fn is_used(&self) -> bool {
+        match self {
+            LldMode::SelfContained | LldMode::External => true,
+            LldMode::Unused => false,
+        }
+    }
+}
+
 /// Global configuration for the entire build and/or bootstrap.
 ///
 /// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
@@ -160,6 +193,7 @@ pub struct Config {
     pub cmd: Subcommand,
     pub incremental: bool,
     pub dry_run: DryRun,
+    pub dump_bootstrap_shims: bool,
     /// Arguments appearing after `--` to be forwarded to tools,
     /// e.g. `--fix-broken` or test arguments.
     pub free_args: Vec<String>,
@@ -199,7 +233,7 @@ pub struct Config {
     pub llvm_from_ci: bool,
     pub llvm_build_config: HashMap<String, String>,
 
-    pub use_lld: bool,
+    pub lld_mode: LldMode,
     pub lld_enabled: bool,
     pub llvm_tools_enabled: bool,
 
@@ -489,6 +523,10 @@ impl TargetSelection {
     pub fn is_synthetic(&self) -> bool {
         self.synthetic
     }
+
+    pub fn is_msvc(&self) -> bool {
+        self.contains("msvc")
+    }
 }
 
 impl fmt::Display for TargetSelection {
@@ -857,7 +895,6 @@ define_config! {
 define_config! {
     struct Dist {
         sign_folder: Option<String> = "sign-folder",
-        gpg_password_file: Option<String> = "gpg-password-file",
         upload_addr: Option<String> = "upload-addr",
         src_tarball: Option<bool> = "src-tarball",
         missing_tools: Option<bool> = "missing-tools",
@@ -977,6 +1014,44 @@ enum StringOrInt<'a> {
     String(&'a str),
     Int(i64),
 }
+
+impl<'de> Deserialize<'de> for LldMode {
+    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
+    where
+        D: Deserializer<'de>,
+    {
+        struct LldModeVisitor;
+
+        impl<'de> serde::de::Visitor<'de> for LldModeVisitor {
+            type Value = LldMode;
+
+            fn expecting(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
+                formatter.write_str("one of true, 'self-contained' or 'external'")
+            }
+
+            fn visit_bool<E>(self, v: bool) -> Result<Self::Value, E>
+            where
+                E: serde::de::Error,
+            {
+                Ok(if v { LldMode::External } else { LldMode::Unused })
+            }
+
+            fn visit_str<E>(self, v: &str) -> Result<Self::Value, E>
+            where
+                E: serde::de::Error,
+            {
+                match v {
+                    "external" => Ok(LldMode::External),
+                    "self-contained" => Ok(LldMode::SelfContained),
+                    _ => Err(E::custom("unknown mode {v}")),
+                }
+            }
+        }
+
+        deserializer.deserialize_any(LldModeVisitor)
+    }
+}
+
 define_config! {
     /// TOML representation of how the Rust build is configured.
     struct Rust {
@@ -995,7 +1070,6 @@ define_config! {
         debuginfo_level_tools: Option<DebuginfoLevel> = "debuginfo-level-tools",
         debuginfo_level_tests: Option<DebuginfoLevel> = "debuginfo-level-tests",
         split_debuginfo: Option<String> = "split-debuginfo",
-        run_dsymutil: Option<bool> = "run-dsymutil",
         backtrace: Option<bool> = "backtrace",
         incremental: Option<bool> = "incremental",
         parallel_compiler: Option<bool> = "parallel-compiler",
@@ -1014,7 +1088,7 @@ define_config! {
         save_toolstates: Option<String> = "save-toolstates",
         codegen_backends: Option<Vec<String>> = "codegen-backends",
         lld: Option<bool> = "lld",
-        use_lld: Option<bool> = "use-lld",
+        lld_mode: Option<LldMode> = "use-lld",
         llvm_tools: Option<bool> = "llvm-tools",
         deny_warnings: Option<bool> = "deny-warnings",
         backtrace_on_ice: Option<bool> = "backtrace-on-ice",
@@ -1137,6 +1211,7 @@ impl Config {
         config.cmd = flags.cmd;
         config.incremental = flags.incremental;
         config.dry_run = if flags.dry_run { DryRun::UserSelected } else { DryRun::Disabled };
+        config.dump_bootstrap_shims = flags.dump_bootstrap_shims;
         config.keep_stage = flags.keep_stage;
         config.keep_stage_std = flags.keep_stage_std;
         config.color = flags.color;
@@ -1274,12 +1349,56 @@ impl Config {
         config.changelog_seen = toml.changelog_seen;
         config.change_id = toml.change_id;
 
-        let build = toml.build.unwrap_or_default();
-        if let Some(file_build) = build.build {
+        let Build {
+            build,
+            host,
+            target,
+            build_dir,
+            cargo,
+            rustc,
+            rustfmt,
+            docs,
+            compiler_docs,
+            library_docs_private_items,
+            docs_minification,
+            submodules,
+            gdb,
+            nodejs,
+            npm,
+            python,
+            reuse,
+            locked_deps,
+            vendor,
+            full_bootstrap,
+            extended,
+            tools,
+            verbose,
+            sanitizers,
+            profiler,
+            cargo_native_static,
+            low_priority,
+            configure_args,
+            local_rebuild,
+            print_step_timings,
+            print_step_rusage,
+            check_stage,
+            doc_stage,
+            build_stage,
+            test_stage,
+            install_stage,
+            dist_stage,
+            bench_stage,
+            patch_binaries_for_nix,
+            // This field is only used by bootstrap.py
+            metrics: _,
+            android_ndk,
+        } = toml.build.unwrap_or_default();
+
+        if let Some(file_build) = build {
             config.build = TargetSelection::from_user(&file_build);
         };
 
-        set(&mut config.out, flags.build_dir.or_else(|| build.build_dir.map(PathBuf::from)));
+        set(&mut config.out, flags.build_dir.or_else(|| build_dir.map(PathBuf::from)));
         // NOTE: Bootstrap spawns various commands with different working directories.
         // To avoid writing to random places on the file system, `config.out` needs to be an absolute path.
         if !config.out.is_absolute() {
@@ -1287,7 +1406,7 @@ impl Config {
             config.out = crate::utils::helpers::absolute(&config.out);
         }
 
-        config.initial_rustc = if let Some(rustc) = build.rustc {
+        config.initial_rustc = if let Some(rustc) = rustc {
             if !flags.skip_stage0_validation {
                 config.check_build_rustc_version(&rustc);
             }
@@ -1297,8 +1416,7 @@ impl Config {
             config.out.join(config.build.triple).join("stage0/bin/rustc")
         };
 
-        config.initial_cargo = build
-            .cargo
+        config.initial_cargo = cargo
             .map(|cargo| {
                 t!(PathBuf::from(cargo).canonicalize(), "`initial_cargo` not found on disk")
             })
@@ -1313,14 +1431,14 @@ impl Config {
 
         config.hosts = if let Some(TargetSelectionList(arg_host)) = flags.host {
             arg_host
-        } else if let Some(file_host) = build.host {
+        } else if let Some(file_host) = host {
             file_host.iter().map(|h| TargetSelection::from_user(h)).collect()
         } else {
             vec![config.build]
         };
         config.targets = if let Some(TargetSelectionList(arg_target)) = flags.target {
             arg_target
-        } else if let Some(file_target) = build.target {
+        } else if let Some(file_target) = target {
             file_target.iter().map(|h| TargetSelection::from_user(h)).collect()
         } else {
             // If target is *not* configured, then default to the host
@@ -1328,43 +1446,44 @@ impl Config {
             config.hosts.clone()
         };
 
-        config.nodejs = build.nodejs.map(PathBuf::from);
-        config.npm = build.npm.map(PathBuf::from);
-        config.gdb = build.gdb.map(PathBuf::from);
-        config.python = build.python.map(PathBuf::from);
-        config.reuse = build.reuse.map(PathBuf::from);
-        config.submodules = build.submodules;
-        config.android_ndk = build.android_ndk;
-        set(&mut config.low_priority, build.low_priority);
-        set(&mut config.compiler_docs, build.compiler_docs);
-        set(&mut config.library_docs_private_items, build.library_docs_private_items);
-        set(&mut config.docs_minification, build.docs_minification);
-        set(&mut config.docs, build.docs);
-        set(&mut config.locked_deps, build.locked_deps);
-        set(&mut config.vendor, build.vendor);
-        set(&mut config.full_bootstrap, build.full_bootstrap);
-        set(&mut config.extended, build.extended);
-        config.tools = build.tools;
-        set(&mut config.verbose, build.verbose);
-        set(&mut config.sanitizers, build.sanitizers);
-        set(&mut config.profiler, build.profiler);
-        set(&mut config.cargo_native_static, build.cargo_native_static);
-        set(&mut config.configure_args, build.configure_args);
-        set(&mut config.local_rebuild, build.local_rebuild);
-        set(&mut config.print_step_timings, build.print_step_timings);
-        set(&mut config.print_step_rusage, build.print_step_rusage);
-        config.patch_binaries_for_nix = build.patch_binaries_for_nix;
+        config.nodejs = nodejs.map(PathBuf::from);
+        config.npm = npm.map(PathBuf::from);
+        config.gdb = gdb.map(PathBuf::from);
+        config.python = python.map(PathBuf::from);
+        config.reuse = reuse.map(PathBuf::from);
+        config.submodules = submodules;
+        config.android_ndk = android_ndk;
+        set(&mut config.low_priority, low_priority);
+        set(&mut config.compiler_docs, compiler_docs);
+        set(&mut config.library_docs_private_items, library_docs_private_items);
+        set(&mut config.docs_minification, docs_minification);
+        set(&mut config.docs, docs);
+        set(&mut config.locked_deps, locked_deps);
+        set(&mut config.vendor, vendor);
+        set(&mut config.full_bootstrap, full_bootstrap);
+        set(&mut config.extended, extended);
+        config.tools = tools;
+        set(&mut config.verbose, verbose);
+        set(&mut config.sanitizers, sanitizers);
+        set(&mut config.profiler, profiler);
+        set(&mut config.cargo_native_static, cargo_native_static);
+        set(&mut config.configure_args, configure_args);
+        set(&mut config.local_rebuild, local_rebuild);
+        set(&mut config.print_step_timings, print_step_timings);
+        set(&mut config.print_step_rusage, print_step_rusage);
+        config.patch_binaries_for_nix = patch_binaries_for_nix;
 
         config.verbose = cmp::max(config.verbose, flags.verbose as usize);
 
         if let Some(install) = toml.install {
-            config.prefix = install.prefix.map(PathBuf::from);
-            config.sysconfdir = install.sysconfdir.map(PathBuf::from);
-            config.datadir = install.datadir.map(PathBuf::from);
-            config.docdir = install.docdir.map(PathBuf::from);
-            set(&mut config.bindir, install.bindir.map(PathBuf::from));
-            config.libdir = install.libdir.map(PathBuf::from);
-            config.mandir = install.mandir.map(PathBuf::from);
+            let Install { prefix, sysconfdir, docdir, bindir, libdir, mandir, datadir } = install;
+            config.prefix = prefix.map(PathBuf::from);
+            config.sysconfdir = sysconfdir.map(PathBuf::from);
+            config.datadir = datadir.map(PathBuf::from);
+            config.docdir = docdir.map(PathBuf::from);
+            set(&mut config.bindir, bindir.map(PathBuf::from));
+            config.libdir = libdir.map(PathBuf::from);
+            config.mandir = mandir.map(PathBuf::from);
         }
 
         // Store off these values as options because if they're not provided
@@ -1387,9 +1506,63 @@ impl Config {
         let mut omit_git_hash = None;
 
         if let Some(rust) = toml.rust {
-            set(&mut config.channel, rust.channel);
-
-            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
+            let Rust {
+                optimize: optimize_toml,
+                debug: debug_toml,
+                codegen_units,
+                codegen_units_std,
+                debug_assertions: debug_assertions_toml,
+                debug_assertions_std: debug_assertions_std_toml,
+                overflow_checks: overflow_checks_toml,
+                overflow_checks_std: overflow_checks_std_toml,
+                debug_logging: debug_logging_toml,
+                debuginfo_level: debuginfo_level_toml,
+                debuginfo_level_rustc: debuginfo_level_rustc_toml,
+                debuginfo_level_std: debuginfo_level_std_toml,
+                debuginfo_level_tools: debuginfo_level_tools_toml,
+                debuginfo_level_tests: debuginfo_level_tests_toml,
+                split_debuginfo,
+                backtrace,
+                incremental,
+                parallel_compiler,
+                default_linker,
+                channel,
+                description,
+                musl_root,
+                rpath,
+                verbose_tests,
+                optimize_tests,
+                codegen_tests,
+                omit_git_hash: omit_git_hash_toml,
+                dist_src,
+                save_toolstates,
+                codegen_backends,
+                lld,
+                llvm_tools,
+                deny_warnings,
+                backtrace_on_ice,
+                verify_llvm_ir,
+                thin_lto_import_instr_limit,
+                remap_debuginfo,
+                jemalloc,
+                test_compare_mode,
+                llvm_libunwind,
+                control_flow_guard,
+                ehcont_guard,
+                new_symbol_mangling,
+                profile_generate,
+                profile_use,
+                download_rustc,
+                lto,
+                validate_mir_opts,
+                stack_protector,
+                strip,
+                lld_mode,
+            } = rust;
+
+            set(&mut config.channel, channel);
+
+            config.download_rustc_commit = config.download_ci_rustc_commit(download_rustc);
             // This list is incomplete, please help by expanding it!
             if config.download_rustc_commit.is_some() {
                 // We need the channel used by the downloaded compiler to match the one we set for rustdoc;
@@ -1406,70 +1579,77 @@ impl Config {
                 }
             }
 
-            debug = rust.debug;
-            debug_assertions = rust.debug_assertions;
-            debug_assertions_std = rust.debug_assertions_std;
-            overflow_checks = rust.overflow_checks;
-            overflow_checks_std = rust.overflow_checks_std;
-            debug_logging = rust.debug_logging;
-            debuginfo_level = rust.debuginfo_level;
-            debuginfo_level_rustc = rust.debuginfo_level_rustc;
-            debuginfo_level_std = rust.debuginfo_level_std;
-            debuginfo_level_tools = rust.debuginfo_level_tools;
-            debuginfo_level_tests = rust.debuginfo_level_tests;
-
-            config.rust_split_debuginfo = rust
-                .split_debuginfo
+            debug = debug_toml;
+            debug_assertions = debug_assertions_toml;
+            debug_assertions_std = debug_assertions_std_toml;
+            overflow_checks = overflow_checks_toml;
+            overflow_checks_std = overflow_checks_std_toml;
+            debug_logging = debug_logging_toml;
+            debuginfo_level = debuginfo_level_toml;
+            debuginfo_level_rustc = debuginfo_level_rustc_toml;
+            debuginfo_level_std = debuginfo_level_std_toml;
+            debuginfo_level_tools = debuginfo_level_tools_toml;
+            debuginfo_level_tests = debuginfo_level_tests_toml;
+
+            config.rust_split_debuginfo = split_debuginfo
                 .as_deref()
                 .map(SplitDebuginfo::from_str)
                 .map(|v| v.expect("invalid value for rust.split_debuginfo"))
                 .unwrap_or(SplitDebuginfo::default_for_platform(&config.build.triple));
-            optimize = rust.optimize;
-            omit_git_hash = rust.omit_git_hash;
-            config.rust_new_symbol_mangling = rust.new_symbol_mangling;
-            set(&mut config.rust_optimize_tests, rust.optimize_tests);
-            set(&mut config.codegen_tests, rust.codegen_tests);
-            set(&mut config.rust_rpath, rust.rpath);
-            set(&mut config.rust_strip, rust.strip);
-            config.rust_stack_protector = rust.stack_protector;
-            set(&mut config.jemalloc, rust.jemalloc);
-            set(&mut config.test_compare_mode, rust.test_compare_mode);
-            set(&mut config.backtrace, rust.backtrace);
-            config.description = rust.description;
-            set(&mut config.rust_dist_src, rust.dist_src);
-            set(&mut config.verbose_tests, rust.verbose_tests);
+            optimize = optimize_toml;
+            omit_git_hash = omit_git_hash_toml;
+            config.rust_new_symbol_mangling = new_symbol_mangling;
+            set(&mut config.rust_optimize_tests, optimize_tests);
+            set(&mut config.codegen_tests, codegen_tests);
+            set(&mut config.rust_rpath, rpath);
+            set(&mut config.rust_strip, strip);
+            config.rust_stack_protector = stack_protector;
+            set(&mut config.jemalloc, jemalloc);
+            set(&mut config.test_compare_mode, test_compare_mode);
+            set(&mut config.backtrace, backtrace);
+            config.description = description;
+            set(&mut config.rust_dist_src, dist_src);
+            set(&mut config.verbose_tests, verbose_tests);
             // in the case "false" is set explicitly, do not overwrite the command line args
-            if let Some(true) = rust.incremental {
+            if let Some(true) = incremental {
                 config.incremental = true;
             }
-            set(&mut config.use_lld, rust.use_lld);
-            set(&mut config.lld_enabled, rust.lld);
-            set(&mut config.llvm_tools_enabled, rust.llvm_tools);
-            config.rustc_parallel = rust
-                .parallel_compiler
-                .unwrap_or(config.channel == "dev" || config.channel == "nightly");
-            config.rustc_default_linker = rust.default_linker;
-            config.musl_root = rust.musl_root.map(PathBuf::from);
-            config.save_toolstates = rust.save_toolstates.map(PathBuf::from);
+            set(&mut config.lld_mode, lld_mode);
+            set(&mut config.lld_enabled, lld);
+
+            if matches!(config.lld_mode, LldMode::SelfContained)
+                && !config.lld_enabled
+                && flags.stage.unwrap_or(0) > 0
+            {
+                panic!(
+                    "Trying to use self-contained lld as a linker, but LLD is not being added to the sysroot. Enable it with rust.lld = true."
+                );
+            }
+
+            set(&mut config.llvm_tools_enabled, llvm_tools);
+            config.rustc_parallel =
+                parallel_compiler.unwrap_or(config.channel == "dev" || config.channel == "nightly");
+            config.rustc_default_linker = default_linker;
+            config.musl_root = musl_root.map(PathBuf::from);
+            config.save_toolstates = save_toolstates.map(PathBuf::from);
             set(
                 &mut config.deny_warnings,
                 match flags.warnings {
                     Warnings::Deny => Some(true),
                     Warnings::Warn => Some(false),
-                    Warnings::Default => rust.deny_warnings,
+                    Warnings::Default => deny_warnings,
                 },
             );
-            set(&mut config.backtrace_on_ice, rust.backtrace_on_ice);
-            set(&mut config.rust_verify_llvm_ir, rust.verify_llvm_ir);
-            config.rust_thin_lto_import_instr_limit = rust.thin_lto_import_instr_limit;
-            set(&mut config.rust_remap_debuginfo, rust.remap_debuginfo);
-            set(&mut config.control_flow_guard, rust.control_flow_guard);
-            set(&mut config.ehcont_guard, rust.ehcont_guard);
-            config.llvm_libunwind_default = rust
-                .llvm_libunwind
-                .map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
-
-            if let Some(ref backends) = rust.codegen_backends {
+            set(&mut config.backtrace_on_ice, backtrace_on_ice);
+            set(&mut config.rust_verify_llvm_ir, verify_llvm_ir);
+            config.rust_thin_lto_import_instr_limit = thin_lto_import_instr_limit;
+            set(&mut config.rust_remap_debuginfo, remap_debuginfo);
+            set(&mut config.control_flow_guard, control_flow_guard);
+            set(&mut config.ehcont_guard, ehcont_guard);
+            config.llvm_libunwind_default =
+                llvm_libunwind.map(|v| v.parse().expect("failed to parse rust.llvm-libunwind"));
+
+            if let Some(ref backends) = codegen_backends {
                 let available_backends = vec!["llvm", "cranelift", "gcc"];
 
                 config.rust_codegen_backends = backends.iter().map(|s| {
@@ -1487,16 +1667,13 @@ impl Config {
                 }).collect();
             }
 
-            config.rust_codegen_units = rust.codegen_units.map(threads_from_config);
-            config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
-            config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
-            config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
-            config.rust_lto = rust
-                .lto
-                .as_deref()
-                .map(|value| RustcLto::from_str(value).unwrap())
-                .unwrap_or_default();
-            config.rust_validate_mir_opts = rust.validate_mir_opts;
+            config.rust_codegen_units = codegen_units.map(threads_from_config);
+            config.rust_codegen_units_std = codegen_units_std.map(threads_from_config);
+            config.rust_profile_use = flags.rust_profile_use.or(profile_use);
+            config.rust_profile_generate = flags.rust_profile_generate.or(profile_generate);
+            config.rust_lto =
+                lto.as_deref().map(|value| RustcLto::from_str(value).unwrap()).unwrap_or_default();
+            config.rust_validate_mir_opts = validate_mir_opts;
         } else {
             config.rust_profile_use = flags.rust_profile_use;
             config.rust_profile_generate = flags.rust_profile_generate;
@@ -1510,43 +1687,71 @@ impl Config {
         config.rust_info = GitInfo::new(config.omit_git_hash, &config.src);
 
         if let Some(llvm) = toml.llvm {
-            match llvm.ccache {
+            let Llvm {
+                optimize: optimize_toml,
+                thin_lto,
+                release_debuginfo,
+                assertions,
+                tests,
+                plugins,
+                ccache,
+                static_libstdcpp,
+                ninja,
+                targets,
+                experimental_targets,
+                link_jobs,
+                link_shared,
+                version_suffix,
+                clang_cl,
+                cflags,
+                cxxflags,
+                ldflags,
+                use_libcxx,
+                use_linker,
+                allow_old_toolchain,
+                polly,
+                clang,
+                enable_warnings,
+                download_ci_llvm,
+                build_config,
+            } = llvm;
+            match ccache {
                 Some(StringOrBool::String(ref s)) => config.ccache = Some(s.to_string()),
                 Some(StringOrBool::Bool(true)) => {
                     config.ccache = Some("ccache".to_string());
                 }
                 Some(StringOrBool::Bool(false)) | None => {}
             }
-            set(&mut config.ninja_in_file, llvm.ninja);
-            llvm_assertions = llvm.assertions;
-            llvm_tests = llvm.tests;
-            llvm_plugins = llvm.plugins;
-            set(&mut config.llvm_optimize, llvm.optimize);
-            set(&mut config.llvm_thin_lto, llvm.thin_lto);
-            set(&mut config.llvm_release_debuginfo, llvm.release_debuginfo);
-            set(&mut config.llvm_static_stdcpp, llvm.static_libstdcpp);
-            if let Some(v) = llvm.link_shared {
+            set(&mut config.ninja_in_file, ninja);
+            llvm_assertions = assertions;
+            llvm_tests = tests;
+            llvm_plugins = plugins;
+            set(&mut config.llvm_optimize, optimize_toml);
+            set(&mut config.llvm_thin_lto, thin_lto);
+            set(&mut config.llvm_release_debuginfo, release_debuginfo);
+            set(&mut config.llvm_static_stdcpp, static_libstdcpp);
+            if let Some(v) = link_shared {
                 config.llvm_link_shared.set(Some(v));
             }
-            config.llvm_targets = llvm.targets.clone();
-            config.llvm_experimental_targets = llvm.experimental_targets.clone();
-            config.llvm_link_jobs = llvm.link_jobs;
-            config.llvm_version_suffix = llvm.version_suffix.clone();
-            config.llvm_clang_cl = llvm.clang_cl.clone();
-
-            config.llvm_cflags = llvm.cflags.clone();
-            config.llvm_cxxflags = llvm.cxxflags.clone();
-            config.llvm_ldflags = llvm.ldflags.clone();
-            set(&mut config.llvm_use_libcxx, llvm.use_libcxx);
-            config.llvm_use_linker = llvm.use_linker.clone();
-            config.llvm_allow_old_toolchain = llvm.allow_old_toolchain.unwrap_or(false);
-            config.llvm_polly = llvm.polly.unwrap_or(false);
-            config.llvm_clang = llvm.clang.unwrap_or(false);
-            config.llvm_enable_warnings = llvm.enable_warnings.unwrap_or(false);
-            config.llvm_build_config = llvm.build_config.clone().unwrap_or(Default::default());
+            config.llvm_targets = targets.clone();
+            config.llvm_experimental_targets = experimental_targets.clone();
+            config.llvm_link_jobs = link_jobs;
+            config.llvm_version_suffix = version_suffix.clone();
+            config.llvm_clang_cl = clang_cl.clone();
+
+            config.llvm_cflags = cflags.clone();
+            config.llvm_cxxflags = cxxflags.clone();
+            config.llvm_ldflags = ldflags.clone();
+            set(&mut config.llvm_use_libcxx, use_libcxx);
+            config.llvm_use_linker = use_linker.clone();
+            config.llvm_allow_old_toolchain = allow_old_toolchain.unwrap_or(false);
+            config.llvm_polly = polly.unwrap_or(false);
+            config.llvm_clang = clang.unwrap_or(false);
+            config.llvm_enable_warnings = enable_warnings.unwrap_or(false);
+            config.llvm_build_config = build_config.clone().unwrap_or(Default::default());
 
             let asserts = llvm_assertions.unwrap_or(false);
-            config.llvm_from_ci = config.parse_download_ci_llvm(llvm.download_ci_llvm, asserts);
+            config.llvm_from_ci = config.parse_download_ci_llvm(download_ci_llvm, asserts);
 
             if config.llvm_from_ci {
                 // None of the LLVM options, except assertions, are supported
@@ -1555,31 +1760,31 @@ impl Config {
                 // explicitly set. The defaults and CI defaults don't
                 // necessarily match but forcing people to match (somewhat
                 // arbitrary) CI configuration locally seems bad/hard.
-                check_ci_llvm!(llvm.optimize);
-                check_ci_llvm!(llvm.thin_lto);
-                check_ci_llvm!(llvm.release_debuginfo);
+                check_ci_llvm!(optimize_toml);
+                check_ci_llvm!(thin_lto);
+                check_ci_llvm!(release_debuginfo);
                 // CI-built LLVM can be either dynamic or static. We won't know until we download it.
-                check_ci_llvm!(llvm.link_shared);
-                check_ci_llvm!(llvm.static_libstdcpp);
-                check_ci_llvm!(llvm.targets);
-                check_ci_llvm!(llvm.experimental_targets);
-                check_ci_llvm!(llvm.link_jobs);
-                check_ci_llvm!(llvm.clang_cl);
-                check_ci_llvm!(llvm.version_suffix);
-                check_ci_llvm!(llvm.cflags);
-                check_ci_llvm!(llvm.cxxflags);
-                check_ci_llvm!(llvm.ldflags);
-                check_ci_llvm!(llvm.use_libcxx);
-                check_ci_llvm!(llvm.use_linker);
-                check_ci_llvm!(llvm.allow_old_toolchain);
-                check_ci_llvm!(llvm.polly);
-                check_ci_llvm!(llvm.clang);
-                check_ci_llvm!(llvm.build_config);
-                check_ci_llvm!(llvm.plugins);
+                check_ci_llvm!(link_shared);
+                check_ci_llvm!(static_libstdcpp);
+                check_ci_llvm!(targets);
+                check_ci_llvm!(experimental_targets);
+                check_ci_llvm!(link_jobs);
+                check_ci_llvm!(clang_cl);
+                check_ci_llvm!(version_suffix);
+                check_ci_llvm!(cflags);
+                check_ci_llvm!(cxxflags);
+                check_ci_llvm!(ldflags);
+                check_ci_llvm!(use_libcxx);
+                check_ci_llvm!(use_linker);
+                check_ci_llvm!(allow_old_toolchain);
+                check_ci_llvm!(polly);
+                check_ci_llvm!(clang);
+                check_ci_llvm!(build_config);
+                check_ci_llvm!(plugins);
             }
 
             // NOTE: can never be hit when downloading from CI, since we call `check_ci_llvm!(thin_lto)` above.
-            if config.llvm_thin_lto && llvm.link_shared.is_none() {
+            if config.llvm_thin_lto && link_shared.is_none() {
                 // If we're building with ThinLTO on, by default we want to link
                 // to LLVM shared, to avoid re-doing ThinLTO (which happens in
                 // the link step) with each stage.
@@ -1645,17 +1850,26 @@ impl Config {
             build_target.llvm_filecheck = Some(ci_llvm_bin.join(exe("FileCheck", config.build)));
         }
 
-        if let Some(t) = toml.dist {
-            config.dist_sign_folder = t.sign_folder.map(PathBuf::from);
-            config.dist_upload_addr = t.upload_addr;
-            config.dist_compression_formats = t.compression_formats;
-            set(&mut config.dist_compression_profile, t.compression_profile);
-            set(&mut config.rust_dist_src, t.src_tarball);
-            set(&mut config.missing_tools, t.missing_tools);
-            set(&mut config.dist_include_mingw_linker, t.include_mingw_linker)
+        if let Some(dist) = toml.dist {
+            let Dist {
+                sign_folder,
+                upload_addr,
+                src_tarball,
+                missing_tools,
+                compression_formats,
+                compression_profile,
+                include_mingw_linker,
+            } = dist;
+            config.dist_sign_folder = sign_folder.map(PathBuf::from);
+            config.dist_upload_addr = upload_addr;
+            config.dist_compression_formats = compression_formats;
+            set(&mut config.dist_compression_profile, compression_profile);
+            set(&mut config.rust_dist_src, src_tarball);
+            set(&mut config.missing_tools, missing_tools);
+            set(&mut config.dist_include_mingw_linker, include_mingw_linker)
         }
 
-        if let Some(r) = build.rustfmt {
+        if let Some(r) = rustfmt {
             *config.initial_rustfmt.borrow_mut() = if r.exists() {
                 RustfmtState::SystemToolchain(r)
             } else {
@@ -1696,20 +1910,20 @@ impl Config {
         let download_rustc = config.download_rustc_commit.is_some();
         // See https://github.com/rust-lang/compiler-team/issues/326
         config.stage = match config.cmd {
-            Subcommand::Check { .. } => flags.stage.or(build.check_stage).unwrap_or(0),
+            Subcommand::Check { .. } => flags.stage.or(check_stage).unwrap_or(0),
             // `download-rustc` only has a speed-up for stage2 builds. Default to stage2 unless explicitly overridden.
             Subcommand::Doc { .. } => {
-                flags.stage.or(build.doc_stage).unwrap_or(if download_rustc { 2 } else { 0 })
+                flags.stage.or(doc_stage).unwrap_or(if download_rustc { 2 } else { 0 })
             }
             Subcommand::Build { .. } => {
-                flags.stage.or(build.build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
+                flags.stage.or(build_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
             Subcommand::Test { .. } => {
-                flags.stage.or(build.test_stage).unwrap_or(if download_rustc { 2 } else { 1 })
+                flags.stage.or(test_stage).unwrap_or(if download_rustc { 2 } else { 1 })
             }
-            Subcommand::Bench { .. } => flags.stage.or(build.bench_stage).unwrap_or(2),
-            Subcommand::Dist { .. } => flags.stage.or(build.dist_stage).unwrap_or(2),
-            Subcommand::Install { .. } => flags.stage.or(build.install_stage).unwrap_or(2),
+            Subcommand::Bench { .. } => flags.stage.or(bench_stage).unwrap_or(2),
+            Subcommand::Dist { .. } => flags.stage.or(dist_stage).unwrap_or(2),
+            Subcommand::Install { .. } => flags.stage.or(install_stage).unwrap_or(2),
             // These are all bootstrap tools, which don't depend on the compiler.
             // The stage we pass shouldn't matter, but use 0 just in case.
             Subcommand::Clean { .. }
diff --git a/src/bootstrap/src/core/config/flags.rs b/src/bootstrap/src/core/config/flags.rs
index 27d0425df54..0b13726081b 100644
--- a/src/bootstrap/src/core/config/flags.rs
+++ b/src/bootstrap/src/core/config/flags.rs
@@ -85,6 +85,9 @@ pub struct Flags {
     #[arg(global(true), long)]
     /// dry run; don't build anything
     pub dry_run: bool,
+    /// Indicates whether to dump the work done from bootstrap shims
+    #[arg(global(true), long)]
+    pub dump_bootstrap_shims: bool,
     #[arg(global(true), value_hint = clap::ValueHint::Other, long, value_name = "N")]
     /// stage to build (indicates compiler to use/test, e.g., stage 0 uses the
     /// bootstrap compiler, stage 1 the stage 0 rustc artifacts, etc.)
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index eec3be66a12..9101d94ea88 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -237,7 +237,7 @@ than building it.
             }
         }
 
-        if need_cmake && target.contains("msvc") {
+        if need_cmake && target.is_msvc() {
             // There are three builds of cmake on windows: MSVC, MinGW, and
             // Cygwin. The Cygwin build does not have generators for Visual
             // Studio, so detect that here and error.
diff --git a/src/bootstrap/src/lib.rs b/src/bootstrap/src/lib.rs
index 13391b1faa1..18f6dc53376 100644
--- a/src/bootstrap/src/lib.rs
+++ b/src/bootstrap/src/lib.rs
@@ -37,7 +37,7 @@ use utils::channel::GitInfo;
 
 use crate::core::builder;
 use crate::core::builder::Kind;
-use crate::core::config::flags;
+use crate::core::config::{flags, LldMode};
 use crate::core::config::{DryRun, Target};
 use crate::core::config::{LlvmLibunwind, TargetSelection};
 use crate::utils::cache::{Interned, INTERNER};
@@ -862,7 +862,7 @@ impl Build {
             }
         } else {
             let base = self.llvm_out(target).join("build");
-            let base = if !self.ninja() && target.contains("msvc") {
+            let base = if !self.ninja() && target.is_msvc() {
                 if self.config.llvm_optimize {
                     if self.config.llvm_release_debuginfo {
                         base.join("RelWithDebInfo")
@@ -1255,35 +1255,27 @@ impl Build {
             Some(self.cxx.borrow()[&target].path().into())
         } else if target != self.config.build
             && helpers::use_host_linker(target)
-            && !target.contains("msvc")
+            && !target.is_msvc()
         {
             Some(self.cc(target))
-        } else if self.config.use_lld && !self.is_fuse_ld_lld(target) && self.build == target {
-            Some(self.initial_lld.clone())
+        } else if self.config.lld_mode.is_used()
+            && self.is_lld_direct_linker(target)
+            && self.build == target
+        {
+            match self.config.lld_mode {
+                LldMode::SelfContained => Some(self.initial_lld.clone()),
+                LldMode::External => Some("lld".into()),
+                LldMode::Unused => None,
+            }
         } else {
             None
         }
     }
 
-    // LLD is used through `-fuse-ld=lld` rather than directly.
+    // Is LLD configured directly through `-Clinker`?
     // Only MSVC targets use LLD directly at the moment.
-    fn is_fuse_ld_lld(&self, target: TargetSelection) -> bool {
-        self.config.use_lld && !target.contains("msvc")
-    }
-
-    fn lld_flags(&self, target: TargetSelection) -> impl Iterator<Item = String> {
-        let mut options = [None, None];
-
-        if self.config.use_lld {
-            if self.is_fuse_ld_lld(target) {
-                options[0] = Some("-Clink-arg=-fuse-ld=lld".to_string());
-            }
-
-            let no_threads = helpers::lld_flag_no_threads(target.contains("windows"));
-            options[1] = Some(format!("-Clink-arg=-Wl,{no_threads}"));
-        }
-
-        IntoIterator::into_iter(options).flatten()
+    fn is_lld_direct_linker(&self, target: TargetSelection) -> bool {
+        target.is_msvc()
     }
 
     /// Returns if this target should statically link the C runtime, if specified
@@ -1764,7 +1756,7 @@ to download LLVM rather than building it.
         // In these cases we automatically enable Ninja if we find it in the
         // environment.
         if !self.config.ninja_in_file
-            && self.config.build.contains("msvc")
+            && self.config.build.is_msvc()
             && cmd_finder.maybe_have("ninja").is_some()
         {
             return true;
@@ -1879,3 +1871,22 @@ pub fn generate_smart_stamp_hash(dir: &Path, additional_input: &str) -> String {
 
     hex::encode(hasher.finalize().as_slice())
 }
+
+/// Ensures that the behavior dump directory is properly initialized.
+pub fn prepare_behaviour_dump_dir(build: &Build) {
+    static INITIALIZED: OnceLock<bool> = OnceLock::new();
+
+    let dump_path = build.out.join("bootstrap-shims-dump");
+
+    let initialized = INITIALIZED.get().unwrap_or_else(|| &false);
+    if !initialized {
+        // clear old dumps
+        if dump_path.exists() {
+            t!(fs::remove_dir_all(&dump_path));
+        }
+
+        t!(fs::create_dir_all(&dump_path));
+
+        t!(INITIALIZED.set(true));
+    }
+}
diff --git a/src/bootstrap/src/tests/config.rs b/src/bootstrap/src/tests/config.rs
index a8106ca8ff9..c24d57fb8f8 100644
--- a/src/bootstrap/src/tests/config.rs
+++ b/src/bootstrap/src/tests/config.rs
@@ -1,5 +1,5 @@
-use crate::core::config::TomlConfig;
 use super::{Config, Flags};
+use crate::core::config::{LldMode, TomlConfig};
 
 use clap::CommandFactory;
 use serde::Deserialize;
@@ -217,3 +217,12 @@ fn verify_file_integrity() {
 
     remove_file(tempfile).unwrap();
 }
+
+#[test]
+fn rust_lld() {
+    assert!(matches!(parse("").lld_mode, LldMode::Unused));
+    assert!(matches!(parse("rust.use-lld = \"self-contained\"").lld_mode, LldMode::SelfContained));
+    assert!(matches!(parse("rust.use-lld = \"external\"").lld_mode, LldMode::External));
+    assert!(matches!(parse("rust.use-lld = true").lld_mode, LldMode::External));
+    assert!(matches!(parse("rust.use-lld = false").lld_mode, LldMode::Unused));
+}
diff --git a/src/bootstrap/src/utils/bin_helpers.rs b/src/bootstrap/src/utils/bin_helpers.rs
index c90fd2805e2..9c4e039ea69 100644
--- a/src/bootstrap/src/utils/bin_helpers.rs
+++ b/src/bootstrap/src/utils/bin_helpers.rs
@@ -2,14 +2,18 @@
 //! dependency on the bootstrap library. This reduces the binary size and
 //! improves compilation time by reducing the linking time.
 
+use std::env;
+use std::fs::OpenOptions;
+use std::io::Write;
+use std::process::Command;
+use std::str::FromStr;
+
 /// Parses the value of the "RUSTC_VERBOSE" environment variable and returns it as a `usize`.
 /// If it was not defined, returns 0 by default.
 ///
 /// Panics if "RUSTC_VERBOSE" is defined with the value that is not an unsigned integer.
 pub(crate) fn parse_rustc_verbose() -> usize {
-    use std::str::FromStr;
-
-    match std::env::var("RUSTC_VERBOSE") {
+    match env::var("RUSTC_VERBOSE") {
         Ok(s) => usize::from_str(&s).expect("RUSTC_VERBOSE should be an integer"),
         Err(_) => 0,
     }
@@ -19,10 +23,29 @@ pub(crate) fn parse_rustc_verbose() -> usize {
 ///
 /// If "RUSTC_STAGE" was not set, the program will be terminated with 101.
 pub(crate) fn parse_rustc_stage() -> String {
-    std::env::var("RUSTC_STAGE").unwrap_or_else(|_| {
+    env::var("RUSTC_STAGE").unwrap_or_else(|_| {
         // Don't panic here; it's reasonable to try and run these shims directly. Give a helpful error instead.
         eprintln!("rustc shim: FATAL: RUSTC_STAGE was not set");
         eprintln!("rustc shim: NOTE: use `x.py build -vvv` to see all environment variables set by bootstrap");
         std::process::exit(101);
     })
 }
+
+/// Writes the command invocation to a file if `DUMP_BOOTSTRAP_SHIMS` is set during bootstrap.
+///
+/// Before writing it, replaces user-specific values to create generic dumps for cross-environment
+/// comparisons.
+pub(crate) fn maybe_dump(dump_name: String, cmd: &Command) {
+    if let Ok(dump_dir) = env::var("DUMP_BOOTSTRAP_SHIMS") {
+        let dump_file = format!("{dump_dir}/{dump_name}");
+
+        let mut file =
+            OpenOptions::new().create(true).write(true).append(true).open(&dump_file).unwrap();
+
+        let cmd_dump = format!("{:?}\n", cmd);
+        let cmd_dump = cmd_dump.replace(&env::var("BUILD_OUT").unwrap(), "${BUILD_OUT}");
+        let cmd_dump = cmd_dump.replace(&env::var("CARGO_HOME").unwrap(), "${CARGO_HOME}");
+
+        file.write_all(cmd_dump.as_bytes()).expect("Unable to write file");
+    }
+}
diff --git a/src/bootstrap/src/utils/cc_detect.rs b/src/bootstrap/src/utils/cc_detect.rs
index 52b36ce75f3..fb5b9d8c88f 100644
--- a/src/bootstrap/src/utils/cc_detect.rs
+++ b/src/bootstrap/src/utils/cc_detect.rs
@@ -39,7 +39,7 @@ fn cc2ar(cc: &Path, target: TargetSelection) -> Option<PathBuf> {
         Some(PathBuf::from(ar))
     } else if let Some(ar) = env::var_os("AR") {
         Some(PathBuf::from(ar))
-    } else if target.contains("msvc") {
+    } else if target.is_msvc() {
         None
     } else if target.contains("musl") {
         Some(PathBuf::from("ar"))
@@ -78,7 +78,7 @@ fn new_cc_build(build: &Build, target: TargetSelection) -> cc::Build {
             cfg.static_crt(a);
         }
         None => {
-            if target.contains("msvc") {
+            if target.is_msvc() {
                 cfg.static_crt(true);
             }
             if target.contains("musl") {
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 887b596b786..8b53a61542e 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -86,4 +86,14 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "Use of the `if-available` value for `download-ci-llvm` is deprecated; prefer using the new `if-unchanged` value.",
     },
+    ChangeInfo {
+        change_id: 116278,
+        severity: ChangeSeverity::Info,
+        summary: "The `rust.use-lld` configuration now has different options ('external'/true or 'self-contained'), and its behaviour has changed.",
+    },
+    ChangeInfo {
+        change_id: 118703,
+        severity: ChangeSeverity::Info,
+        summary: "Removed rust.run_dsymutil and dist.gpg_password_file config options, as they were unused.",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index f878d634743..133792d85e8 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -5,7 +5,7 @@
 
 use build_helper::util::fail;
 use std::env;
-use std::ffi::{OsStr, OsString};
+use std::ffi::OsStr;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
@@ -16,6 +16,7 @@ use std::time::{Instant, SystemTime, UNIX_EPOCH};
 
 use crate::core::builder::Builder;
 use crate::core::config::{Config, TargetSelection};
+use crate::LldMode;
 
 pub use crate::utils::dylib::{dylib_path, dylib_path_var};
 
@@ -378,6 +379,7 @@ fn absolute_unix(path: &Path) -> io::Result<PathBuf> {
 
 #[cfg(windows)]
 fn absolute_windows(path: &std::path::Path) -> std::io::Result<std::path::PathBuf> {
+    use std::ffi::OsString;
     use std::io::Error;
     use std::os::windows::ffi::{OsStrExt, OsStringExt};
     use std::ptr::null_mut;
@@ -443,17 +445,29 @@ pub fn get_clang_cl_resource_dir(clang_cl_path: &str) -> PathBuf {
     clang_rt_dir.to_path_buf()
 }
 
-pub fn lld_flag_no_threads(is_windows: bool) -> &'static str {
+/// Returns a flag that configures LLD to use only a single thread.
+/// If we use an external LLD, we need to find out which version is it to know which flag should we
+/// pass to it (LLD older than version 10 had a different flag).
+fn lld_flag_no_threads(lld_mode: LldMode, is_windows: bool) -> &'static str {
     static LLD_NO_THREADS: OnceLock<(&'static str, &'static str)> = OnceLock::new();
-    let (windows, other) = LLD_NO_THREADS.get_or_init(|| {
-        let out = output(Command::new("lld").arg("-flavor").arg("ld").arg("--version"));
-        let newer = match (out.find(char::is_numeric), out.find('.')) {
-            (Some(b), Some(e)) => out.as_str()[b..e].parse::<i32>().ok().unwrap_or(14) > 10,
+
+    let new_flags = ("/threads:1", "--threads=1");
+    let old_flags = ("/no-threads", "--no-threads");
+
+    let (windows_flag, other_flag) = LLD_NO_THREADS.get_or_init(|| {
+        let newer_version = match lld_mode {
+            LldMode::External => {
+                let out = output(Command::new("lld").arg("-flavor").arg("ld").arg("--version"));
+                match (out.find(char::is_numeric), out.find('.')) {
+                    (Some(b), Some(e)) => out.as_str()[b..e].parse::<i32>().ok().unwrap_or(14) > 10,
+                    _ => true,
+                }
+            }
             _ => true,
         };
-        if newer { ("/threads:1", "--threads=1") } else { ("/no-threads", "--no-threads") }
+        if newer_version { new_flags } else { old_flags }
     });
-    if is_windows { windows } else { other }
+    if is_windows { windows_flag } else { other_flag }
 }
 
 pub fn dir_is_empty(dir: &Path) -> bool {
@@ -476,22 +490,49 @@ pub enum LldThreads {
     No,
 }
 
-pub fn add_rustdoc_lld_flags(
-    cmd: &mut Command,
+/// Returns the linker arguments for rustc/rustdoc for the given builder and target.
+pub fn linker_args(
     builder: &Builder<'_>,
     target: TargetSelection,
     lld_threads: LldThreads,
-) {
-    cmd.args(build_rustdoc_lld_flags(builder, target, lld_threads));
+) -> Vec<String> {
+    let mut args = linker_flags(builder, target, lld_threads);
+
+    if let Some(linker) = builder.linker(target) {
+        args.push(format!("-Clinker={}", linker.display()));
+    }
+
+    args
 }
 
-pub fn add_rustdoc_cargo_lld_flags(
+/// Returns the linker arguments for rustc/rustdoc for the given builder and target, without the
+/// -Clinker flag.
+pub fn linker_flags(
+    builder: &Builder<'_>,
+    target: TargetSelection,
+    lld_threads: LldThreads,
+) -> Vec<String> {
+    let mut args = vec![];
+    if !builder.is_lld_direct_linker(target) && builder.config.lld_mode.is_used() {
+        args.push(String::from("-Clink-arg=-fuse-ld=lld"));
+
+        if matches!(lld_threads, LldThreads::No) {
+            args.push(format!(
+                "-Clink-arg=-Wl,{}",
+                lld_flag_no_threads(builder.config.lld_mode, target.is_msvc())
+            ));
+        }
+    }
+    args
+}
+
+pub fn add_rustdoc_cargo_linker_args(
     cmd: &mut Command,
     builder: &Builder<'_>,
     target: TargetSelection,
     lld_threads: LldThreads,
 ) {
-    let args = build_rustdoc_lld_flags(builder, target, lld_threads);
+    let args = linker_args(builder, target, lld_threads);
     let mut flags = cmd
         .get_envs()
         .find_map(|(k, v)| if k == OsStr::new("RUSTDOCFLAGS") { v } else { None })
@@ -507,27 +548,3 @@ pub fn add_rustdoc_cargo_lld_flags(
         cmd.env("RUSTDOCFLAGS", flags);
     }
 }
-
-fn build_rustdoc_lld_flags(
-    builder: &Builder<'_>,
-    target: TargetSelection,
-    lld_threads: LldThreads,
-) -> Vec<OsString> {
-    let mut args = vec![];
-
-    if let Some(linker) = builder.linker(target) {
-        let mut flag = std::ffi::OsString::from("-Clinker=");
-        flag.push(linker);
-        args.push(flag);
-    }
-    if builder.is_fuse_ld_lld(target) {
-        args.push(OsString::from("-Clink-arg=-fuse-ld=lld"));
-        if matches!(lld_threads, LldThreads::No) {
-            args.push(OsString::from(format!(
-                "-Clink-arg=-Wl,{}",
-                lld_flag_no_threads(target.contains("windows"))
-            )));
-        }
-    }
-    args
-}
diff --git a/src/doc/rustc/src/linker-plugin-lto.md b/src/doc/rustc/src/linker-plugin-lto.md
index 858b7bc79c4..ff80f140482 100644
--- a/src/doc/rustc/src/linker-plugin-lto.md
+++ b/src/doc/rustc/src/linker-plugin-lto.md
@@ -136,6 +136,7 @@ able to get around this problem by setting `-Clinker=lld-link` in RUSTFLAGS
 ```python
 from collections import defaultdict
 import subprocess
+import sys
 
 def minor_version(version):
     return int(version.split('.')[1])
@@ -143,7 +144,7 @@ def minor_version(version):
 INSTALL_TOOLCHAIN = ["rustup", "toolchain", "install", "--profile", "minimal"]
 subprocess.run(INSTALL_TOOLCHAIN + ["nightly"])
 
-LOWER_BOUND = 65
+LOWER_BOUND = 73
 NIGHTLY_VERSION = minor_version(subprocess.run(
     ["rustc", "+nightly", "--version"],
     capture_output=True,
@@ -159,6 +160,7 @@ def llvm_version(toolchain):
 version_map = defaultdict(lambda: [])
 for version in range(LOWER_BOUND, NIGHTLY_VERSION - 1):
     toolchain = "1.{}.0".format(version)
+    print("Checking", toolchain, file=sys.stderr)
     subprocess.run(
         INSTALL_TOOLCHAIN + ["--no-self-update", toolchain],
         capture_output=True)
@@ -196,6 +198,8 @@ The following table shows known good combinations of toolchain versions.
 | 1.52 - 1.55  |      12       |
 | 1.56 - 1.59  |      13       |
 | 1.60 - 1.64  |      14       |
-| 1.65         |      15       |
+| 1.65 - 1.69  |      15       |
+| 1.70 - 1.72  |      16       |
+| 1.73 - 1.74  |      17       |
 
 Note that the compatibility policy for this feature might change in the future.
diff --git a/src/doc/rustc/src/platform-support/TEMPLATE.md b/src/doc/rustc/src/platform-support/TEMPLATE.md
index e64783fcf19..87dde722558 100644
--- a/src/doc/rustc/src/platform-support/TEMPLATE.md
+++ b/src/doc/rustc/src/platform-support/TEMPLATE.md
@@ -6,7 +6,7 @@ One-sentence description of the target (e.g. CPU, OS)
 
 ## Target maintainers
 
-- Some Person, `email@example.org`, https://github.com/...
+- Some Person, https://github.com/...
 
 ## Requirements
 
diff --git a/src/doc/unstable-book/src/compiler-flags/env.md b/src/doc/unstable-book/src/compiler-flags/env.md
new file mode 100644
index 00000000000..df0547dd24b
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/env.md
@@ -0,0 +1,26 @@
+# `env`
+
+The tracking issue for this feature is: [#118372](https://github.com/rust-lang/rust/issues/118372).
+
+------------------------
+
+This option flag allows to specify environment variables value at compile time to be
+used by `env!` and `option_env!` macros.
+
+When retrieving an environment variable value, the one specified by `--env` will take
+precedence. For example, if you want have `PATH=a` in your environment and pass:
+
+```bash
+rustc --env PATH=env
+```
+
+Then you will have:
+
+```rust,no_run
+assert_eq!(env!("PATH"), "env");
+```
+
+Please note that on Windows, environment variables are case insensitive but case
+preserving whereas `rustc`'s environment variables are case sensitive. For example,
+having `Path` in your environment (case insensitive) is different than using
+`rustc --env Path=...` (case sensitive).
diff --git a/src/etc/completions/x.py.fish b/src/etc/completions/x.py.fish
index 99096307039..95bce9e31a4 100644
--- a/src/etc/completions/x.py.fish
+++ b/src/etc/completions/x.py.fish
@@ -25,6 +25,7 @@ complete -c x.py -n "__fish_use_subcommand" -s v -l verbose -d 'use verbose outp
 complete -c x.py -n "__fish_use_subcommand" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_use_subcommand" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_use_subcommand" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_use_subcommand" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_use_subcommand" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_use_subcommand" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_use_subcommand" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -72,6 +73,7 @@ complete -c x.py -n "__fish_seen_subcommand_from build" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from build" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from build" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from build" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -106,6 +108,7 @@ complete -c x.py -n "__fish_seen_subcommand_from check" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from check" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from check" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from check" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from check" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from check" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from check" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from check" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -144,6 +147,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clippy" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clippy" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from clippy" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -177,6 +181,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fix" -s v -l verbose -d 'use ve
 complete -c x.py -n "__fish_seen_subcommand_from fix" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fix" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from fix" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -211,6 +216,7 @@ complete -c x.py -n "__fish_seen_subcommand_from fmt" -s v -l verbose -d 'use ve
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from fmt" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from fmt" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -246,6 +252,7 @@ complete -c x.py -n "__fish_seen_subcommand_from doc" -s v -l verbose -d 'use ve
 complete -c x.py -n "__fish_seen_subcommand_from doc" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from doc" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from doc" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -292,6 +299,7 @@ complete -c x.py -n "__fish_seen_subcommand_from test" -s v -l verbose -d 'use v
 complete -c x.py -n "__fish_seen_subcommand_from test" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from test" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from test" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -326,6 +334,7 @@ complete -c x.py -n "__fish_seen_subcommand_from bench" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from bench" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from bench" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from bench" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -360,6 +369,7 @@ complete -c x.py -n "__fish_seen_subcommand_from clean" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from clean" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from clean" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from clean" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -393,6 +403,7 @@ complete -c x.py -n "__fish_seen_subcommand_from dist" -s v -l verbose -d 'use v
 complete -c x.py -n "__fish_seen_subcommand_from dist" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from dist" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from dist" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -426,6 +437,7 @@ complete -c x.py -n "__fish_seen_subcommand_from install" -s v -l verbose -d 'us
 complete -c x.py -n "__fish_seen_subcommand_from install" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from install" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from install" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -460,6 +472,7 @@ complete -c x.py -n "__fish_seen_subcommand_from run" -s v -l verbose -d 'use ve
 complete -c x.py -n "__fish_seen_subcommand_from run" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from run" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from run" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -493,6 +506,7 @@ complete -c x.py -n "__fish_seen_subcommand_from setup" -s v -l verbose -d 'use
 complete -c x.py -n "__fish_seen_subcommand_from setup" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from setup" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from setup" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
@@ -527,6 +541,7 @@ complete -c x.py -n "__fish_seen_subcommand_from suggest" -s v -l verbose -d 'us
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -s i -l incremental -d 'use incremental compilation'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l include-default-paths -d 'include default paths in addition to the provided ones'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dry-run -d 'dry run; don\'t build anything'
+complete -c x.py -n "__fish_seen_subcommand_from suggest" -l dump-bootstrap-shims -d 'Indicates whether to dump the work done from bootstrap shims'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l json-output -d 'use message-format=json'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l bypass-bootstrap-lock -d 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)'
 complete -c x.py -n "__fish_seen_subcommand_from suggest" -l llvm-profile-generate -d 'generate PGO profile with llvm built for rustc'
diff --git a/src/etc/completions/x.py.ps1 b/src/etc/completions/x.py.ps1
index 7e926d10b3f..dabc3b16e4d 100644
--- a/src/etc/completions/x.py.ps1
+++ b/src/etc/completions/x.py.ps1
@@ -51,6 +51,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -105,6 +106,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -146,6 +148,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -191,6 +194,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -231,6 +235,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -272,6 +277,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -314,6 +320,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -367,6 +374,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -408,6 +416,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -449,6 +458,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -489,6 +499,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -529,6 +540,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -570,6 +582,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -610,6 +623,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
@@ -651,6 +665,7 @@ Register-ArgumentCompleter -Native -CommandName 'x.py' -ScriptBlock {
             [CompletionResult]::new('--incremental', 'incremental', [CompletionResultType]::ParameterName, 'use incremental compilation')
             [CompletionResult]::new('--include-default-paths', 'include-default-paths', [CompletionResultType]::ParameterName, 'include default paths in addition to the provided ones')
             [CompletionResult]::new('--dry-run', 'dry-run', [CompletionResultType]::ParameterName, 'dry run; don''t build anything')
+            [CompletionResult]::new('--dump-bootstrap-shims', 'dump-bootstrap-shims', [CompletionResultType]::ParameterName, 'Indicates whether to dump the work done from bootstrap shims')
             [CompletionResult]::new('--json-output', 'json-output', [CompletionResultType]::ParameterName, 'use message-format=json')
             [CompletionResult]::new('--bypass-bootstrap-lock', 'bypass-bootstrap-lock', [CompletionResultType]::ParameterName, 'Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)')
             [CompletionResult]::new('--llvm-profile-generate', 'llvm-profile-generate', [CompletionResultType]::ParameterName, 'generate PGO profile with llvm built for rustc')
diff --git a/src/etc/completions/x.py.sh b/src/etc/completions/x.py.sh
index 78754f6e7b2..f739f46b88b 100644
--- a/src/etc/completions/x.py.sh
+++ b/src/etc/completions/x.py.sh
@@ -61,7 +61,7 @@ _x.py() {
 
     case "${cmd}" in
         x.py)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]... build check clippy fix fmt doc test bench clean dist install run setup suggest"
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 1 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -171,7 +171,7 @@ _x.py() {
             return 0
             ;;
         x.py__bench)
-            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --test-args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -285,7 +285,7 @@ _x.py() {
             return 0
             ;;
         x.py__build)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -395,7 +395,7 @@ _x.py() {
             return 0
             ;;
         x.py__check)
-            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all-targets --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -505,7 +505,7 @@ _x.py() {
             return 0
             ;;
         x.py__clean)
-            opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --all --stage --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -615,7 +615,7 @@ _x.py() {
             return 0
             ;;
         x.py__clippy)
-            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-A -D -W -F -v -i -j -h --fix --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -741,7 +741,7 @@ _x.py() {
             return 0
             ;;
         x.py__dist)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -851,7 +851,7 @@ _x.py() {
             return 0
             ;;
         x.py__doc)
-            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --open --json --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -961,7 +961,7 @@ _x.py() {
             return 0
             ;;
         x.py__fix)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1071,7 +1071,7 @@ _x.py() {
             return 0
             ;;
         x.py__fmt)
-            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --check --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1181,7 +1181,7 @@ _x.py() {
             return 0
             ;;
         x.py__install)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1291,7 +1291,7 @@ _x.py() {
             return 0
             ;;
         x.py__run)
-            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --args --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1405,7 +1405,7 @@ _x.py() {
             return 0
             ;;
         x.py__setup)
-            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [<PROFILE>|hook|vscode|link] [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1515,7 +1515,7 @@ _x.py() {
             return 0
             ;;
         x.py__suggest)
-            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --run --verbose --incremental --config --build-dir --build --host --target --exclude --skip --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
@@ -1625,7 +1625,7 @@ _x.py() {
             return 0
             ;;
         x.py__test)
-            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
+            opts="-v -i -j -h --no-fail-fast --skip --test-args --rustc-args --no-doc --doc --bless --extra-checks --force-rerun --only-modified --compare-mode --pass --run --rustfix-coverage --verbose --incremental --config --build-dir --build --host --target --exclude --include-default-paths --rustc-error-format --on-fail --dry-run --dump-bootstrap-shims --stage --keep-stage --keep-stage-std --src --jobs --warnings --error-format --json-output --color --bypass-bootstrap-lock --llvm-skip-rebuild --rust-profile-generate --rust-profile-use --llvm-profile-use --llvm-profile-generate --enable-bolt-settings --skip-stage0-validation --reproducible-artifact --set --help [PATHS]... [ARGS]..."
             if [[ ${cur} == -* || ${COMP_CWORD} -eq 2 ]] ; then
                 COMPREPLY=( $(compgen -W "${opts}" -- "${cur}") )
                 return 0
diff --git a/src/etc/completions/x.py.zsh b/src/etc/completions/x.py.zsh
index 29dfc292615..639f0487f8b 100644
--- a/src/etc/completions/x.py.zsh
+++ b/src/etc/completions/x.py.zsh
@@ -45,6 +45,7 @@ _x.py() {
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -95,6 +96,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -138,6 +140,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -185,6 +188,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -227,6 +231,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -270,6 +275,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -314,6 +320,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -369,6 +376,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -412,6 +420,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -455,6 +464,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -497,6 +507,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -539,6 +550,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -582,6 +594,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -624,6 +637,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
@@ -668,6 +682,7 @@ _arguments "${_arguments_options[@]}" \
 '--incremental[use incremental compilation]' \
 '--include-default-paths[include default paths in addition to the provided ones]' \
 '--dry-run[dry run; don'\''t build anything]' \
+'--dump-bootstrap-shims[Indicates whether to dump the work done from bootstrap shims]' \
 '--json-output[use message-format=json]' \
 '--bypass-bootstrap-lock[Bootstrap uses this value to decide whether it should bypass locking the build process. This is rarely needed (e.g., compiling the std library for different targets in parallel)]' \
 '--llvm-profile-generate[generate PGO profile with llvm built for rustc]' \
diff --git a/src/librustdoc/clean/auto_trait.rs b/src/librustdoc/clean/auto_trait.rs
index 007c5e113b7..e692f4ef72e 100644
--- a/src/librustdoc/clean/auto_trait.rs
+++ b/src/librustdoc/clean/auto_trait.rs
@@ -1,9 +1,7 @@
-use rustc_data_structures::fx::FxHashSet;
 use rustc_hir as hir;
 use rustc_hir::lang_items::LangItem;
-use rustc_middle::ty::{self, Region, RegionVid, TypeFoldable};
+use rustc_middle::ty::{Region, RegionVid, TypeFoldable};
 use rustc_trait_selection::traits::auto_trait::{self, AutoTraitResult};
-use thin_vec::ThinVec;
 
 use std::fmt::Debug;
 
diff --git a/src/librustdoc/clean/cfg/tests.rs b/src/librustdoc/clean/cfg/tests.rs
index bb62660e194..20bcf1abf41 100644
--- a/src/librustdoc/clean/cfg/tests.rs
+++ b/src/librustdoc/clean/cfg/tests.rs
@@ -1,8 +1,8 @@
 use super::*;
 
-use rustc_ast::{LitKind, MetaItemLit, Path, StrStyle};
+use rustc_ast::{MetaItemLit, Path, StrStyle};
 use rustc_span::create_default_session_globals_then;
-use rustc_span::symbol::{kw, Ident, Symbol};
+use rustc_span::symbol::{kw, Ident};
 use rustc_span::DUMMY_SP;
 use thin_vec::thin_vec;
 
diff --git a/src/librustdoc/clean/render_macro_matchers.rs b/src/librustdoc/clean/render_macro_matchers.rs
index 66d10f2368b..605f9e496c7 100644
--- a/src/librustdoc/clean/render_macro_matchers.rs
+++ b/src/librustdoc/clean/render_macro_matchers.rs
@@ -40,7 +40,7 @@ pub(super) fn render_macro_matcher(tcx: TyCtxt<'_>, matcher: &TokenTree) -> Stri
     printer.zerobreak();
     printer.ibox(0);
     match matcher {
-        TokenTree::Delimited(_span, _delim, tts) => print_tts(&mut printer, tts),
+        TokenTree::Delimited(_span, _spacing, _delim, tts) => print_tts(&mut printer, tts),
         // Matcher which is not a Delimited is unexpected and should've failed
         // to compile, but we render whatever it is wrapped in parens.
         TokenTree::Token(..) => print_tt(&mut printer, matcher),
@@ -97,7 +97,7 @@ fn print_tt(printer: &mut Printer<'_>, tt: &TokenTree) {
                 printer.hardbreak()
             }
         }
-        TokenTree::Delimited(_span, delim, tts) => {
+        TokenTree::Delimited(_span, _spacing, delim, tts) => {
             let open_delim = printer.token_kind_to_string(&token::OpenDelim(*delim));
             printer.word(open_delim);
             if !tts.is_empty() {
@@ -158,7 +158,7 @@ fn print_tts(printer: &mut Printer<'_>, tts: &TokenStream) {
                 (_, token::Pound) => (true, Pound),
                 (_, _) => (true, Other),
             },
-            TokenTree::Delimited(_, delim, _) => match (state, delim) {
+            TokenTree::Delimited(.., delim, _) => match (state, delim) {
                 (Dollar, Delimiter::Parenthesis) => (false, DollarParen),
                 (Pound | PoundBang, Delimiter::Bracket) => (false, Other),
                 (Ident, Delimiter::Parenthesis | Delimiter::Bracket) => (false, Other),
diff --git a/src/librustdoc/clean/types.rs b/src/librustdoc/clean/types.rs
index 7a5cf803137..0a14404d689 100644
--- a/src/librustdoc/clean/types.rs
+++ b/src/librustdoc/clean/types.rs
@@ -31,7 +31,7 @@ use rustc_resolve::rustdoc::{
 use rustc_session::Session;
 use rustc_span::hygiene::MacroKind;
 use rustc_span::symbol::{kw, sym, Ident, Symbol};
-use rustc_span::{self, FileName, Loc, DUMMY_SP};
+use rustc_span::{FileName, Loc, DUMMY_SP};
 use rustc_target::abi::VariantIdx;
 use rustc_target::spec::abi::Abi;
 
diff --git a/src/librustdoc/clean/types/tests.rs b/src/librustdoc/clean/types/tests.rs
index ee7c0068eb4..4befce07170 100644
--- a/src/librustdoc/clean/types/tests.rs
+++ b/src/librustdoc/clean/types/tests.rs
@@ -1,8 +1,7 @@
 use super::*;
 
-use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragment, DocFragmentKind};
-use rustc_span::symbol::Symbol;
-use rustc_span::{create_default_session_globals_then, DUMMY_SP};
+use rustc_resolve::rustdoc::{unindent_doc_fragments, DocFragmentKind};
+use rustc_span::create_default_session_globals_then;
 
 fn create_doc_fragment(s: &str) -> Vec<DocFragment> {
     vec![DocFragment {
diff --git a/src/librustdoc/docfs.rs b/src/librustdoc/docfs.rs
index 82c1a503924..1f7abdfc315 100644
--- a/src/librustdoc/docfs.rs
+++ b/src/librustdoc/docfs.rs
@@ -12,7 +12,6 @@ use std::cmp::max;
 use std::fs;
 use std::io;
 use std::path::{Path, PathBuf};
-use std::string::ToString;
 use std::sync::mpsc::Sender;
 use std::thread::available_parallelism;
 use threadpool::ThreadPool;
diff --git a/src/librustdoc/html/render/mod.rs b/src/librustdoc/html/render/mod.rs
index 58599de76ea..34350c2ed3a 100644
--- a/src/librustdoc/html/render/mod.rs
+++ b/src/librustdoc/html/render/mod.rs
@@ -45,7 +45,6 @@ use std::iter::Peekable;
 use std::path::PathBuf;
 use std::rc::Rc;
 use std::str;
-use std::string::ToString;
 
 use askama::Template;
 use rustc_attr::{ConstStability, DeprecatedSince, Deprecation, StabilityLevel, StableSince};
diff --git a/src/librustdoc/html/static/js/search.js b/src/librustdoc/html/static/js/search.js
index 8f68796ad26..a521bf66bed 100644
--- a/src/librustdoc/html/static/js/search.js
+++ b/src/librustdoc/html/static/js/search.js
@@ -243,7 +243,7 @@ function initSearch(rawSearchIndex) {
      * Map from normalized type names to integers. Used to make type search
      * more efficient.
      *
-     * @type {Map<string, integer>}
+     * @type {Map<string, {id: integer, assocOnly: boolean}>}
      */
     let typeNameIdMap;
     const ALIASES = new Map();
@@ -270,19 +270,22 @@ function initSearch(rawSearchIndex) {
      * get the same ID.
      *
      * @param {string} name
+     * @param {boolean} isAssocType - True if this is an assoc type
      *
      * @returns {integer}
      */
-    function buildTypeMapIndex(name) {
+    function buildTypeMapIndex(name, isAssocType) {
         if (name === "" || name === null) {
             return null;
         }
 
         if (typeNameIdMap.has(name)) {
-            return typeNameIdMap.get(name);
+            const obj = typeNameIdMap.get(name);
+            obj.assocOnly = isAssocType && obj.assocOnly;
+            return obj.id;
         } else {
             const id = typeNameIdMap.size;
-            typeNameIdMap.set(name, id);
+            typeNameIdMap.set(name, {id, assocOnly: isAssocType});
             return id;
         }
     }
@@ -1430,7 +1433,7 @@ function initSearch(rawSearchIndex) {
                             return true;
                         }
                     } else if (unifyFunctionTypes(
-                        fnType.generics,
+                        [...fnType.generics, ...Array.from(fnType.bindings.values()).flat() ],
                         queryElems,
                         whereClause,
                         mgens ? new Map(mgens) : null,
@@ -2129,17 +2132,20 @@ function initSearch(rawSearchIndex) {
              * See `buildTypeMapIndex` for more information.
              *
              * @param {QueryElement} elem
+             * @param {boolean} isAssocType
              */
-            function convertNameToId(elem) {
-                if (typeNameIdMap.has(elem.pathLast)) {
-                    elem.id = typeNameIdMap.get(elem.pathLast);
+            function convertNameToId(elem, isAssocType) {
+                if (typeNameIdMap.has(elem.pathLast) &&
+                    (isAssocType || !typeNameIdMap.get(elem.pathLast).assocOnly)) {
+                    elem.id = typeNameIdMap.get(elem.pathLast).id;
                 } else if (!parsedQuery.literalSearch) {
                     let match = null;
                     let matchDist = maxEditDistance + 1;
                     let matchName = "";
-                    for (const [name, id] of typeNameIdMap) {
+                    for (const [name, {id, assocOnly}] of typeNameIdMap) {
                         const dist = editDistance(name, elem.pathLast, maxEditDistance);
-                        if (dist <= matchDist && dist <= maxEditDistance) {
+                        if (dist <= matchDist && dist <= maxEditDistance &&
+                            (isAssocType || !assocOnly)) {
                             if (dist === matchDist && matchName > name) {
                                 continue;
                             }
@@ -2206,12 +2212,13 @@ function initSearch(rawSearchIndex) {
                                 name,
                                 " does not exist",
                             ];
+                            return [null, []];
                         }
                         for (const elem2 of constraints) {
                             convertNameToId(elem2);
                         }
 
-                        return [typeNameIdMap.get(name), constraints];
+                        return [typeNameIdMap.get(name).id, constraints];
                     })
                 );
             }
@@ -2720,7 +2727,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
      *
      * @param {RawFunctionType} type
      */
-    function buildItemSearchType(type, lowercasePaths) {
+    function buildItemSearchType(type, lowercasePaths, isAssocType) {
         const PATH_INDEX_DATA = 0;
         const GENERICS_DATA = 1;
         const BINDINGS_DATA = 2;
@@ -2749,7 +2756,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
                     //
                     // As a result, the key should never have generics on it.
                     return [
-                        buildItemSearchType(assocType, lowercasePaths).id,
+                        buildItemSearchType(assocType, lowercasePaths, true).id,
                         buildItemSearchTypeAll(constraints, lowercasePaths),
                     ];
                 }));
@@ -2780,7 +2787,7 @@ ${item.displayPath}<span class="${type}">${name}</span>\
         }
         const item = lowercasePaths[pathIndex - 1];
         return {
-            id: buildTypeMapIndex(item.name),
+            id: buildTypeMapIndex(item.name, isAssocType),
             ty: item.ty,
             path: item.path,
             generics,
diff --git a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
index d4828778be2..b1aa472aa03 100644
--- a/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
+++ b/src/tools/clippy/clippy_lints/src/crate_in_macro_def.rs
@@ -92,7 +92,7 @@ fn contains_unhygienic_crate_reference(tts: &TokenStream) -> Option<Span> {
         {
             return Some(span);
         }
-        if let TokenTree::Delimited(_, _, tts) = &curr {
+        if let TokenTree::Delimited(.., tts) = &curr {
             let span = contains_unhygienic_crate_reference(tts);
             if span.is_some() {
                 return span;
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index b440e267efe..3627096ed91 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -684,7 +684,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::unit_types::UNIT_ARG_INFO,
     crate::unit_types::UNIT_CMP_INFO,
     crate::unnamed_address::FN_ADDRESS_COMPARISONS_INFO,
-    crate::unnamed_address::VTABLE_ADDRESS_COMPARISONS_INFO,
     crate::unnecessary_box_returns::UNNECESSARY_BOX_RETURNS_INFO,
     crate::unnecessary_map_on_constructor::UNNECESSARY_MAP_ON_CONSTRUCTOR_INFO,
     crate::unnecessary_owned_empty_strings::UNNECESSARY_OWNED_EMPTY_STRINGS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/derive.rs b/src/tools/clippy/clippy_lints/src/derive.rs
index 61faaa10b8a..d8abe411030 100644
--- a/src/tools/clippy/clippy_lints/src/derive.rs
+++ b/src/tools/clippy/clippy_lints/src/derive.rs
@@ -450,12 +450,12 @@ fn check_partial_eq_without_eq<'tcx>(cx: &LateContext<'tcx>, span: Span, trait_r
         && let Some(def_id) = trait_ref.trait_def_id()
         && cx.tcx.is_diagnostic_item(sym::PartialEq, def_id)
         && let param_env = param_env_for_derived_eq(cx.tcx, adt.did(), eq_trait_def_id)
-        && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[])
+        && !implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(),&[])
         // If all of our fields implement `Eq`, we can implement `Eq` too
         && adt
             .all_fields()
             .map(|f| f.ty(cx.tcx, args))
-            .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, &[]))
+            .all(|ty| implements_trait_with_env(cx.tcx, param_env, ty, eq_trait_def_id, adt.did(), &[]))
     {
         span_lint_and_sugg(
             cx,
diff --git a/src/tools/clippy/clippy_lints/src/escape.rs b/src/tools/clippy/clippy_lints/src/escape.rs
index ae1e69a4f23..3452f98c5aa 100644
--- a/src/tools/clippy/clippy_lints/src/escape.rs
+++ b/src/tools/clippy/clippy_lints/src/escape.rs
@@ -1,5 +1,5 @@
 use clippy_utils::diagnostics::span_lint_hir;
-use rustc_hir::{self, intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
+use rustc_hir::{intravisit, AssocItemKind, Body, FnDecl, HirId, HirIdSet, Impl, ItemKind, Node, Pat, PatKind};
 use rustc_hir_typeck::expr_use_visitor::{Delegate, ExprUseVisitor, PlaceBase, PlaceWithHirId};
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
diff --git a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
index 9a66cbde53c..4811691c80d 100644
--- a/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
+++ b/src/tools/clippy/clippy_lints/src/implied_bounds_in_impls.rs
@@ -194,6 +194,10 @@ fn is_same_generics<'tcx>(
         .enumerate()
         .skip(1) // skip `Self` implicit arg
         .all(|(arg_index, arg)| {
+            if [implied_by_generics.host_effect_index, implied_generics.host_effect_index].contains(&Some(arg_index)) {
+                // skip host effect params in determining whether generics are same
+                return true;
+            }
             if let Some(ty) = arg.as_type() {
                 if let &ty::Param(ty::ParamTy { index, .. }) = ty.kind()
                     // `index == 0` means that it's referring to `Self`,
diff --git a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
index 1c2b7a169fc..c7980060807 100644
--- a/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/explicit_iter_loop.rs
@@ -118,7 +118,7 @@ fn is_ref_iterable<'tcx>(
             .liberate_late_bound_regions(fn_id, cx.tcx.fn_sig(fn_id).skip_binder())
         && let &[req_self_ty, req_res_ty] = &**sig.inputs_and_output
         && let param_env = cx.tcx.param_env(fn_id)
-        && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, &[])
+        && implements_trait_with_env(cx.tcx, param_env, req_self_ty, trait_id, fn_id, &[])
         && let Some(into_iter_ty) =
             make_normalized_projection_with_regions(cx.tcx, param_env, trait_id, sym!(IntoIter), [req_self_ty])
         && let req_res_ty = normalize_with_regions(cx.tcx, param_env, req_res_ty)
diff --git a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
index 40d56240b9d..fda6c9749d4 100644
--- a/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/manual_memcpy.rs
@@ -12,7 +12,6 @@ use rustc_lint::LateContext;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::sym;
 use std::fmt::Display;
-use std::iter::Iterator;
 
 /// Checks for `for` loops that sequentially copy items from one slice-like
 /// object to another.
diff --git a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
index e2be861a708..28abecd0429 100644
--- a/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/needless_range_loop.rs
@@ -13,7 +13,7 @@ use rustc_lint::LateContext;
 use rustc_middle::middle::region;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::symbol::{sym, Symbol};
-use std::iter::{self, Iterator};
+use std::iter::{self};
 use std::mem;
 
 /// Checks for looping over a range and then indexing a sequence with it.
diff --git a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
index cc054cb4669..62bc663191f 100644
--- a/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/never_loop.rs
@@ -8,7 +8,7 @@ use rustc_errors::Applicability;
 use rustc_hir::{Block, Destination, Expr, ExprKind, HirId, InlineAsmOperand, Pat, Stmt, StmtKind};
 use rustc_lint::LateContext;
 use rustc_span::{sym, Span};
-use std::iter::{once, Iterator};
+use std::iter::once;
 
 pub(super) fn check<'tcx>(
     cx: &LateContext<'tcx>,
diff --git a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
index 15e11fd386c..f4eaf649f77 100644
--- a/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/same_item_push.rs
@@ -11,7 +11,6 @@ use rustc_hir::{BindingAnnotation, Block, Expr, ExprKind, HirId, Mutability, Nod
 use rustc_lint::LateContext;
 use rustc_span::symbol::sym;
 use rustc_span::SyntaxContext;
-use std::iter::Iterator;
 
 /// Detects for loop pushing the same item into a Vec
 pub(super) fn check<'tcx>(
diff --git a/src/tools/clippy/clippy_lints/src/loops/utils.rs b/src/tools/clippy/clippy_lints/src/loops/utils.rs
index 38fdca573c6..e685274adb8 100644
--- a/src/tools/clippy/clippy_lints/src/loops/utils.rs
+++ b/src/tools/clippy/clippy_lints/src/loops/utils.rs
@@ -9,7 +9,6 @@ use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty};
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::{sym, Symbol};
-use std::iter::Iterator;
 
 #[derive(Debug, PartialEq, Eq)]
 enum IncrementVisitorVarState {
diff --git a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
index 575c2d8f157..826c3de1db5 100644
--- a/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
+++ b/src/tools/clippy/clippy_lints/src/methods/option_map_unwrap_or.rs
@@ -6,7 +6,7 @@ use rustc_data_structures::fx::FxHashSet;
 use rustc_errors::Applicability;
 use rustc_hir::def::Res;
 use rustc_hir::intravisit::{walk_path, Visitor};
-use rustc_hir::{self, ExprKind, HirId, Node, PatKind, Path, QPath};
+use rustc_hir::{ExprKind, HirId, Node, PatKind, Path, QPath};
 use rustc_lint::LateContext;
 use rustc_middle::hir::nested_filter;
 use rustc_span::{sym, Span};
diff --git a/src/tools/clippy/clippy_lints/src/missing_inline.rs b/src/tools/clippy/clippy_lints/src/missing_inline.rs
index 07bcbfc4ff4..7393b39c8f6 100644
--- a/src/tools/clippy/clippy_lints/src/missing_inline.rs
+++ b/src/tools/clippy/clippy_lints/src/missing_inline.rs
@@ -1,7 +1,7 @@
 use clippy_utils::diagnostics::span_lint;
 use rustc_ast::ast;
 use rustc_hir as hir;
-use rustc_lint::{self, LateContext, LateLintPass, LintContext};
+use rustc_lint::{LateContext, LateLintPass, LintContext};
 use rustc_session::declare_lint_pass;
 use rustc_span::{sym, Span};
 
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
index 27da44812eb..2c5c3dcaa75 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_value.rs
@@ -186,6 +186,7 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByValue {
                         cx.param_env,
                         ty,
                         t,
+                        None,
                         [Option::<ty::GenericArg<'tcx>>::None],
                     )
                 })
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index 613f1ecc6fb..9f5897d2ca7 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -58,4 +58,5 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::undropped_manually_drops", "undropped_manually_drops"),
     ("clippy::unknown_clippy_lints", "unknown_lints"),
     ("clippy::unused_label", "unused_labels"),
+    ("clippy::vtable_address_comparisons", "ambiguous_wide_pointer_comparisons"),
 ];
diff --git a/src/tools/clippy/clippy_lints/src/unnamed_address.rs b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
index 41e13e13e56..cd2dacc9f09 100644
--- a/src/tools/clippy/clippy_lints/src/unnamed_address.rs
+++ b/src/tools/clippy/clippy_lints/src/unnamed_address.rs
@@ -1,9 +1,8 @@
-use clippy_utils::diagnostics::{span_lint, span_lint_and_help};
+use clippy_utils::diagnostics::span_lint;
 use rustc_hir::{BinOpKind, Expr, ExprKind};
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::ty;
 use rustc_session::declare_lint_pass;
-use rustc_span::sym;
 
 declare_clippy_lint! {
     /// ### What it does
@@ -29,31 +28,7 @@ declare_clippy_lint! {
     "comparison with an address of a function item"
 }
 
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparisons with an address of a trait vtable.
-    ///
-    /// ### Why is this bad?
-    /// Comparing trait objects pointers compares an vtable addresses which
-    /// are not guaranteed to be unique and could vary between different code generation units.
-    /// Furthermore vtables for different types could have the same address after being merged
-    /// together.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// let a: Rc<dyn Trait> = ...
-    /// let b: Rc<dyn Trait> = ...
-    /// if Rc::ptr_eq(&a, &b) {
-    ///     ...
-    /// }
-    /// ```
-    #[clippy::version = "1.44.0"]
-    pub VTABLE_ADDRESS_COMPARISONS,
-    correctness,
-    "comparison with an address of a trait vtable"
-}
-
-declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS, VTABLE_ADDRESS_COMPARISONS]);
+declare_lint_pass!(UnnamedAddress => [FN_ADDRESS_COMPARISONS]);
 
 impl LateLintPass<'_> for UnnamedAddress {
     fn check_expr(&mut self, cx: &LateContext<'_>, expr: &Expr<'_>) {
@@ -64,51 +39,12 @@ impl LateLintPass<'_> for UnnamedAddress {
             )
         }
 
-        fn is_trait_ptr(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-            match cx.typeck_results().expr_ty_adjusted(expr).kind() {
-                ty::RawPtr(ty::TypeAndMut { ty, .. }) => ty.is_trait(),
-                _ => false,
-            }
-        }
-
         fn is_fn_def(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
             matches!(cx.typeck_results().expr_ty(expr).kind(), ty::FnDef(..))
         }
 
         if let ExprKind::Binary(binop, left, right) = expr.kind
             && is_comparison(binop.node)
-            && is_trait_ptr(cx, left)
-            && is_trait_ptr(cx, right)
-        {
-            span_lint_and_help(
-                cx,
-                VTABLE_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing trait object pointers compares a non-unique vtable address",
-                None,
-                "consider extracting and comparing data pointers only",
-            );
-        }
-
-        if let ExprKind::Call(func, [ref _left, ref _right]) = expr.kind
-            && let ExprKind::Path(ref func_qpath) = func.kind
-            && let Some(def_id) = cx.qpath_res(func_qpath, func.hir_id).opt_def_id()
-            && cx.tcx.is_diagnostic_item(sym::ptr_eq, def_id)
-            && let ty_param = cx.typeck_results().node_args(func.hir_id).type_at(0)
-            && ty_param.is_trait()
-        {
-            span_lint_and_help(
-                cx,
-                VTABLE_ADDRESS_COMPARISONS,
-                expr.span,
-                "comparing trait object pointers compares a non-unique vtable address",
-                None,
-                "consider extracting and comparing data pointers only",
-            );
-        }
-
-        if let ExprKind::Binary(binop, left, right) = expr.kind
-            && is_comparison(binop.node)
             && cx.typeck_results().expr_ty_adjusted(left).is_fn_ptr()
             && cx.typeck_results().expr_ty_adjusted(right).is_fn_ptr()
             && (is_fn_def(cx, left) || is_fn_def(cx, right))
diff --git a/src/tools/clippy/clippy_utils/src/ty.rs b/src/tools/clippy/clippy_utils/src/ty.rs
index 1e748a46922..868c92f2f54 100644
--- a/src/tools/clippy/clippy_utils/src/ty.rs
+++ b/src/tools/clippy/clippy_utils/src/ty.rs
@@ -214,7 +214,8 @@ pub fn implements_trait<'tcx>(
     trait_id: DefId,
     args: &[GenericArg<'tcx>],
 ) -> bool {
-    implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, args.iter().map(|&x| Some(x)))
+    let callee_id = cx.enclosing_body.map(|body| cx.tcx.hir().body_owner(body).owner.to_def_id());
+    implements_trait_with_env_from_iter(cx.tcx, cx.param_env, ty, trait_id, callee_id, args.iter().map(|&x| Some(x)))
 }
 
 /// Same as `implements_trait` but allows using a `ParamEnv` different from the lint context.
@@ -223,9 +224,10 @@ pub fn implements_trait_with_env<'tcx>(
     param_env: ParamEnv<'tcx>,
     ty: Ty<'tcx>,
     trait_id: DefId,
+    callee_id: DefId,
     args: &[GenericArg<'tcx>],
 ) -> bool {
-    implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, args.iter().map(|&x| Some(x)))
+    implements_trait_with_env_from_iter(tcx, param_env, ty, trait_id, Some(callee_id), args.iter().map(|&x| Some(x)))
 }
 
 /// Same as `implements_trait_from_env` but takes the arguments as an iterator.
@@ -234,6 +236,7 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
     param_env: ParamEnv<'tcx>,
     ty: Ty<'tcx>,
     trait_id: DefId,
+    callee_id: Option<DefId>,
     args: impl IntoIterator<Item = impl Into<Option<GenericArg<'tcx>>>>,
 ) -> bool {
     // Clippy shouldn't have infer types
@@ -245,20 +248,29 @@ pub fn implements_trait_with_env_from_iter<'tcx>(
     }
 
     let infcx = tcx.infer_ctxt().build();
+    let args = args.into_iter().map(|arg| {
+        arg.into().unwrap_or_else(|| {
+            let orig = TypeVariableOrigin {
+                kind: TypeVariableOriginKind::MiscVariable,
+                span: DUMMY_SP,
+            };
+            infcx.next_ty_var(orig).into()
+        })
+    }).collect::<Vec<_>>();
+
+    // If an effect arg was not specified, we need to specify it.
+    let effect_arg = if tcx.generics_of(trait_id).host_effect_index.is_some_and(|x| args.get(x - 1).is_none()) {
+        Some(GenericArg::from(callee_id.map(|def_id| tcx.expected_host_effect_param_for_body(def_id)).unwrap_or(tcx.consts.true_)))
+    } else {
+        None
+    };
+
     let trait_ref = TraitRef::new(
         tcx,
         trait_id,
         Some(GenericArg::from(ty))
             .into_iter()
-            .chain(args.into_iter().map(|arg| {
-                arg.into().unwrap_or_else(|| {
-                    let orig = TypeVariableOrigin {
-                        kind: TypeVariableOriginKind::MiscVariable,
-                        span: DUMMY_SP,
-                    };
-                    infcx.next_ty_var(orig).into()
-                })
-            })),
+            .chain(args).chain(effect_arg),
     );
 
     debug_assert_matches!(
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index 4df9be2c21d..31f1ee6a86d 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -51,6 +51,7 @@
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 #![warn(clippy::almost_complete_range)]
 #![warn(clippy::disallowed_names)]
 #![warn(clippy::blocks_in_if_conditions)]
@@ -107,5 +108,6 @@
 #![warn(undropped_manually_drops)]
 #![warn(unknown_lints)]
 #![warn(unused_labels)]
+#![warn(ambiguous_wide_pointer_comparisons)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index 940e60068e7..325bc356c15 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -51,6 +51,7 @@
 #![allow(undropped_manually_drops)]
 #![allow(unknown_lints)]
 #![allow(unused_labels)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 #![warn(clippy::almost_complete_letter_range)]
 #![warn(clippy::blacklisted_name)]
 #![warn(clippy::block_in_if_condition_expr)]
@@ -107,5 +108,6 @@
 #![warn(clippy::undropped_manually_drops)]
 #![warn(clippy::unknown_clippy_lints)]
 #![warn(clippy::unused_label)]
+#![warn(clippy::vtable_address_comparisons)]
 
 fn main() {}
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index 30824e154b8..a6164338c20 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -8,334 +8,340 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = help: to override `-D warnings` add `#[allow(renamed_and_removed_lints)]`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::incorrect_clone_impl_on_copy_type` has been renamed to `clippy::non_canonical_clone_impl`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::incorrect_clone_impl_on_copy_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_clone_impl`
 
 error: lint `clippy::incorrect_partial_ord_impl_on_ord_type` has been renamed to `clippy::non_canonical_partial_ord_impl`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::incorrect_partial_ord_impl_on_ord_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::non_canonical_partial_ord_impl`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::unwrap_or_else_default` has been renamed to `clippy::unwrap_or_default`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::unwrap_or_else_default)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_or_default`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `invalid_reference_casting`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_reference_casting`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::fn_null_check` has been renamed to `useless_ptr_null_checks`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:93:9
    |
 LL | #![warn(clippy::fn_null_check)]
    |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `useless_ptr_null_checks`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:99:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:100:9
+  --> $DIR/rename.rs:101:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:101:9
+  --> $DIR/rename.rs:102:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:102:9
+  --> $DIR/rename.rs:103:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:103:9
+  --> $DIR/rename.rs:104:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:104:9
+  --> $DIR/rename.rs:105:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:105:9
+  --> $DIR/rename.rs:106:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:106:9
+  --> $DIR/rename.rs:107:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> $DIR/rename.rs:107:9
+  --> $DIR/rename.rs:108:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:108:9
+  --> $DIR/rename.rs:109:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:109:9
+  --> $DIR/rename.rs:110:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 56 previous errors
+error: lint `clippy::vtable_address_comparisons` has been renamed to `ambiguous_wide_pointer_comparisons`
+  --> $DIR/rename.rs:111:9
+   |
+LL | #![warn(clippy::vtable_address_comparisons)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `ambiguous_wide_pointer_comparisons`
+
+error: aborting due to 57 previous errors
 
diff --git a/src/tools/clippy/tests/ui/vtable_address_comparisons.rs b/src/tools/clippy/tests/ui/vtable_address_comparisons.rs
deleted file mode 100644
index 75647c027e1..00000000000
--- a/src/tools/clippy/tests/ui/vtable_address_comparisons.rs
+++ /dev/null
@@ -1,52 +0,0 @@
-use std::fmt::Debug;
-use std::ptr;
-use std::rc::Rc;
-use std::sync::Arc;
-
-#[warn(clippy::vtable_address_comparisons)]
-#[allow(clippy::borrow_as_ptr)]
-
-fn main() {
-    let a: *const dyn Debug = &1 as &dyn Debug;
-    let b: *const dyn Debug = &1 as &dyn Debug;
-
-    // These should fail:
-    let _ = a == b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a != b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a < b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a <= b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a > b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    let _ = a >= b;
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-    ptr::eq(a, b);
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-
-    let a = &1 as &dyn Debug;
-    let b = &1 as &dyn Debug;
-    ptr::eq(a, b);
-    //~^ ERROR: comparing trait object pointers compares a non-unique vtable address
-
-    // These should be fine:
-    let a = &1;
-    ptr::eq(a, a);
-
-    let a = Rc::new(1);
-    Rc::ptr_eq(&a, &a);
-
-    let a = Arc::new(1);
-    Arc::ptr_eq(&a, &a);
-
-    let a: Rc<dyn Debug> = Rc::new(1);
-    Rc::ptr_eq(&a, &a);
-
-    let a: Arc<dyn Debug> = Arc::new(1);
-    Arc::ptr_eq(&a, &a);
-
-    let a: &[u8] = b"";
-    ptr::eq(a, a);
-}
diff --git a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr b/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
deleted file mode 100644
index 83c82f3796e..00000000000
--- a/src/tools/clippy/tests/ui/vtable_address_comparisons.stderr
+++ /dev/null
@@ -1,68 +0,0 @@
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:14:13
-   |
-LL |     let _ = a == b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-   = note: `-D clippy::vtable-address-comparisons` implied by `-D warnings`
-   = help: to override `-D warnings` add `#[allow(clippy::vtable_address_comparisons)]`
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:16:13
-   |
-LL |     let _ = a != b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:18:13
-   |
-LL |     let _ = a < b;
-   |             ^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:20:13
-   |
-LL |     let _ = a <= b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:22:13
-   |
-LL |     let _ = a > b;
-   |             ^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:24:13
-   |
-LL |     let _ = a >= b;
-   |             ^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:26:5
-   |
-LL |     ptr::eq(a, b);
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: comparing trait object pointers compares a non-unique vtable address
-  --> $DIR/vtable_address_comparisons.rs:31:5
-   |
-LL |     ptr::eq(a, b);
-   |     ^^^^^^^^^^^^^
-   |
-   = help: consider extracting and comparing data pointers only
-
-error: aborting due to 8 previous errors
-
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 73e201aa309..7987fadbfc4 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-61afc9c92896a43fce92bd5e3bba6274c5e3e960
+e2a3c9b3f0895c866c104bd2fff2a8bf16eaf964
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index 1a11879fa90..b964b1f9ec2 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -2,13 +2,10 @@ use smallvec::SmallVec;
 use std::fmt;
 
 use rustc_data_structures::fx::FxHashSet;
-use rustc_middle::mir::interpret::{alloc_range, AllocId, AllocRange, InterpError};
 use rustc_span::{Span, SpanData};
 use rustc_target::abi::Size;
 
-use crate::borrow_tracker::{
-    stacked_borrows::Permission, AccessKind, GlobalStateInner, ProtectorKind,
-};
+use crate::borrow_tracker::{AccessKind, GlobalStateInner, ProtectorKind};
 use crate::*;
 
 /// Error reporting
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index 1df2b1b8391..eac315d0436 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -18,7 +18,7 @@ use rustc_target::abi::{Abi, Size};
 
 use crate::borrow_tracker::{
     stacked_borrows::diagnostics::{AllocHistory, DiagnosticCx, DiagnosticCxBuilder},
-    AccessKind, GlobalStateInner, ProtectorKind, RetagFields,
+    AccessKind, GlobalStateInner, ProtectorKind,
 };
 use crate::*;
 
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index e902939290a..573d13bf4a5 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -2,9 +2,7 @@ use log::trace;
 
 use rustc_target::abi::{Abi, Size};
 
-use crate::borrow_tracker::{
-    AccessKind, GlobalState, GlobalStateInner, ProtectorKind, RetagFields,
-};
+use crate::borrow_tracker::{AccessKind, GlobalState, GlobalStateInner, ProtectorKind};
 use rustc_middle::{
     mir::{Mutability, RetagKind},
     ty::{
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
index 6801397b2ce..778a544544b 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/tree.rs
@@ -14,7 +14,6 @@ use std::fmt;
 
 use smallvec::SmallVec;
 
-use rustc_const_eval::interpret::InterpResult;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_span::Span;
 use rustc_target::abi::Size;
diff --git a/src/tools/miri/src/concurrency/weak_memory.rs b/src/tools/miri/src/concurrency/weak_memory.rs
index 39e89ce7faa..9ebb64afd35 100644
--- a/src/tools/miri/src/concurrency/weak_memory.rs
+++ b/src/tools/miri/src/concurrency/weak_memory.rs
@@ -82,7 +82,6 @@ use std::{
     collections::VecDeque,
 };
 
-use rustc_const_eval::interpret::{alloc_range, AllocRange, InterpResult, MPlaceTy, Scalar};
 use rustc_data_structures::fx::FxHashMap;
 
 use crate::*;
diff --git a/src/tools/miri/src/eval.rs b/src/tools/miri/src/eval.rs
index 875a78974fa..6013c0bd341 100644
--- a/src/tools/miri/src/eval.rs
+++ b/src/tools/miri/src/eval.rs
@@ -10,7 +10,6 @@ use std::thread;
 use log::info;
 use rustc_middle::ty::Ty;
 
-use crate::borrow_tracker::RetagFields;
 use crate::concurrency::thread::TlsAllocAction;
 use crate::diagnostics::report_leaks;
 use rustc_data_structures::fx::FxHashSet;
diff --git a/src/tools/miri/src/shims/env.rs b/src/tools/miri/src/shims/env.rs
index 9e19f720211..9e8239cdbac 100644
--- a/src/tools/miri/src/shims/env.rs
+++ b/src/tools/miri/src/shims/env.rs
@@ -3,7 +3,6 @@ use std::ffi::{OsStr, OsString};
 use std::io::ErrorKind;
 use std::mem;
 
-use rustc_const_eval::interpret::Pointer;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::ty::Ty;
diff --git a/src/tools/miri/src/shims/unix/fs.rs b/src/tools/miri/src/shims/unix/fs.rs
index be30627cf0c..1402f07dd38 100644
--- a/src/tools/miri/src/shims/unix/fs.rs
+++ b/src/tools/miri/src/shims/unix/fs.rs
@@ -1,7 +1,6 @@
 use std::any::Any;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
-use std::convert::TryInto;
 use std::fs::{
     read_dir, remove_dir, remove_file, rename, DirBuilder, File, FileType, OpenOptions, ReadDir,
 };
diff --git a/src/tools/miri/src/shims/unix/linux/sync.rs b/src/tools/miri/src/shims/unix/linux/sync.rs
index 10e06226b3f..66105391c47 100644
--- a/src/tools/miri/src/shims/unix/linux/sync.rs
+++ b/src/tools/miri/src/shims/unix/linux/sync.rs
@@ -1,6 +1,6 @@
 use std::time::SystemTime;
 
-use crate::concurrency::thread::{MachineCallback, Time};
+use crate::concurrency::thread::MachineCallback;
 use crate::*;
 
 /// Implementation of the SYS_futex syscall.
diff --git a/src/tools/miri/src/shims/unix/sync.rs b/src/tools/miri/src/shims/unix/sync.rs
index 45b47450b7b..054e9719b34 100644
--- a/src/tools/miri/src/shims/unix/sync.rs
+++ b/src/tools/miri/src/shims/unix/sync.rs
@@ -1,7 +1,7 @@
 use std::time::SystemTime;
 
 use crate::concurrency::sync::CondvarLock;
-use crate::concurrency::thread::{MachineCallback, Time};
+use crate::concurrency::thread::MachineCallback;
 use crate::*;
 
 // pthread_mutexattr_t is either 4 or 8 bytes, depending on the platform.
diff --git a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
index 697970a0885..fafeb9e0558 100644
--- a/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
+++ b/src/tools/miri/tests/pass-dep/shims/libc-fs.rs
@@ -4,7 +4,6 @@
 #![feature(io_error_more)]
 #![feature(io_error_uncategorized)]
 
-use std::convert::TryInto;
 use std::ffi::CString;
 use std::fs::{canonicalize, remove_dir_all, remove_file, File};
 use std::io::{Error, ErrorKind, Write};
diff --git a/src/tools/miri/tests/pass/arrays.rs b/src/tools/miri/tests/pass/arrays.rs
index 9589ffa1724..61b44453e9b 100644
--- a/src/tools/miri/tests/pass/arrays.rs
+++ b/src/tools/miri/tests/pass/arrays.rs
@@ -1,5 +1,3 @@
-use std::convert::TryFrom;
-
 fn empty_array() -> [u16; 0] {
     []
 }
diff --git a/src/tools/miri/tests/pass/binary-heap.rs b/src/tools/miri/tests/pass/binary-heap.rs
index 278038d8ad3..e85e56e1b79 100644
--- a/src/tools/miri/tests/pass/binary-heap.rs
+++ b/src/tools/miri/tests/pass/binary-heap.rs
@@ -1,5 +1,4 @@
 use std::collections::BinaryHeap;
-use std::iter::Iterator;
 
 fn zero_sized_push() {
     const N: usize = 8;
diff --git a/src/tools/miri/tests/pass/enum-nullable-const-null-with-fields.rs b/src/tools/miri/tests/pass/enum-nullable-const-null-with-fields.rs
index 8385cc5d880..86f30f42b62 100644
--- a/src/tools/miri/tests/pass/enum-nullable-const-null-with-fields.rs
+++ b/src/tools/miri/tests/pass/enum-nullable-const-null-with-fields.rs
@@ -1,6 +1,3 @@
-use std::result::Result;
-use std::result::Result::Ok;
-
 static C: Result<(), Box<isize>> = Ok(());
 
 // This is because of yet another bad assertion (ICE) about the null side of a nullable enum.
diff --git a/src/tools/miri/tests/pass/function_calls/abi_compat.rs b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
index b24fe56cad6..14fd2d333d4 100644
--- a/src/tools/miri/tests/pass/function_calls/abi_compat.rs
+++ b/src/tools/miri/tests/pass/function_calls/abi_compat.rs
@@ -71,6 +71,8 @@ fn main() {
         test_abi_compat(0isize, 0i64);
     }
     test_abi_compat(42u32, num::NonZeroU32::new(1).unwrap());
+    // - `char` and `u32`.
+    test_abi_compat(42u32, 'x');
     // - Reference/pointer types with the same pointee.
     test_abi_compat(&0u32, &0u32 as *const u32);
     test_abi_compat(&mut 0u32 as *mut u32, Box::new(0u32));
@@ -81,7 +83,7 @@ fn main() {
     test_abi_compat(main as fn(), id::<i32> as fn(i32) -> i32);
     // - 1-ZST
     test_abi_compat((), [0u8; 0]);
-    // - Guaranteed null-pointer-optimizations.
+    // - Guaranteed null-pointer-optimizations (RFC 3391).
     test_abi_compat(&0u32 as *const u32, Some(&0u32));
     test_abi_compat(main as fn(), Some(main as fn()));
     test_abi_compat(0u32, Some(num::NonZeroU32::new(1).unwrap()));
@@ -103,6 +105,8 @@ fn main() {
     test_abi_newtype::<Option<num::NonZeroU32>>();
 
     // Extra test for assumptions made by arbitrary-self-dyn-receivers.
+    // This is interesting since these types are not `repr(transparent)`. So this is not part of our
+    // public ABI guarantees, but is relied on by the compiler.
     let rc = Rc::new(0);
     let rc_ptr: *mut i32 = unsafe { mem::transmute_copy(&rc) };
     test_abi_compat(rc, rc_ptr);
diff --git a/src/tools/miri/tests/pass/pointers.rs b/src/tools/miri/tests/pass/pointers.rs
index 1525ded6151..c7b720dafa2 100644
--- a/src/tools/miri/tests/pass/pointers.rs
+++ b/src/tools/miri/tests/pass/pointers.rs
@@ -2,6 +2,7 @@
 //@[tree]compile-flags: -Zmiri-tree-borrows
 //@compile-flags: -Zmiri-permissive-provenance
 #![feature(ptr_metadata, const_raw_ptr_comparison)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::mem::{self, transmute};
 use std::ptr;
diff --git a/src/tools/miri/tests/pass/rc.rs b/src/tools/miri/tests/pass/rc.rs
index 6375abcd232..6dd1b3aff9e 100644
--- a/src/tools/miri/tests/pass/rc.rs
+++ b/src/tools/miri/tests/pass/rc.rs
@@ -3,6 +3,7 @@
 //@compile-flags: -Zmiri-strict-provenance
 #![feature(new_uninit)]
 #![feature(get_mut_unchecked)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::cell::{Cell, RefCell};
 use std::fmt::Debug;
diff --git a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
index 48efbf589c6..87118a62650 100644
--- a/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
+++ b/src/tools/rust-analyzer/crates/proc-macro-api/src/version.rs
@@ -85,8 +85,8 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'
 }
 
 /// Check the version of rustc that was used to compile a proc macro crate's
-///
 /// binary file.
+///
 /// A proc macro crate binary's ".rustc" section has following byte layout:
 /// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes
 /// * ff060000 734e6150 is followed, it's the snappy format magic bytes,
@@ -96,8 +96,8 @@ fn read_section<'a>(dylib_binary: &'a [u8], section_name: &str) -> io::Result<&'
 /// The bytes you get after decompressing the snappy format portion has
 /// following layout:
 /// * [b'r',b'u',b's',b't',0,0,0,5] is the first 8 bytes(again)
-/// * [crate root bytes] next 4 bytes is to store crate root position,
-///   according to rustc's source code comment
+/// * [crate root bytes] next 8 bytes (4 in old versions) is to store
+///   crate root position, according to rustc's source code comment
 /// * [length byte] next 1 byte tells us how many bytes we should read next
 ///   for the version string's utf8 bytes
 /// * [version string bytes encoded in utf8] <- GET THIS BOI
@@ -119,14 +119,19 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
     }
     let version = u32::from_be_bytes([dot_rustc[4], dot_rustc[5], dot_rustc[6], dot_rustc[7]]);
     // Last supported version is:
-    // https://github.com/rust-lang/rust/commit/0696e79f2740ad89309269b460579e548a5cd632
-    let snappy_portion = match version {
-        5 | 6 => &dot_rustc[8..],
+    // https://github.com/rust-lang/rust/commit/b94cfefc860715fb2adf72a6955423d384c69318
+    let (snappy_portion, bytes_before_version) = match version {
+        5 | 6 => (&dot_rustc[8..], 13),
         7 | 8 => {
             let len_bytes = &dot_rustc[8..12];
             let data_len = u32::from_be_bytes(len_bytes.try_into().unwrap()) as usize;
-            &dot_rustc[12..data_len + 12]
+            (&dot_rustc[12..data_len + 12], 13)
         }
+        9 => {
+            let len_bytes = &dot_rustc[8..16];
+            let data_len = u64::from_le_bytes(len_bytes.try_into().unwrap()) as usize;
+            (&dot_rustc[16..data_len + 12], 17)
+         }
         _ => {
             return Err(io::Error::new(
                 io::ErrorKind::InvalidData,
@@ -142,15 +147,15 @@ pub fn read_version(dylib_path: &AbsPath) -> io::Result<String> {
         Box::new(SnapDecoder::new(snappy_portion))
     };
 
-    // the bytes before version string bytes, so this basically is:
+    // We're going to skip over the bytes before the version string, so basically:
     // 8 bytes for [b'r',b'u',b's',b't',0,0,0,5]
-    // 4 bytes for [crate root bytes]
+    // 4 or 8 bytes for [crate root bytes]
     // 1 byte for length of version string
-    // so 13 bytes in total, and we should check the 13th byte
+    // so 13 or 17 bytes in total, and we should check the last of those bytes
     // to know the length
-    let mut bytes_before_version = [0u8; 13];
-    uncompressed.read_exact(&mut bytes_before_version)?;
-    let length = bytes_before_version[12];
+    let mut bytes = [0u8; 17];
+    uncompressed.read_exact(&mut bytes[..bytes_before_version])?;
+    let length = bytes[bytes_before_version - 1];
 
     let mut version_string_utf8 = vec![0u8; length as usize];
     uncompressed.read_exact(&mut version_string_utf8)?;
diff --git a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
index fd44e6c6d0f..7dba002c6ec 100644
--- a/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
+++ b/src/tools/rust-analyzer/crates/stdx/src/anymap.rs
@@ -17,7 +17,6 @@
 
 #![warn(missing_docs, unused_results)]
 
-use core::convert::TryInto;
 use core::hash::Hasher;
 
 /// A hasher designed to eke a little more speed out, given `TypeId`’s known characteristics.
diff --git a/src/tools/rustfmt/src/comment.rs b/src/tools/rustfmt/src/comment.rs
index 7da0f79bd09..f7cd7cefb3d 100644
--- a/src/tools/rustfmt/src/comment.rs
+++ b/src/tools/rustfmt/src/comment.rs
@@ -1,6 +1,6 @@
 // Formatting and tools for comments.
 
-use std::{self, borrow::Cow, iter};
+use std::{borrow::Cow, iter};
 
 use itertools::{multipeek, MultiPeek};
 use lazy_static::lazy_static;
@@ -1847,7 +1847,6 @@ fn remove_comment_header(comment: &str) -> &str {
 #[cfg(test)]
 mod test {
     use super::*;
-    use crate::shape::{Indent, Shape};
 
     #[test]
     fn char_classes() {
diff --git a/src/tools/rustfmt/src/config/file_lines.rs b/src/tools/rustfmt/src/config/file_lines.rs
index e33fe9bb283..224864393d3 100644
--- a/src/tools/rustfmt/src/config/file_lines.rs
+++ b/src/tools/rustfmt/src/config/file_lines.rs
@@ -6,7 +6,7 @@ use std::path::PathBuf;
 use std::{cmp, fmt, iter, str};
 
 use rustc_data_structures::sync::Lrc;
-use rustc_span::{self, SourceFile};
+use rustc_span::SourceFile;
 use serde::{ser, Deserialize, Deserializer, Serialize, Serializer};
 use serde_json as json;
 use thiserror::Error;
diff --git a/src/tools/rustfmt/src/config/mod.rs b/src/tools/rustfmt/src/config/mod.rs
index 7538b26522d..9d454137b2c 100644
--- a/src/tools/rustfmt/src/config/mod.rs
+++ b/src/tools/rustfmt/src/config/mod.rs
@@ -1,5 +1,4 @@
 use std::cell::Cell;
-use std::default::Default;
 use std::fs::File;
 use std::io::{Error, ErrorKind, Read};
 use std::path::{Path, PathBuf};
@@ -1017,7 +1016,6 @@ make_backup = false
     #[cfg(test)]
     mod partially_unstable_option {
         use super::mock::{Config, PartiallyUnstableOption};
-        use super::*;
 
         /// From the command line, we can override with a stable variant.
         #[test]
diff --git a/src/tools/rustfmt/src/emitter/checkstyle.rs b/src/tools/rustfmt/src/emitter/checkstyle.rs
index 56d6a0ed681..2a4a9dfce8e 100644
--- a/src/tools/rustfmt/src/emitter/checkstyle.rs
+++ b/src/tools/rustfmt/src/emitter/checkstyle.rs
@@ -1,7 +1,6 @@
 use self::xml::XmlEscaped;
 use super::*;
 use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
-use std::io::{self, Write};
 
 mod xml;
 
diff --git a/src/tools/rustfmt/src/emitter/diff.rs b/src/tools/rustfmt/src/emitter/diff.rs
index 764cd136e01..0af19a7d0b2 100644
--- a/src/tools/rustfmt/src/emitter/diff.rs
+++ b/src/tools/rustfmt/src/emitter/diff.rs
@@ -51,8 +51,6 @@ impl Emitter for DiffEmitter {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::config::Config;
-    use crate::FileName;
     use std::path::PathBuf;
 
     #[test]
diff --git a/src/tools/rustfmt/src/emitter/json.rs b/src/tools/rustfmt/src/emitter/json.rs
index 5594196bed9..f47c3260a02 100644
--- a/src/tools/rustfmt/src/emitter/json.rs
+++ b/src/tools/rustfmt/src/emitter/json.rs
@@ -2,7 +2,6 @@ use super::*;
 use crate::rustfmt_diff::{make_diff, DiffLine, Mismatch};
 use serde::Serialize;
 use serde_json::to_string as to_json_string;
-use std::io::{self, Write};
 
 #[derive(Debug, Default)]
 pub(crate) struct JsonEmitter {
@@ -106,7 +105,6 @@ impl JsonEmitter {
 #[cfg(test)]
 mod tests {
     use super::*;
-    use crate::FileName;
     use std::path::PathBuf;
 
     #[test]
diff --git a/src/tools/rustfmt/src/emitter/modified_lines.rs b/src/tools/rustfmt/src/emitter/modified_lines.rs
index 94ff570a8a9..81f0a31b974 100644
--- a/src/tools/rustfmt/src/emitter/modified_lines.rs
+++ b/src/tools/rustfmt/src/emitter/modified_lines.rs
@@ -1,6 +1,5 @@
 use super::*;
 use crate::rustfmt_diff::{make_diff, ModifiedLines};
-use std::io::Write;
 
 #[derive(Debug, Default)]
 pub(crate) struct ModifiedLinesEmitter;
diff --git a/src/tools/rustfmt/src/emitter/stdout.rs b/src/tools/rustfmt/src/emitter/stdout.rs
index 0bbc7332dfe..0b635a28bf2 100644
--- a/src/tools/rustfmt/src/emitter/stdout.rs
+++ b/src/tools/rustfmt/src/emitter/stdout.rs
@@ -1,6 +1,5 @@
 use super::*;
 use crate::config::Verbosity;
-use std::io::Write;
 
 #[derive(Debug)]
 pub(crate) struct StdoutEmitter {
diff --git a/src/tools/rustfmt/src/ignore_path.rs b/src/tools/rustfmt/src/ignore_path.rs
index d955949496a..7b5697bec3e 100644
--- a/src/tools/rustfmt/src/ignore_path.rs
+++ b/src/tools/rustfmt/src/ignore_path.rs
@@ -1,4 +1,4 @@
-use ignore::{self, gitignore};
+use ignore::gitignore;
 
 use crate::config::{FileName, IgnoreList};
 
diff --git a/src/tools/rustfmt/src/imports.rs b/src/tools/rustfmt/src/imports.rs
index f8e7fa62890..09f6e752338 100644
--- a/src/tools/rustfmt/src/imports.rs
+++ b/src/tools/rustfmt/src/imports.rs
@@ -1102,7 +1102,6 @@ enum SharedPrefix {
 #[cfg(test)]
 mod test {
     use super::*;
-    use rustc_span::DUMMY_SP;
 
     // Parse the path part of an import. This parser is not robust and is only
     // suitable for use in a test harness.
diff --git a/src/tools/rustfmt/src/macros.rs b/src/tools/rustfmt/src/macros.rs
index 76553466e48..b4c58d2fefb 100644
--- a/src/tools/rustfmt/src/macros.rs
+++ b/src/tools/rustfmt/src/macros.rs
@@ -708,7 +708,7 @@ struct MacroArgParser {
 fn last_tok(tt: &TokenTree) -> Token {
     match *tt {
         TokenTree::Token(ref t, _) => t.clone(),
-        TokenTree::Delimited(delim_span, delim, _) => Token {
+        TokenTree::Delimited(delim_span, _, delim, _) => Token {
             kind: TokenKind::CloseDelim(delim),
             span: delim_span.close,
         },
@@ -925,7 +925,7 @@ impl MacroArgParser {
                     self.add_meta_variable(&mut iter)?;
                 }
                 TokenTree::Token(ref t, _) => self.update_buffer(t),
-                &TokenTree::Delimited(_delimited_span, delimited, ref tts) => {
+                &TokenTree::Delimited(_dspan, _spacing, delimited, ref tts) => {
                     if !self.buf.is_empty() {
                         if next_space(&self.last_tok.kind) == SpaceState::Always {
                             self.add_separator();
@@ -1167,7 +1167,7 @@ impl<'a> MacroParser<'a> {
         let tok = self.toks.next()?;
         let (lo, args_paren_kind) = match tok {
             TokenTree::Token(..) => return None,
-            &TokenTree::Delimited(delimited_span, d, _) => (delimited_span.open.lo(), d),
+            &TokenTree::Delimited(delimited_span, _, d, _) => (delimited_span.open.lo(), d),
         };
         let args = TokenStream::new(vec![tok.clone()]);
         match self.toks.next()? {
diff --git a/src/tools/rustfmt/src/reorder.rs b/src/tools/rustfmt/src/reorder.rs
index 3bddf4c1b6a..3e14f9f1272 100644
--- a/src/tools/rustfmt/src/reorder.rs
+++ b/src/tools/rustfmt/src/reorder.rs
@@ -6,7 +6,7 @@
 
 // FIXME(#2455): Reorder trait items.
 
-use std::cmp::{Ord, Ordering};
+use std::cmp::Ordering;
 
 use rustc_ast::{ast, attr};
 use rustc_span::{symbol::sym, Span};
diff --git a/src/tools/rustfmt/src/types.rs b/src/tools/rustfmt/src/types.rs
index 8ca27150371..a5a4244903c 100644
--- a/src/tools/rustfmt/src/types.rs
+++ b/src/tools/rustfmt/src/types.rs
@@ -1,4 +1,3 @@
-use std::iter::ExactSizeIterator;
 use std::ops::Deref;
 
 use rustc_ast::ast::{self, FnRetTy, Mutability, Term};
diff --git a/src/tools/rustfmt/tests/source/issue-2927-2.rs b/src/tools/rustfmt/tests/source/issue-2927-2.rs
index d87761fdc9c..07afef38cf5 100644
--- a/src/tools/rustfmt/tests/source/issue-2927-2.rs
+++ b/src/tools/rustfmt/tests/source/issue-2927-2.rs
@@ -1,5 +1,5 @@
 // rustfmt-edition: 2015
-#![feature(rust_2018_preview, uniform_paths)]
+#![feature(uniform_paths)]
 use futures::prelude::*;
 use http_03::cli::Cli;
 use hyper::{service::service_fn_ok, Body, Response, Server};
diff --git a/src/tools/rustfmt/tests/source/issue-2927.rs b/src/tools/rustfmt/tests/source/issue-2927.rs
index a7df32084f3..c7ec7bb0855 100644
--- a/src/tools/rustfmt/tests/source/issue-2927.rs
+++ b/src/tools/rustfmt/tests/source/issue-2927.rs
@@ -1,5 +1,5 @@
 // rustfmt-edition: 2018
-#![feature(rust_2018_preview, uniform_paths)]
+#![feature(uniform_paths)]
 use futures::prelude::*;
 use http_03::cli::Cli;
 use hyper::{service::service_fn_ok, Body, Response, Server};
diff --git a/src/tools/rustfmt/tests/target/issue-2927-2.rs b/src/tools/rustfmt/tests/target/issue-2927-2.rs
index e895783ba8b..46e0bf0e989 100644
--- a/src/tools/rustfmt/tests/target/issue-2927-2.rs
+++ b/src/tools/rustfmt/tests/target/issue-2927-2.rs
@@ -1,5 +1,5 @@
 // rustfmt-edition: 2015
-#![feature(rust_2018_preview, uniform_paths)]
+#![feature(uniform_paths)]
 use futures::prelude::*;
 use http_03::cli::Cli;
 use hyper::{service::service_fn_ok, Body, Response, Server};
diff --git a/src/tools/rustfmt/tests/target/issue-2927.rs b/src/tools/rustfmt/tests/target/issue-2927.rs
index 3267be28d7b..56afc2d3e40 100644
--- a/src/tools/rustfmt/tests/target/issue-2927.rs
+++ b/src/tools/rustfmt/tests/target/issue-2927.rs
@@ -1,5 +1,5 @@
 // rustfmt-edition: 2018
-#![feature(rust_2018_preview, uniform_paths)]
+#![feature(uniform_paths)]
 use ::log::{error, info, log};
 use futures::prelude::*;
 use http_03::cli::Cli;
diff --git a/tests/pretty/cast-lt.pp b/tests/pretty/cast-lt.pp
index e6c4d195691..61cd8f59712 100644
--- a/tests/pretty/cast-lt.pp
+++ b/tests/pretty/cast-lt.pp
@@ -8,6 +8,6 @@ extern crate std;
 // pretty-mode:expanded
 // pp-exact:cast-lt.pp
 
-macro_rules! negative { ($e : expr) => { $e < 0 } }
+macro_rules! negative { ($e:expr) => { $e < 0 } }
 
 fn main() { (1 as i32) < 0; }
diff --git a/tests/run-make/rustc-macro-dep-files/foo.rs b/tests/run-make/rustc-macro-dep-files/foo.rs
index 66db1a21736..00b1c26d43f 100644
--- a/tests/run-make/rustc-macro-dep-files/foo.rs
+++ b/tests/run-make/rustc-macro-dep-files/foo.rs
@@ -7,6 +7,6 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(A)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert!(input.contains("struct A ;"));
+    assert!(input.contains("struct A;"));
     "struct B;".parse().unwrap()
 }
diff --git a/tests/rustdoc-js/assoc-type.js b/tests/rustdoc-js/assoc-type.js
index cc3afaa17c0..47776656e32 100644
--- a/tests/rustdoc-js/assoc-type.js
+++ b/tests/rustdoc-js/assoc-type.js
@@ -19,6 +19,17 @@ const EXPECTED = [
             { 'path': 'assoc_type::my', 'name': 'other_fn' },
         ],
     },
+    {
+        'query': 'something',
+        'correction': null,
+        'others': [
+            { 'path': 'assoc_type', 'name': 'Something' },
+        ],
+        'in_args': [
+            { 'path': 'assoc_type', 'name': 'my_fn' },
+            { 'path': 'assoc_type::my', 'name': 'other_fn' },
+        ],
+    },
     // if I write an explicit binding, only it shows up
     {
         'query': 'iterator<item=something> -> u32',
diff --git a/tests/rustdoc-js/enum-variant-not-type.js b/tests/rustdoc-js/enum-variant-not-type.js
new file mode 100644
index 00000000000..b0f1ec66658
--- /dev/null
+++ b/tests/rustdoc-js/enum-variant-not-type.js
@@ -0,0 +1,70 @@
+const EXPECTED = [
+    {
+        'query': 'T -> T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type',
+                'name': 'my_fn',
+            },
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'assoc_type_acts_like_generic',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHere -> InsertUnnecessarilyLongTypeNameHere',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type',
+                'name': 'my_fn',
+            },
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'assoc_type_acts_like_generic',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHere',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'InsertUnnecessarilyLongTypeNameHere',
+            },
+        ],
+    },
+    {
+        'query': 'InsertUnnecessarilyLongTypeNameHereX',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::AutoCorrectConfounder',
+                'name': 'InsertUnnecessarilyLongTypeNameHere',
+            },
+        ],
+    },
+    {
+        'query': 'T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::MyTrait',
+                'name': 'T',
+            },
+        ],
+    },
+    {
+        'query': 'T',
+        'correction': null,
+        'others': [
+            {
+                'path': 'enum_variant_not_type::MyTrait',
+                'name': 'T',
+            },
+        ],
+    },
+];
diff --git a/tests/rustdoc-js/enum-variant-not-type.rs b/tests/rustdoc-js/enum-variant-not-type.rs
new file mode 100644
index 00000000000..421bddf6289
--- /dev/null
+++ b/tests/rustdoc-js/enum-variant-not-type.rs
@@ -0,0 +1,14 @@
+pub trait MyTrait {
+    // Reduced from `arti` crate.
+    // https://tpo.pages.torproject.net/core/doc/rust/tor_config/list_builder/trait.DirectDefaultEmptyListBuilderAccessors.html#associatedtype.T
+    type T;
+    fn not_appearing(&self) -> Option<&Self::T>;
+}
+
+pub fn my_fn<X>(t: X) -> X { t }
+
+pub trait AutoCorrectConfounder {
+    type InsertUnnecessarilyLongTypeNameHere;
+    fn assoc_type_acts_like_generic(&self, x: &Self::InsertUnnecessarilyLongTypeNameHere)
+        -> Option<&Self::InsertUnnecessarilyLongTypeNameHere>;
+}
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index fe5333643ed..24c4543c20c 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -32,7 +32,7 @@ extern crate thin_vec;
 #[allow(unused_extern_crates)]
 extern crate rustc_driver;
 
-use rustc_ast::mut_visit::{self, visit_clobber, MutVisitor};
+use rustc_ast::mut_visit::{visit_clobber, MutVisitor};
 use rustc_ast::ptr::P;
 use rustc_ast::*;
 use rustc_ast_pretty::pprust;
diff --git a/tests/ui/abi/compatibility.rs b/tests/ui/abi/compatibility.rs
index d5f05313078..c6bba7186da 100644
--- a/tests/ui/abi/compatibility.rs
+++ b/tests/ui/abi/compatibility.rs
@@ -263,6 +263,13 @@ test_abi_compatible!(box_ptr, Box<i32>, *const i32);
 test_abi_compatible!(nonnull_ptr, NonNull<i32>, *const i32);
 test_abi_compatible!(fn_fn, fn(), fn(i32) -> i32);
 
+// Compatibility of integer types.
+test_abi_compatible!(char_uint, char, u32);
+#[cfg(target_pointer_width = "32")]
+test_abi_compatible!(isize_int, isize, i32);
+#[cfg(target_pointer_width = "64")]
+test_abi_compatible!(isize_int, isize, i64);
+
 // Compatibility of 1-ZST.
 test_abi_compatible!(zst_unit, Zst, ());
 #[cfg(not(any(target_arch = "sparc64")))]
diff --git a/tests/ui/async-await/issues/issue-60674.stdout b/tests/ui/async-await/issues/issue-60674.stdout
index 6f980e60664..df129b033d2 100644
--- a/tests/ui/async-await/issues/issue-60674.stdout
+++ b/tests/ui/async-await/issues/issue-60674.stdout
@@ -1,3 +1,3 @@
-async fn f(mut x : u8) {}
-async fn g((mut x, y, mut z) : (u8, u8, u8)) {}
-async fn g(mut x : u8, (a, mut b, c) : (u8, u8, u8), y : u8) {}
+async fn f(mut x: u8) {}
+async fn g((mut x, y, mut z): (u8, u8, u8)) {}
+async fn g(mut x: u8, (a, mut b, c): (u8, u8, u8), y: u8) {}
diff --git a/tests/ui/bare-fn-implements-fn-mut.rs b/tests/ui/bare-fn-implements-fn-mut.rs
index dfead48893e..d6ecd6b654b 100644
--- a/tests/ui/bare-fn-implements-fn-mut.rs
+++ b/tests/ui/bare-fn-implements-fn-mut.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-use std::ops::FnMut;
-
 fn call_f<F:FnMut()>(mut f: F) {
     f();
 }
diff --git a/tests/ui/box/alloc-unstable.rs b/tests/ui/box/alloc-unstable.rs
index 66388d0d512..640cadcc8e3 100644
--- a/tests/ui/box/alloc-unstable.rs
+++ b/tests/ui/box/alloc-unstable.rs
@@ -1,8 +1,5 @@
 // run-pass
 #![feature(allocator_api)]
-
-use std::boxed::Box;
-
 fn main() {
     let _boxed: Box<u32, _> = Box::new(10);
 }
diff --git a/tests/ui/box/into-boxed-slice.rs b/tests/ui/box/into-boxed-slice.rs
index 61b3d915253..86866ac2f7e 100644
--- a/tests/ui/box/into-boxed-slice.rs
+++ b/tests/ui/box/into-boxed-slice.rs
@@ -1,7 +1,5 @@
 // run-pass
 #![feature(box_into_boxed_slice)]
-
-use std::boxed::Box;
 fn main() {
     assert_eq!(Box::into_boxed_slice(Box::new(5u8)), Box::new([5u8]) as Box<[u8]>);
     assert_eq!(Box::into_boxed_slice(Box::new([25u8])), Box::new([[25u8]]) as Box<[[u8; 1]]>);
diff --git a/tests/ui/box/new-box-syntax.rs b/tests/ui/box/new-box-syntax.rs
index c56e1dd4625..e3b1550d60b 100644
--- a/tests/ui/box/new-box-syntax.rs
+++ b/tests/ui/box/new-box-syntax.rs
@@ -8,8 +8,6 @@
 
 // Tests that the new `box` syntax works with unique pointers.
 
-use std::boxed::Box;
-
 struct Structure {
     x: isize,
     y: isize,
diff --git a/tests/ui/box/unit/unique-kinds.rs b/tests/ui/box/unit/unique-kinds.rs
index f02d0b50764..1ef09d7195a 100644
--- a/tests/ui/box/unit/unique-kinds.rs
+++ b/tests/ui/box/unit/unique-kinds.rs
@@ -1,6 +1,5 @@
 // run-pass
 
-use std::cmp::PartialEq;
 use std::fmt::Debug;
 
 fn sendable() {
diff --git a/tests/ui/check-cfg/allow-same-level.stderr b/tests/ui/check-cfg/allow-same-level.stderr
index 19d9443d477..652efc3f591 100644
--- a/tests/ui/check-cfg/allow-same-level.stderr
+++ b/tests/ui/check-cfg/allow-same-level.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `FALSE`
 LL | #[cfg(FALSE)]
    |       ^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/compact-names.stderr b/tests/ui/check-cfg/compact-names.stderr
index ffde972a25e..d3bfb9f7100 100644
--- a/tests/ui/check-cfg/compact-names.stderr
+++ b/tests/ui/check-cfg/compact-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `target_architecture`
 LL | #[cfg(target(os = "linux", architecture = "arm"))]
    |                            ^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
index 9efc77fb43f..9501c134bac 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_cfg.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
index 971abb1a21a..e37a222f52a 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.empty_names_values.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
index 4549482abcb..ea204eaff1b 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.feature.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
diff --git a/tests/ui/check-cfg/exhaustive-names-values.full.stderr b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
index 4549482abcb..ea204eaff1b 100644
--- a/tests/ui/check-cfg/exhaustive-names-values.full.stderr
+++ b/tests/ui/check-cfg/exhaustive-names-values.full.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: unexpected `cfg` condition value: `value`
diff --git a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
index 7d01c73cc09..b5c8cad275f 100644
--- a/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.exhaustive_names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/exhaustive-names.stderr b/tests/ui/check-cfg/exhaustive-names.stderr
index 866595b1213..c5f6d537c5e 100644
--- a/tests/ui/check-cfg/exhaustive-names.stderr
+++ b/tests/ui/check-cfg/exhaustive-names.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `unknown_key`
 LL | #[cfg(unknown_key = "value")]
    |       ^^^^^^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/mix.cfg.stderr b/tests/ui/check-cfg/mix.cfg.stderr
index 21c0c7da1dd..046d40f36b0 100644
--- a/tests/ui/check-cfg/mix.cfg.stderr
+++ b/tests/ui/check-cfg/mix.cfg.stderr
@@ -36,7 +36,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, test)]
    |            ^^
    |
-   = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `cfg`, `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `names_values`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
 
 warning: unexpected `cfg` condition name: `widnows`
   --> $DIR/mix.rs:43:10
diff --git a/tests/ui/check-cfg/mix.stderr b/tests/ui/check-cfg/mix.stderr
index eefdbd6af30..25b8f95ae2f 100644
--- a/tests/ui/check-cfg/mix.stderr
+++ b/tests/ui/check-cfg/mix.stderr
@@ -36,7 +36,7 @@ warning: unexpected `cfg` condition name: `uu`
 LL | #[cfg_attr(uu, test)]
    |            ^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `feature`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
 
 warning: unexpected `cfg` condition name: `widnows`
   --> $DIR/mix.rs:40:10
diff --git a/tests/ui/check-cfg/stmt-no-ice.stderr b/tests/ui/check-cfg/stmt-no-ice.stderr
index 3fb3ae27ec4..c2483fe4a06 100644
--- a/tests/ui/check-cfg/stmt-no-ice.stderr
+++ b/tests/ui/check-cfg/stmt-no-ice.stderr
@@ -4,7 +4,7 @@ warning: unexpected `cfg` condition name: `crossbeam_loom`
 LL |     #[cfg(crossbeam_loom)]
    |           ^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/well-known-names.stderr b/tests/ui/check-cfg/well-known-names.stderr
index a986e61bcdc..6040663074d 100644
--- a/tests/ui/check-cfg/well-known-names.stderr
+++ b/tests/ui/check-cfg/well-known-names.stderr
@@ -16,7 +16,7 @@ warning: unexpected `cfg` condition name: `features`
 LL | #[cfg(features = "foo")]
    |       ^^^^^^^^^^^^^^^^
    |
-   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
 
 warning: unexpected `cfg` condition name: `feature`
   --> $DIR/well-known-names.rs:17:7
diff --git a/tests/ui/cleanup-rvalue-for-scope.rs b/tests/ui/cleanup-rvalue-for-scope.rs
index b6582c01fba..38a41f3b8d7 100644
--- a/tests/ui/cleanup-rvalue-for-scope.rs
+++ b/tests/ui/cleanup-rvalue-for-scope.rs
@@ -5,9 +5,6 @@
 #![allow(unused_variables)]
 // Test that the lifetime of rvalues in for loops is extended
 // to the for loop itself.
-
-use std::ops::Drop;
-
 static mut FLAGS: u64 = 0;
 
 struct Box<T> { f: T }
diff --git a/tests/ui/cleanup-rvalue-scopes.rs b/tests/ui/cleanup-rvalue-scopes.rs
index b80f95b79f9..56340e515b9 100644
--- a/tests/ui/cleanup-rvalue-scopes.rs
+++ b/tests/ui/cleanup-rvalue-scopes.rs
@@ -8,8 +8,6 @@
 
 #![feature(box_patterns)]
 
-use std::ops::Drop;
-
 static mut FLAGS: u64 = 0;
 
 struct Box<T> { f: T }
diff --git a/tests/ui/codegen/const-bool-bitcast.rs b/tests/ui/codegen/const-bool-bitcast.rs
new file mode 100644
index 00000000000..24ae76b9029
--- /dev/null
+++ b/tests/ui/codegen/const-bool-bitcast.rs
@@ -0,0 +1,15 @@
+// This is a regression test for https://github.com/rust-lang/rust/issues/118047
+// build-pass
+// compile-flags: -Zmir-opt-level=0 -Zmir-enable-passes=+DataflowConstProp
+
+#![crate_type = "lib"]
+
+pub struct State {
+    inner: bool
+}
+
+pub fn make() -> State {
+    State {
+        inner: true
+    }
+}
diff --git a/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs b/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs
index b87e162aca0..d5306d59ed5 100644
--- a/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs
+++ b/tests/ui/coherence/coherence-negative-impls-safe-rpass.rs
@@ -4,8 +4,6 @@
 
 #![feature(negative_impls)]
 
-use std::marker::Send;
-
 struct TestType;
 
 impl !Send for TestType {}
diff --git a/tests/ui/coherence/coherence-where-clause.rs b/tests/ui/coherence/coherence-where-clause.rs
index 5c40def86bb..cd9a423f4ec 100644
--- a/tests/ui/coherence/coherence-where-clause.rs
+++ b/tests/ui/coherence/coherence-where-clause.rs
@@ -1,8 +1,6 @@
 // run-pass
 
 use std::fmt::Debug;
-use std::default::Default;
-
 trait MyTrait {
     fn get(&self) -> Self;
 }
diff --git a/tests/ui/consts/const-block.rs b/tests/ui/consts/const-block.rs
index ec99c70f6e0..40c7a7a1da9 100644
--- a/tests/ui/consts/const-block.rs
+++ b/tests/ui/consts/const-block.rs
@@ -3,8 +3,6 @@
 #![allow(dead_code)]
 #![allow(unused_unsafe)]
 
-use std::marker::Sync;
-
 struct Foo {
     a: usize,
     b: *const ()
diff --git a/tests/ui/consts/fn_trait_refs.stderr b/tests/ui/consts/fn_trait_refs.stderr
index 3d82837d530..e5ebe1d8528 100644
--- a/tests/ui/consts/fn_trait_refs.stderr
+++ b/tests/ui/consts/fn_trait_refs.stderr
@@ -4,12 +4,6 @@ error[E0635]: unknown feature `const_fn_trait_ref_impls`
 LL | #![feature(const_fn_trait_ref_impls)]
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0635]: unknown feature `const_cmp`
-  --> $DIR/fn_trait_refs.rs:8:12
-   |
-LL | #![feature(const_cmp)]
-   |            ^^^^^^^^^
-
 error: ~const can only be applied to `#[const_trait]` traits
   --> $DIR/fn_trait_refs.rs:15:15
    |
@@ -80,6 +74,6 @@ LL |     T: ~const FnMut<()> + ~const Destruct,
    |
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 12 previous errors
+error: aborting due to 11 previous errors
 
 For more information about this error, try `rustc --explain E0635`.
diff --git a/tests/ui/coroutine/control-flow.rs b/tests/ui/coroutine/control-flow.rs
index 709b135b2ee..0cb37524a6c 100644
--- a/tests/ui/coroutine/control-flow.rs
+++ b/tests/ui/coroutine/control-flow.rs
@@ -5,7 +5,6 @@
 
 #![feature(coroutines, coroutine_trait)]
 
-use std::marker::Unpin;
 use std::ops::{CoroutineState, Coroutine};
 use std::pin::Pin;
 
diff --git a/tests/ui/coroutine/discriminant.rs b/tests/ui/coroutine/discriminant.rs
index 73bdd9c8671..0cdeb6dd678 100644
--- a/tests/ui/coroutine/discriminant.rs
+++ b/tests/ui/coroutine/discriminant.rs
@@ -6,7 +6,7 @@
 #![feature(coroutines, coroutine_trait, core_intrinsics, discriminant_kind)]
 
 use std::intrinsics::discriminant_value;
-use std::marker::{DiscriminantKind, Unpin};
+use std::marker::DiscriminantKind;
 use std::mem::size_of_val;
 use std::{cmp, ops::*};
 
diff --git a/tests/ui/coroutine/iterator-count.rs b/tests/ui/coroutine/iterator-count.rs
index 322e56f8a8b..b7628c44ddc 100644
--- a/tests/ui/coroutine/iterator-count.rs
+++ b/tests/ui/coroutine/iterator-count.rs
@@ -2,7 +2,6 @@
 
 #![feature(coroutines, coroutine_trait)]
 
-use std::marker::Unpin;
 use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
diff --git a/tests/ui/coroutine/non-static-is-unpin.rs b/tests/ui/coroutine/non-static-is-unpin.rs
index d6ded53ae5a..d77fe659f08 100644
--- a/tests/ui/coroutine/non-static-is-unpin.rs
+++ b/tests/ui/coroutine/non-static-is-unpin.rs
@@ -5,7 +5,7 @@
 #![feature(coroutines, coroutine_trait)]
 #![allow(dropping_copy_types)]
 
-use std::marker::{PhantomPinned, Unpin};
+use std::marker::PhantomPinned;
 
 fn assert_unpin<G: Unpin>(_: G) {
 }
diff --git a/tests/ui/coroutine/smoke-resume-args.rs b/tests/ui/coroutine/smoke-resume-args.rs
index a801989859e..752b21ba087 100644
--- a/tests/ui/coroutine/smoke-resume-args.rs
+++ b/tests/ui/coroutine/smoke-resume-args.rs
@@ -6,7 +6,6 @@
 #![feature(coroutines, coroutine_trait)]
 
 use std::fmt::Debug;
-use std::marker::Unpin;
 use std::ops::{
     Coroutine,
     CoroutineState::{self, *},
diff --git a/tests/ui/editions/edition-feature-ok.rs b/tests/ui/editions/edition-feature-ok.rs
deleted file mode 100644
index 69242fd715c..00000000000
--- a/tests/ui/editions/edition-feature-ok.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-// check-pass
-
-#![feature(rust_2018_preview)]
-
-fn main() {}
diff --git a/tests/ui/editions/edition-feature-redundant.rs b/tests/ui/editions/edition-feature-redundant.rs
deleted file mode 100644
index 1049a2da8fd..00000000000
--- a/tests/ui/editions/edition-feature-redundant.rs
+++ /dev/null
@@ -1,7 +0,0 @@
-// edition:2018
-// check-pass
-
-#![feature(rust_2018_preview)]
-//~^ WARN the feature `rust_2018_preview` is included in the Rust 2018 edition
-
-fn main() {}
diff --git a/tests/ui/editions/edition-feature-redundant.stderr b/tests/ui/editions/edition-feature-redundant.stderr
deleted file mode 100644
index b11e616d7f2..00000000000
--- a/tests/ui/editions/edition-feature-redundant.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-warning[E0705]: the feature `rust_2018_preview` is included in the Rust 2018 edition
-  --> $DIR/edition-feature-redundant.rs:4:12
-   |
-LL | #![feature(rust_2018_preview)]
-   |            ^^^^^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
-For more information about this error, try `rustc --explain E0705`.
diff --git a/tests/ui/editions/epoch-gate-feature.rs b/tests/ui/editions/epoch-gate-feature.rs
deleted file mode 100644
index 5f7feb5347b..00000000000
--- a/tests/ui/editions/epoch-gate-feature.rs
+++ /dev/null
@@ -1,15 +0,0 @@
-// run-pass
-
-#![allow(dead_code)]
-#![allow(unused_variables)]
-// Checks if the correct registers are being used to pass arguments
-// when the sysv64 ABI is specified.
-
-#![feature(rust_2018_preview)]
-
-pub trait Foo {}
-
-// should compile without the dyn trait feature flag
-fn foo(x: &dyn Foo) {}
-
-pub fn main() {}
diff --git a/tests/ui/error-codes/E0705.rs b/tests/ui/error-codes/E0705.rs
deleted file mode 100644
index 05abcb629b1..00000000000
--- a/tests/ui/error-codes/E0705.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-// check-pass
-
-// This is a stub feature that doesn't control anything, so to make tidy happy,
-// gate-test-test_2018_feature
-
-#![feature(test_2018_feature)]
-//~^ WARN the feature `test_2018_feature` is included in the Rust 2018 edition
-#![feature(rust_2018_preview)]
-
-fn main() {}
diff --git a/tests/ui/error-codes/E0705.stderr b/tests/ui/error-codes/E0705.stderr
deleted file mode 100644
index 6fa843158bb..00000000000
--- a/tests/ui/error-codes/E0705.stderr
+++ /dev/null
@@ -1,9 +0,0 @@
-warning[E0705]: the feature `test_2018_feature` is included in the Rust 2018 edition
-  --> $DIR/E0705.rs:6:12
-   |
-LL | #![feature(test_2018_feature)]
-   |            ^^^^^^^^^^^^^^^^^
-
-warning: 1 warning emitted
-
-For more information about this error, try `rustc --explain E0705`.
diff --git a/tests/ui/extenv/extenv-env-overload.rs b/tests/ui/extenv/extenv-env-overload.rs
new file mode 100644
index 00000000000..b82bb2fe966
--- /dev/null
+++ b/tests/ui/extenv/extenv-env-overload.rs
@@ -0,0 +1,9 @@
+// run-pass
+// rustc-env:MY_VAR=tadam
+// compile-flags: --env MY_VAR=123abc -Zunstable-options
+
+// This test ensures that variables provided with `--env` take precedence over
+// variables from environment.
+fn main() {
+    assert_eq!(env!("MY_VAR"), "123abc");
+}
diff --git a/tests/ui/extenv/extenv-env.rs b/tests/ui/extenv/extenv-env.rs
new file mode 100644
index 00000000000..9fda52b8941
--- /dev/null
+++ b/tests/ui/extenv/extenv-env.rs
@@ -0,0 +1,5 @@
+// compile-flags: --env FOO=123abc -Zunstable-options
+// run-pass
+fn main() {
+    assert_eq!(env!("FOO"), "123abc");
+}
diff --git a/tests/ui/extenv/extenv-not-env.rs b/tests/ui/extenv/extenv-not-env.rs
new file mode 100644
index 00000000000..d6c4a43b003
--- /dev/null
+++ b/tests/ui/extenv/extenv-not-env.rs
@@ -0,0 +1,7 @@
+// run-pass
+// rustc-env:MY_ENV=/
+// Ensures that variables not defined through `--env` are still available.
+
+fn main() {
+    assert!(!env!("MY_ENV").is_empty());
+}
diff --git a/tests/ui/extern/issue-13655.rs b/tests/ui/extern/issue-13655.rs
index 6dd1847995f..a47b5183f2b 100644
--- a/tests/ui/extern/issue-13655.rs
+++ b/tests/ui/extern/issue-13655.rs
@@ -1,7 +1,5 @@
 // run-pass
 #![feature(fn_traits, unboxed_closures)]
-use std::ops::Fn;
-
 struct Foo<T>(T);
 
 impl<T: Copy> Fn<()> for Foo<T> {
diff --git a/tests/ui/feature-gates/env-flag.rs b/tests/ui/feature-gates/env-flag.rs
new file mode 100644
index 00000000000..9dfda2584fb
--- /dev/null
+++ b/tests/ui/feature-gates/env-flag.rs
@@ -0,0 +1,3 @@
+// compile-flags: --env A=B
+
+fn main() {}
diff --git a/tests/ui/feature-gates/env-flag.stderr b/tests/ui/feature-gates/env-flag.stderr
new file mode 100644
index 00000000000..5cb18cef9fb
--- /dev/null
+++ b/tests/ui/feature-gates/env-flag.stderr
@@ -0,0 +1,2 @@
+error: the `-Z unstable-options` flag must also be passed to enable the flag `env`
+
diff --git a/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.rs b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.rs
new file mode 100644
index 00000000000..c06107e66a7
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.rs
@@ -0,0 +1,6 @@
+fn foo(x: &Vec<i32>) -> impl Sized {
+    x
+    //~^ ERROR hidden type for `impl Sized` captures lifetime that does not appear in bounds
+}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr
new file mode 100644
index 00000000000..173e3dc02cc
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-lifetime-capture-rules-2024.stderr
@@ -0,0 +1,18 @@
+error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
+  --> $DIR/feature-gate-lifetime-capture-rules-2024.rs:2:5
+   |
+LL | fn foo(x: &Vec<i32>) -> impl Sized {
+   |           ---------     ---------- opaque type defined here
+   |           |
+   |           hidden type `&Vec<i32>` captures the anonymous lifetime defined here
+LL |     x
+   |     ^
+   |
+help: to declare that `impl Sized` captures `'_`, you can add an explicit `'_` lifetime bound
+   |
+LL | fn foo(x: &Vec<i32>) -> impl Sized + '_ {
+   |                                    ++++
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0700`.
diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs
index ca5ce3b9489..f3910622313 100644
--- a/tests/ui/feature-gates/feature-gate-never_patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs
@@ -12,16 +12,63 @@ fn main() {
     unsafe {
         let ptr: *const Void = NonNull::dangling().as_ptr();
         match *ptr {
-            ! //~ ERROR `!` patterns are experimental
+            !
+            //~^ ERROR `!` patterns are experimental
+        }
+        // Check that the gate operates even behind `cfg`.
+        #[cfg(FALSE)]
+        match *ptr {
+            !
+            //~^ ERROR `!` patterns are experimental
+        }
+        #[cfg(FALSE)]
+        match *ptr {
+            ! => {}
+            //~^ ERROR `!` patterns are experimental
         }
     }
 
+    // Correctly gate match arms with no body.
+    match Some(0) {
+        None => {}
+        Some(_),
+        //~^ ERROR unexpected `,` in pattern
+    }
+    match Some(0) {
+        None => {}
+        Some(_)
+        //~^ ERROR `match` arm with no body
+    }
+    match Some(0) {
+        _ => {}
+        Some(_) if false,
+        //~^ ERROR `match` arm with no body
+        Some(_) if false
+        //~^ ERROR `match` arm with no body
+    }
+    match res {
+        Ok(_) => {}
+        Err(!),
+        //~^ ERROR `!` patterns are experimental
+    }
+    match res {
+        Err(!) if false,
+        //~^ ERROR `!` patterns are experimental
+        //~| ERROR a guard on a never pattern will never be run
+        _ => {}
+    }
+
     // Check that the gate operates even behind `cfg`.
-    #[cfg(FALSE)]
-    unsafe {
-        let ptr: *const Void = NonNull::dangling().as_ptr();
-        match *ptr {
-            ! => {} //~ ERROR `!` patterns are experimental
-        }
+    match Some(0) {
+        None => {}
+        #[cfg(FALSE)]
+        Some(_)
+        //~^ ERROR `match` arm with no body
+    }
+    match Some(0) {
+        _ => {}
+        #[cfg(FALSE)]
+        Some(_) if false
+        //~^ ERROR `match` arm with no body
     }
 }
diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr
index 2354a3b0476..dd10829d495 100644
--- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr
+++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr
@@ -1,3 +1,18 @@
+error: unexpected `,` in pattern
+  --> $DIR/feature-gate-never_patterns.rs:34:16
+   |
+LL |         Some(_),
+   |                ^
+   |
+help: try adding parentheses to match on a tuple...
+   |
+LL |         (Some(_),)
+   |         +        +
+help: ...or a vertical bar to match on multiple alternatives
+   |
+LL |         Some(_) |
+   |
+
 error[E0408]: variable `_x` is not bound in all patterns
   --> $DIR/feature-gate-never_patterns.rs:8:19
    |
@@ -25,7 +40,16 @@ LL |             !
    = help: add `#![feature(never_patterns)]` to the crate attributes to enable
 
 error[E0658]: `!` patterns are experimental
-  --> $DIR/feature-gate-never_patterns.rs:24:13
+  --> $DIR/feature-gate-never_patterns.rs:21:13
+   |
+LL |             !
+   |             ^
+   |
+   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
+   = help: add `#![feature(never_patterns)]` to the crate attributes to enable
+
+error[E0658]: `!` patterns are experimental
+  --> $DIR/feature-gate-never_patterns.rs:26:13
    |
 LL |             ! => {}
    |             ^
@@ -33,7 +57,61 @@ LL |             ! => {}
    = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
    = help: add `#![feature(never_patterns)]` to the crate attributes to enable
 
-error: aborting due to 4 previous errors
+error: `match` arm with no body
+  --> $DIR/feature-gate-never_patterns.rs:39:9
+   |
+LL |         Some(_)
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/feature-gate-never_patterns.rs:44:9
+   |
+LL |         Some(_) if false,
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/feature-gate-never_patterns.rs:46:9
+   |
+LL |         Some(_) if false
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error[E0658]: `!` patterns are experimental
+  --> $DIR/feature-gate-never_patterns.rs:51:13
+   |
+LL |         Err(!),
+   |             ^
+   |
+   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
+   = help: add `#![feature(never_patterns)]` to the crate attributes to enable
+
+error[E0658]: `!` patterns are experimental
+  --> $DIR/feature-gate-never_patterns.rs:55:13
+   |
+LL |         Err(!) if false,
+   |             ^
+   |
+   = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
+   = help: add `#![feature(never_patterns)]` to the crate attributes to enable
+
+error: `match` arm with no body
+  --> $DIR/feature-gate-never_patterns.rs:65:9
+   |
+LL |         Some(_)
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/feature-gate-never_patterns.rs:71:9
+   |
+LL |         Some(_) if false
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: a guard on a never pattern will never be run
+  --> $DIR/feature-gate-never_patterns.rs:55:19
+   |
+LL |         Err(!) if false,
+   |                   ^^^^^ help: remove this guard
+
+error: aborting due to 14 previous errors
 
 Some errors have detailed explanations: E0408, E0658.
 For more information about an error, try `rustc --explain E0408`.
diff --git a/tests/ui/for-loop-while/while-prelude-drop.rs b/tests/ui/for-loop-while/while-prelude-drop.rs
index 196b9daf6ec..947a70e1dd2 100644
--- a/tests/ui/for-loop-while/while-prelude-drop.rs
+++ b/tests/ui/for-loop-while/while-prelude-drop.rs
@@ -1,8 +1,5 @@
 // run-pass
 #![allow(non_camel_case_types)]
-
-use std::string::String;
-
 #[derive(PartialEq)]
 enum t { a, b(String), }
 
diff --git a/tests/ui/hygiene/unpretty-debug.stdout b/tests/ui/hygiene/unpretty-debug.stdout
index 51c21043db8..3d686f95df9 100644
--- a/tests/ui/hygiene/unpretty-debug.stdout
+++ b/tests/ui/hygiene/unpretty-debug.stdout
@@ -8,7 +8,7 @@
 #![feature /* 0#0 */(no_core)]
 #![no_core /* 0#0 */]
 
-macro_rules! foo /* 0#0 */ { ($x : ident) => { y + $x } }
+macro_rules! foo /* 0#0 */ { ($x: ident) => { y + $x } }
 
 fn bar /* 0#0 */() {
     let x /* 0#0 */ = 1;
diff --git a/tests/ui/impl-trait/implicit-capture-late.rs b/tests/ui/impl-trait/implicit-capture-late.rs
new file mode 100644
index 00000000000..8bfb16760c9
--- /dev/null
+++ b/tests/ui/impl-trait/implicit-capture-late.rs
@@ -0,0 +1,14 @@
+// known-bug: #117647
+
+#![feature(lifetime_capture_rules_2024)]
+#![feature(rustc_attrs)]
+#![allow(internal_features)]
+#![rustc_variance_of_opaques]
+
+use std::ops::Deref;
+
+fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
+    Box::new(x)
+}
+
+fn main() {}
diff --git a/tests/ui/impl-trait/implicit-capture-late.stderr b/tests/ui/impl-trait/implicit-capture-late.stderr
new file mode 100644
index 00000000000..9b3a4ff5f42
--- /dev/null
+++ b/tests/ui/impl-trait/implicit-capture-late.stderr
@@ -0,0 +1,9 @@
+error[E0657]: `impl Trait` can only capture lifetimes bound at the fn or impl level
+  --> $DIR/implicit-capture-late.rs:10:36
+   |
+LL | fn foo(x: Vec<i32>) -> Box<dyn for<'a> Deref<Target = impl ?Sized>> {
+   |                                    ^^
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0657`.
diff --git a/tests/ui/impl-trait/variance.e2024.stderr b/tests/ui/impl-trait/variance.e2024.stderr
new file mode 100644
index 00000000000..17245055744
--- /dev/null
+++ b/tests/ui/impl-trait/variance.e2024.stderr
@@ -0,0 +1,26 @@
+error: [*, o]
+  --> $DIR/variance.rs:14:36
+   |
+LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
+   |                                    ^^^^^^^^^^
+
+error: [*, o]
+  --> $DIR/variance.rs:19:32
+   |
+LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [o]
+  --> $DIR/variance.rs:21:40
+   |
+LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
+   |                                        ^^^^^^^^^^
+
+error: [o]
+  --> $DIR/variance.rs:26:36
+   |
+LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/impl-trait/variance.new.stderr b/tests/ui/impl-trait/variance.new.stderr
new file mode 100644
index 00000000000..17245055744
--- /dev/null
+++ b/tests/ui/impl-trait/variance.new.stderr
@@ -0,0 +1,26 @@
+error: [*, o]
+  --> $DIR/variance.rs:14:36
+   |
+LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
+   |                                    ^^^^^^^^^^
+
+error: [*, o]
+  --> $DIR/variance.rs:19:32
+   |
+LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: [o]
+  --> $DIR/variance.rs:21:40
+   |
+LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
+   |                                        ^^^^^^^^^^
+
+error: [o]
+  --> $DIR/variance.rs:26:36
+   |
+LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
+   |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/impl-trait/variance.stderr b/tests/ui/impl-trait/variance.old.stderr
index 64473675410..9410b54b491 100644
--- a/tests/ui/impl-trait/variance.stderr
+++ b/tests/ui/impl-trait/variance.old.stderr
@@ -1,23 +1,23 @@
 error: [*]
-  --> $DIR/variance.rs:8:36
+  --> $DIR/variance.rs:14:36
    |
 LL | fn not_captured_early<'a: 'a>() -> impl Sized {}
    |                                    ^^^^^^^^^^
 
 error: [*, o]
-  --> $DIR/variance.rs:10:32
+  --> $DIR/variance.rs:19:32
    |
 LL | fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {}
    |                                ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: []
-  --> $DIR/variance.rs:12:40
+  --> $DIR/variance.rs:21:40
    |
 LL | fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
    |                                        ^^^^^^^^^^
 
 error: [o]
-  --> $DIR/variance.rs:14:36
+  --> $DIR/variance.rs:26:36
    |
 LL | fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {}
    |                                    ^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/impl-trait/variance.rs b/tests/ui/impl-trait/variance.rs
index d6212f8f393..86da1908509 100644
--- a/tests/ui/impl-trait/variance.rs
+++ b/tests/ui/impl-trait/variance.rs
@@ -1,3 +1,9 @@
+// revisions: old new e2024
+//[e2024] edition: 2024
+//[e2024] compile-flags: -Z unstable-options
+
+#![cfg_attr(new, feature(lifetime_capture_rules_2024))]
+
 #![feature(rustc_attrs)]
 #![allow(internal_features)]
 #![rustc_variance_of_opaques]
@@ -5,11 +11,17 @@
 trait Captures<'a> {}
 impl<T> Captures<'_> for T {}
 
-fn not_captured_early<'a: 'a>() -> impl Sized {} //~ [*]
+fn not_captured_early<'a: 'a>() -> impl Sized {}
+//[old]~^ [*]
+//[new]~^^ [*, o]
+//[e2024]~^^^ [*, o]
 
 fn captured_early<'a: 'a>() -> impl Sized + Captures<'a> {} //~ [*, o]
 
-fn not_captured_late<'a>(_: &'a ()) -> impl Sized {} //~ []
+fn not_captured_late<'a>(_: &'a ()) -> impl Sized {}
+//[old]~^ []
+//[new]~^^ [o]
+//[e2024]~^^^ [o]
 
 fn captured_late<'a>(_: &'a ()) -> impl Sized + Captures<'a> {} //~ [o]
 
diff --git a/tests/ui/infinite/issue-41731-infinite-macro-print.stderr b/tests/ui/infinite/issue-41731-infinite-macro-print.stderr
index e30b2039d69..71510816d0b 100644
--- a/tests/ui/infinite/issue-41731-infinite-macro-print.stderr
+++ b/tests/ui/infinite/issue-41731-infinite-macro-print.stderr
@@ -14,13 +14,13 @@ LL |     stack!("overflow");
    |     ^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `stack! { "overflow" }`
-   = note: to `print! (stack! ("overflow")) ;`
+   = note: to `print! (stack! ("overflow"));`
    = note: expanding `print! { stack! ("overflow") }`
-   = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))); }`
    = note: expanding `stack! { "overflow" }`
-   = note: to `print! (stack! ("overflow")) ;`
+   = note: to `print! (stack! ("overflow"));`
    = note: expanding `print! { stack! ("overflow") }`
-   = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args! (stack! ("overflow"))); }`
 
 error: format argument must be a string literal
   --> $DIR/issue-41731-infinite-macro-print.rs:14:5
diff --git a/tests/ui/infinite/issue-41731-infinite-macro-println.stderr b/tests/ui/infinite/issue-41731-infinite-macro-println.stderr
index 66b466dafa0..645176d45cb 100644
--- a/tests/ui/infinite/issue-41731-infinite-macro-println.stderr
+++ b/tests/ui/infinite/issue-41731-infinite-macro-println.stderr
@@ -14,13 +14,13 @@ LL |     stack!("overflow");
    |     ^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `stack! { "overflow" }`
-   = note: to `println! (stack! ("overflow")) ;`
+   = note: to `println! (stack! ("overflow"));`
    = note: expanding `println! { stack! ("overflow") }`
-   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))); }`
    = note: expanding `stack! { "overflow" }`
-   = note: to `println! (stack! ("overflow")) ;`
+   = note: to `println! (stack! ("overflow"));`
    = note: expanding `println! { stack! ("overflow") }`
-   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! (stack! ("overflow"))); }`
 
 error: format argument must be a string literal
   --> $DIR/issue-41731-infinite-macro-println.rs:14:5
diff --git a/tests/ui/issues/issue-17336.rs b/tests/ui/issues/issue-17336.rs
index 89ce59b11f2..97782ff9f0e 100644
--- a/tests/ui/issues/issue-17336.rs
+++ b/tests/ui/issues/issue-17336.rs
@@ -1,5 +1,8 @@
 // build-pass
+
 #![allow(unused_must_use)]
+#![allow(ambiguous_wide_pointer_comparisons)]
+
 #[allow(dead_code)]
 fn check(a: &str) {
     let x = a as *const str;
diff --git a/tests/ui/issues/issue-20847.rs b/tests/ui/issues/issue-20847.rs
index 0cd7edf89db..03e632263e6 100644
--- a/tests/ui/issues/issue-20847.rs
+++ b/tests/ui/issues/issue-20847.rs
@@ -1,8 +1,6 @@
 // run-pass
 #![feature(fn_traits)]
 
-use std::ops::Fn;
-
 fn say(x: u32, y: u32) {
     println!("{} {}", x, y);
 }
diff --git a/tests/ui/issues/issue-5554.rs b/tests/ui/issues/issue-5554.rs
index 7737536f43d..afe333ed709 100644
--- a/tests/ui/issues/issue-5554.rs
+++ b/tests/ui/issues/issue-5554.rs
@@ -2,7 +2,6 @@
 #![allow(dead_code)]
 // pretty-expanded FIXME #23616
 
-use std::default::Default;
 
 pub struct X<T> {
     a: T,
diff --git a/tests/ui/issues/issue-8783.rs b/tests/ui/issues/issue-8783.rs
index 4eb49c82161..cfffd9eb018 100644
--- a/tests/ui/issues/issue-8783.rs
+++ b/tests/ui/issues/issue-8783.rs
@@ -2,8 +2,6 @@
 #![allow(unused_variables)]
 // pretty-expanded FIXME #23616
 
-use std::default::Default;
-
 struct X { pub x: usize }
 impl Default for X {
     fn default() -> X {
diff --git a/tests/ui/lint/wide_pointer_comparisons.rs b/tests/ui/lint/wide_pointer_comparisons.rs
new file mode 100644
index 00000000000..8334575cf52
--- /dev/null
+++ b/tests/ui/lint/wide_pointer_comparisons.rs
@@ -0,0 +1,138 @@
+// check-pass
+
+use std::rc::Rc;
+use std::sync::Arc;
+use std::cmp::PartialEq;
+
+struct A;
+struct B;
+
+trait T {}
+impl T for A {}
+impl T for B {}
+
+fn main() {
+    let ab = (A, B);
+    let a = &ab.0 as *const dyn T;
+    let b = &ab.1 as *const dyn T;
+
+    let _ = a == b;
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a != b;
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a < b;
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a <= b;
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a > b;
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a >= b;
+    //~^ WARN ambiguous wide pointer comparison
+
+    let _ = PartialEq::eq(&a, &b);
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = PartialEq::ne(&a, &b);
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a.eq(&b);
+    //~^ WARN ambiguous wide pointer comparison
+    let _ = a.ne(&b);
+    //~^ WARN ambiguous wide pointer comparison
+
+    {
+        // &*const ?Sized
+        let a = &a;
+        let b = &b;
+
+        let _ = a == b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a != b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a < b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a <= b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a > b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a >= b;
+        //~^ WARN ambiguous wide pointer comparison
+
+        let _ = PartialEq::eq(a, b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = PartialEq::ne(a, b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = PartialEq::eq(&a, &b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = PartialEq::ne(&a, &b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a.eq(b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a.ne(b);
+        //~^ WARN ambiguous wide pointer comparison
+    }
+
+    let s = "" as *const str;
+    let _ = s == s;
+    //~^ WARN ambiguous wide pointer comparison
+
+    let s = &[8, 7][..] as *const [i32];
+    let _ = s == s;
+    //~^ WARN ambiguous wide pointer comparison
+
+    fn cmp<T: ?Sized>(a: *mut T, b: *mut T) -> bool {
+        let _ = a == b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a != b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a < b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a <= b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a > b;
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a >= b;
+        //~^ WARN ambiguous wide pointer comparison
+
+        let _ = PartialEq::eq(&a, &b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = PartialEq::ne(&a, &b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a.eq(&b);
+        //~^ WARN ambiguous wide pointer comparison
+        let _ = a.ne(&b);
+        //~^ WARN ambiguous wide pointer comparison
+
+        let a = &a;
+        let b = &b;
+        &*a == &*b
+        //~^ WARN ambiguous wide pointer comparison
+    }
+
+    {
+        macro_rules! cmp {
+            ($a:ident, $b:ident) => { $a == $b }
+            //~^ WARN ambiguous wide pointer comparison
+        }
+
+        cmp!(a, b);
+    }
+
+    {
+        // this produce weird diagnostics
+        macro_rules! cmp {
+            ($a:expr, $b:expr) => { $a == $b }
+            //~^ WARN ambiguous wide pointer comparison
+        }
+
+        cmp!(&a, &b);
+    }
+
+    let _ = std::ptr::eq(a, b);
+    let _ = std::ptr::addr_eq(a, b);
+    let _ = a as *const () == b as *const ();
+
+    let a: Rc<dyn std::fmt::Debug> = Rc::new(1);
+    Rc::ptr_eq(&a, &a);
+
+    let a: Arc<dyn std::fmt::Debug> = Arc::new(1);
+    Arc::ptr_eq(&a, &a);
+}
diff --git a/tests/ui/lint/wide_pointer_comparisons.stderr b/tests/ui/lint/wide_pointer_comparisons.stderr
new file mode 100644
index 00000000000..926b8775902
--- /dev/null
+++ b/tests/ui/lint/wide_pointer_comparisons.stderr
@@ -0,0 +1,452 @@
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:19:13
+   |
+LL |     let _ = a == b;
+   |             ^^^^^^
+   |
+   = note: `#[warn(ambiguous_wide_pointer_comparisons)]` on by default
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ++++++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:21:13
+   |
+LL |     let _ = a != b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             +++++++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:23:13
+   |
+LL |     let _ = a < b;
+   |             ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () < b as *const ();
+   |               ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:25:13
+   |
+LL |     let _ = a <= b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () <= b as *const ();
+   |               ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:27:13
+   |
+LL |     let _ = a > b;
+   |             ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () > b as *const ();
+   |               ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:29:13
+   |
+LL |     let _ = a >= b;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = a as *const () >= b as *const ();
+   |               ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:32:13
+   |
+LL |     let _ = PartialEq::eq(&a, &b);
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ~~~~~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:34:13
+   |
+LL |     let _ = PartialEq::ne(&a, &b);
+   |             ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             ~~~~~~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:36:13
+   |
+LL |     let _ = a.eq(&b);
+   |             ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(a, b);
+   |             ++++++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:38:13
+   |
+LL |     let _ = a.ne(&b);
+   |             ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = !std::ptr::addr_eq(a, b);
+   |             +++++++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:46:17
+   |
+LL |         let _ = a == b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 +++++++++++++++++++ ~~~ +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:48:17
+   |
+LL |         let _ = a != b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ++++++++++++++++++++ ~~~ +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:50:17
+   |
+LL |         let _ = a < b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () < *b as *const ();
+   |                 +  ++++++++++++   +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:52:17
+   |
+LL |         let _ = a <= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () <= *b as *const ();
+   |                 +  ++++++++++++    +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:54:17
+   |
+LL |         let _ = a > b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () > *b as *const ();
+   |                 +  ++++++++++++   +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:56:17
+   |
+LL |         let _ = a >= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = *a as *const () >= *b as *const ();
+   |                 +  ++++++++++++    +  ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:59:17
+   |
+LL |         let _ = PartialEq::eq(a, b);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:61:17
+   |
+LL |         let _ = PartialEq::ne(a, b);
+   |                 ^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:63:17
+   |
+LL |         let _ = PartialEq::eq(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:65:17
+   |
+LL |         let _ = PartialEq::ne(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ~~~~~~~~~~~~~~~~~~~~ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:67:17
+   |
+LL |         let _ = a.eq(b);
+   |                 ^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(*a, *b);
+   |                 +++++++++++++++++++ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:69:17
+   |
+LL |         let _ = a.ne(b);
+   |                 ^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(*a, *b);
+   |                 ++++++++++++++++++++ ~~~ ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:74:13
+   |
+LL |     let _ = s == s;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(s, s);
+   |             ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |     let _ = std::ptr::eq(s, s);
+   |             +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:78:13
+   |
+LL |     let _ = s == s;
+   |             ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |     let _ = std::ptr::addr_eq(s, s);
+   |             ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |     let _ = std::ptr::eq(s, s);
+   |             +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:82:17
+   |
+LL |         let _ = a == b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 +++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:84:17
+   |
+LL |         let _ = a != b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 +++++++++++++++++++ ~  +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ++++++++++++++ ~  +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:86:17
+   |
+LL |         let _ = a < b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () < b as *const ();
+   |                   ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:88:17
+   |
+LL |         let _ = a <= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () <= b as *const ();
+   |                   ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:90:17
+   |
+LL |         let _ = a > b;
+   |                 ^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () > b as *const ();
+   |                   ++++++++++++     ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:92:17
+   |
+LL |         let _ = a >= b;
+   |                 ^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = a as *const () >= b as *const ();
+   |                   ++++++++++++      ++++++++++++
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:95:17
+   |
+LL |         let _ = PartialEq::eq(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ~~~~~~~~~~~~~~~~~~ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 ~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:97:17
+   |
+LL |         let _ = PartialEq::ne(&a, &b);
+   |                 ^^^^^^^^^^^^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 ~~~~~~~~~~~~~~~~~~~ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ~~~~~~~~~~~~~~ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:99:17
+   |
+LL |         let _ = a.eq(&b);
+   |                 ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = std::ptr::addr_eq(a, b);
+   |                 ++++++++++++++++++ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = std::ptr::eq(a, b);
+   |                 +++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:101:17
+   |
+LL |         let _ = a.ne(&b);
+   |                 ^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         let _ = !std::ptr::addr_eq(a, b);
+   |                 +++++++++++++++++++ ~  ~
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         let _ = !std::ptr::eq(a, b);
+   |                 ++++++++++++++ ~  ~
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:106:9
+   |
+LL |         &*a == &*b
+   |         ^^^^^^^^^^
+   |
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |         std::ptr::addr_eq(*a, *b)
+   |         ~~~~~~~~~~~~~~~~~~  ~   +
+help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   |
+LL |         std::ptr::eq(*a, *b)
+   |         ~~~~~~~~~~~~~  ~   +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:112:39
+   |
+LL |             ($a:ident, $b:ident) => { $a == $b }
+   |                                       ^^^^^^^^
+...
+LL |         cmp!(a, b);
+   |         ---------- in this macro invocation
+   |
+   = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   |
+LL |             ($a:ident, $b:ident) => { std::ptr::addr_eq($a, $b) }
+   |                                       ++++++++++++++++++  ~   +
+
+warning: ambiguous wide pointer comparison, the comparison includes metadata which may not be expected
+  --> $DIR/wide_pointer_comparisons.rs:122:37
+   |
+LL |             ($a:expr, $b:expr) => { $a == $b }
+   |                                     ^^
+...
+LL |         cmp!(&a, &b);
+   |         ------------ in this macro invocation
+   |
+   = help: use explicit `std::ptr::eq` method to compare metadata and addresses
+   = help: use `std::ptr::addr_eq` or untyped pointers to only compare their addresses
+   = note: this warning originates in the macro `cmp` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+warning: 37 warnings emitted
+
diff --git a/tests/ui/macros/stringify.rs b/tests/ui/macros/stringify.rs
index c0eb7f01fdb..6fc12509aad 100644
--- a/tests/ui/macros/stringify.rs
+++ b/tests/ui/macros/stringify.rs
@@ -10,6 +10,8 @@
 #![feature(coroutines)]
 #![feature(decl_macro)]
 #![feature(explicit_tail_calls)]
+#![feature(if_let_guard)]
+#![feature(let_chains)]
 #![feature(more_qualified_paths)]
 #![feature(never_patterns)]
 #![feature(raw_ref_op)]
@@ -47,7 +49,7 @@ macro_rules! c1 {
 // easy to find the cases where the two pretty-printing approaches give
 // different results.
 macro_rules! c2 {
-    ($frag:ident, [$($tt:tt)*], $s1:literal, $s2:literal) => {
+    ($frag:ident, [$($tt:tt)*], $s1:literal, $s2:literal $(,)?) => {
         assert_ne!($s1, $s2, "should use `c1!` instead");
         assert_eq!($frag!($($tt)*), $s1);
         assert_eq!(stringify!($($tt)*), $s2);
@@ -59,19 +61,13 @@ fn test_block() {
     c1!(block, [ {} ], "{}");
     c1!(block, [ { true } ], "{ true }");
     c1!(block, [ { return } ], "{ return }");
-    c2!(block, [ {
-            return;
-        } ],
-        "{ return; }",
-        "{ return ; }"
-    );
-    c2!(block,
+    c1!(block, [ { return; } ], "{ return; }");
+    c1!(block,
         [ {
             let _;
             true
         } ],
-        "{ let _; true }",
-        "{ let _ ; true }"
+        "{ let _; true }"
     );
 }
 
@@ -88,17 +84,18 @@ fn test_expr() {
 
     // ExprKind::Call
     c1!(expr, [ f() ], "f()");
-    c2!(expr, [ f::<u8>() ], "f::<u8>()", "f :: < u8 > ()");
-    c2!(expr, [ f::<1>() ], "f::<1>()", "f :: < 1 > ()");
-    c2!(expr, [ f::<'a, u8, 1>() ], "f::<'a, u8, 1>()", "f :: < 'a, u8, 1 > ()");
+    c1!(expr, [ f::<u8>() ], "f::<u8>()");
+    c2!(expr, [ f ::  < u8>( ) ], "f::<u8>()", "f :: < u8>()");
+    c1!(expr, [ f::<1>() ], "f::<1>()");
+    c1!(expr, [ f::<'a, u8, 1>() ], "f::<'a, u8, 1>()");
     c1!(expr, [ f(true) ], "f(true)");
     c2!(expr, [ f(true,) ], "f(true)", "f(true,)");
-    c2!(expr, [ ()() ], "()()", "() ()");
+    c1!(expr, [ ()() ], "()()");
 
     // ExprKind::MethodCall
     c1!(expr, [ x.f() ], "x.f()");
-    c2!(expr, [ x.f::<u8>() ], "x.f::<u8>()", "x.f :: < u8 > ()");
-    c2!(expr, [ x.collect::<Vec<_>>() ], "x.collect::<Vec<_>>()", "x.collect :: < Vec < _ >> ()");
+    c1!(expr, [ x.f::<u8>() ], "x.f::<u8>()");
+    c1!(expr, [ x.collect::<Vec<_>>() ], "x.collect::<Vec<_>>()");
 
     // ExprKind::Tup
     c1!(expr, [ () ], "()");
@@ -110,18 +107,14 @@ fn test_expr() {
     c1!(expr, [ true || false ], "true || false");
     c1!(expr, [ true || false && false ], "true || false && false");
     c1!(expr, [ a < 1 && 2 < b && c > 3 && 4 > d ], "a < 1 && 2 < b && c > 3 && 4 > d");
-    c2!(expr, [ a & b & !c ], "a & b & !c", "a & b &! c"); // FIXME
-    c2!(expr,
-        [ a + b * c - d + -1 * -2 - -3],
-        "a + b * c - d + -1 * -2 - -3",
-        "a + b * c - d + - 1 * - 2 - - 3"
-    );
-    c2!(expr, [ x = !y ], "x = !y", "x =! y"); // FIXME
+    c2!(expr, [ a & b & !c ], "a & b & !c", "a & b &!c"); // FIXME
+    c1!(expr, [ a + b * c - d + -1 * -2 - -3], "a + b * c - d + -1 * -2 - -3");
+    c2!(expr, [ x = !y ], "x = !y", "x =!y"); // FIXME
 
     // ExprKind::Unary
-    c2!(expr, [ *expr ], "*expr", "* expr");
-    c2!(expr, [ !expr ], "!expr", "! expr");
-    c2!(expr, [ -expr ], "-expr", "- expr");
+    c1!(expr, [ *expr ], "*expr");
+    c1!(expr, [ !expr ], "!expr");
+    c1!(expr, [ -expr ], "-expr");
 
     // ExprKind::Lit
     c1!(expr, [ 'x' ], "'x'");
@@ -130,21 +123,34 @@ fn test_expr() {
 
     // ExprKind::Cast
     c1!(expr, [ expr as T ], "expr as T");
-    c2!(expr, [ expr as T<u8> ], "expr as T<u8>", "expr as T < u8 >");
+    c1!(expr, [ expr as T<u8> ], "expr as T<u8>");
 
     // ExprKind::Type: there is no syntax for type ascription.
 
     // ExprKind::Let
     c1!(expr, [ if let Some(a) = b { c } else { d } ], "if let Some(a) = b { c } else { d }");
+    c1!(expr, [ if let _ = true && false {} ], "if let _ = true && false {}");
+    c1!(expr, [ if let _ = (true && false) {} ], "if let _ = (true && false) {}");
+    macro_rules! c2_if_let {
+        ($expr:expr, $expr_expected:expr, $tokens_expected:expr $(,)?) => {
+            c2!(expr, [ if let _ = $expr {} ], $expr_expected, $tokens_expected);
+        };
+    }
+    c2_if_let!(
+        true && false,
+        "if let _ = (true && false) {}",
+        "if let _ = true && false {}",
+    );
+    c2!(expr,
+        [ match () { _ if let _ = Struct {} => {} } ],
+        "match () { _ if let _ = Struct {} => {} }",
+        "match() { _ if let _ = Struct {} => {} }",
+    );
 
     // ExprKind::If
     c1!(expr, [ if true {} ], "if true {}");
-    c2!(expr, [ if !true {} ], "if !true {}", "if! true {}"); // FIXME
-    c2!(expr,
-        [ if ::std::blah() { } else { } ],
-        "if ::std::blah() {} else {}",
-        "if :: std :: blah() {} else {}"
-    );
+    c2!(expr, [ if !true {} ], "if !true {}", "if!true {}"); // FIXME
+    c1!(expr, [ if ::std::blah() { } else { } ], "if ::std::blah() {} else {}");
     c1!(expr, [ if let true = true {} else {} ], "if let true = true {} else {}");
     c1!(expr,
         [ if true {
@@ -159,7 +165,7 @@ fn test_expr() {
         } ],
         "if true {} else if false {} else {}"
     );
-    c2!(expr,
+    c1!(expr,
         [ if true {
             return;
         } else if false {
@@ -167,22 +173,21 @@ fn test_expr() {
         } else {
             0
         } ],
-        "if true { return; } else if false { 0 } else { 0 }",
-        "if true { return ; } else if false { 0 } else { 0 }"
+        "if true { return; } else if false { 0 } else { 0 }"
     );
 
     // ExprKind::While
     c1!(expr, [ while true {} ], "while true {}");
-    c2!(expr, [ 'a: while true {} ], "'a: while true {}", "'a : while true {}");
+    c1!(expr, [ 'a: while true {} ], "'a: while true {}");
     c1!(expr, [ while let true = true {} ], "while let true = true {}");
 
     // ExprKind::ForLoop
     c1!(expr, [ for _ in x {} ], "for _ in x {}");
-    c2!(expr, [ 'a: for _ in x {} ], "'a: for _ in x {}", "'a : for _ in x {}");
+    c1!(expr, [ 'a: for _ in x {} ], "'a: for _ in x {}");
 
     // ExprKind::Loop
     c1!(expr, [ loop {} ], "loop {}");
-    c2!(expr, [ 'a: loop {} ], "'a: loop {}", "'a : loop {}");
+    c1!(expr, [ 'a: loop {} ], "'a: loop {}");
 
     // ExprKind::Match
     c1!(expr, [ match self {} ], "match self {}");
@@ -202,8 +207,8 @@ fn test_expr() {
 
     // ExprKind::Closure
     c1!(expr, [ || {} ], "|| {}");
-    c2!(expr, [ |x| {} ], "|x| {}", "| x | {}");
-    c2!(expr, [ |x: u8| {} ], "|x: u8| {}", "| x : u8 | {}");
+    c1!(expr, [ |x| {} ], "|x| {}");
+    c1!(expr, [ |x: u8| {} ], "|x: u8| {}");
     c1!(expr, [ || () ], "|| ()");
     c1!(expr, [ move || self ], "move || self");
     c1!(expr, [ async || self ], "async || self");
@@ -218,7 +223,7 @@ fn test_expr() {
     // ExprKind::Block
     c1!(expr, [ {} ], "{}");
     c1!(expr, [ unsafe {} ], "unsafe {}");
-    c2!(expr, [ 'a: {} ], "'a: {}", "'a : {}");
+    c1!(expr, [ 'a: {} ], "'a: {}");
     c1!(expr, [ #[attr] {} ], "#[attr] {}");
     c2!(expr,
         [
@@ -229,7 +234,7 @@ fn test_expr() {
         "{\n\
         \x20   #![attr]\n\
         }",
-        "{ #! [attr] }"
+        "{ #![attr] }"
     );
 
     // ExprKind::Async
@@ -253,34 +258,35 @@ fn test_expr() {
     c1!(expr, [ expr.0 ], "expr.0");
 
     // ExprKind::Index
-    c2!(expr, [ expr[true] ], "expr[true]", "expr [true]");
+    c1!(expr, [ expr[true] ], "expr[true]");
 
     // ExprKind::Range
     c1!(expr, [ .. ], "..");
-    c2!(expr, [ ..hi ], "..hi", ".. hi");
-    c2!(expr, [ lo.. ], "lo..", "lo ..");
-    c2!(expr, [ lo..hi ], "lo..hi", "lo .. hi");
-    c2!(expr, [ ..=hi ], "..=hi", "..= hi");
-    c2!(expr, [ lo..=hi ], "lo..=hi", "lo ..= hi");
-    c2!(expr, [ -2..=-1 ], "-2..=-1", "- 2 ..= - 1");
+    c1!(expr, [ ..hi ], "..hi");
+    c1!(expr, [ lo.. ], "lo..");
+    c1!(expr, [ lo..hi ], "lo..hi");
+    c2!(expr, [ lo .. hi ], "lo..hi", "lo .. hi");
+    c1!(expr, [ ..=hi ], "..=hi");
+    c1!(expr, [ lo..=hi ], "lo..=hi");
+    c1!(expr, [ -2..=-1 ], "-2..=-1");
 
     // ExprKind::Underscore
     // FIXME: todo
 
     // ExprKind::Path
     c1!(expr, [ thing ], "thing");
-    c2!(expr, [ m::thing ], "m::thing", "m :: thing");
-    c2!(expr, [ self::thing ], "self::thing", "self :: thing");
-    c2!(expr, [ crate::thing ], "crate::thing", "crate :: thing");
-    c2!(expr, [ Self::thing ], "Self::thing", "Self :: thing");
-    c2!(expr, [ <Self as T>::thing ], "<Self as T>::thing", "< Self as T > :: thing");
-    c2!(expr, [ Self::<'static> ], "Self::<'static>", "Self :: < 'static >");
+    c1!(expr, [ m::thing ], "m::thing");
+    c1!(expr, [ self::thing ], "self::thing");
+    c1!(expr, [ crate::thing ], "crate::thing");
+    c1!(expr, [ Self::thing ], "Self::thing");
+    c1!(expr, [ <Self as T>::thing ], "<Self as T>::thing");
+    c1!(expr, [ Self::<'static> ], "Self::<'static>");
 
     // ExprKind::AddrOf
-    c2!(expr, [ &expr ], "&expr", "& expr");
-    c2!(expr, [ &mut expr ], "&mut expr", "& mut expr");
-    c2!(expr, [ &raw const expr ], "&raw const expr", "& raw const expr");
-    c2!(expr, [ &raw mut expr ], "&raw mut expr", "& raw mut expr");
+    c1!(expr, [ &expr ], "&expr");
+    c1!(expr, [ &mut expr ], "&mut expr");
+    c1!(expr, [ &raw const expr ], "&raw const expr");
+    c1!(expr, [ &raw mut expr ], "&raw mut expr");
 
     // ExprKind::Break
     c1!(expr, [ break ], "break");
@@ -301,38 +307,30 @@ fn test_expr() {
     // ExprKind::OffsetOf: untestable because this test works pre-expansion.
 
     // ExprKind::MacCall
-    c2!(expr, [ mac!(...) ], "mac!(...)", "mac! (...)");
-    c2!(expr, [ mac![...] ], "mac![...]", "mac! [...]");
+    c1!(expr, [ mac!(...) ], "mac!(...)");
+    c1!(expr, [ mac![...] ], "mac![...]");
     c1!(expr, [ mac! { ... } ], "mac! { ... }");
 
     // ExprKind::Struct
     c1!(expr, [ Struct {} ], "Struct {}");
-    c2!(expr,
-        [ <Struct as Trait>::Type {} ],
-        "<Struct as Trait>::Type {}",
-        "< Struct as Trait > :: Type {}"
-    );
+    c1!(expr, [ <Struct as Trait>::Type {} ], "<Struct as Trait>::Type {}");
     c1!(expr, [ Struct { .. } ], "Struct { .. }");
-    c2!(expr, [ Struct { ..base } ], "Struct { ..base }", "Struct { .. base }");
+    c1!(expr, [ Struct { ..base } ], "Struct { ..base }");
     c1!(expr, [ Struct { x } ], "Struct { x }");
     c1!(expr, [ Struct { x, .. } ], "Struct { x, .. }");
-    c2!(expr, [ Struct { x, ..base } ], "Struct { x, ..base }", "Struct { x, .. base }");
-    c2!(expr, [ Struct { x: true } ], "Struct { x: true }", "Struct { x : true }");
-    c2!(expr, [ Struct { x: true, .. } ], "Struct { x: true, .. }", "Struct { x : true, .. }");
-    c2!(expr,
-        [ Struct { x: true, ..base } ],
-        "Struct { x: true, ..base }",
-        "Struct { x : true, .. base }"
-    );
+    c1!(expr, [ Struct { x, ..base } ], "Struct { x, ..base }");
+    c1!(expr, [ Struct { x: true } ], "Struct { x: true }");
+    c1!(expr, [ Struct { x: true, .. } ], "Struct { x: true, .. }");
+    c1!(expr, [ Struct { x: true, ..base } ], "Struct { x: true, ..base }");
 
     // ExprKind::Repeat
-    c2!(expr, [ [(); 0] ], "[(); 0]", "[() ; 0]");
+    c1!(expr, [ [(); 0] ], "[(); 0]");
 
     // ExprKind::Paren
     c1!(expr, [ (expr) ], "(expr)");
 
     // ExprKind::Try
-    c2!(expr, [ expr? ], "expr?", "expr ?");
+    c1!(expr, [ expr? ], "expr?");
 
     // ExprKind::Yield
     c1!(expr, [ yield ], "yield");
@@ -356,51 +354,42 @@ fn test_expr() {
 #[test]
 fn test_item() {
     // ItemKind::ExternCrate
-    c2!(item, [ extern crate std; ], "extern crate std;", "extern crate std ;");
-    c2!(item,
-        [ pub extern crate self as std; ],
-        "pub extern crate self as std;",
-        "pub extern crate self as std ;"
-    );
+    c1!(item, [ extern crate std; ], "extern crate std;");
+    c1!(item, [ pub extern crate self as std; ], "pub extern crate self as std;");
 
     // ItemKind::Use
     c2!(item,
         [ pub use crate::{a, b::c}; ],
         "pub use crate::{a, b::c};",
-        "pub use crate :: { a, b :: c } ;"
+        "pub use crate::{ a, b::c };" // FIXME
     );
-    c2!(item, [ pub use A::*; ], "pub use A::*;", "pub use A :: * ;");
+    c1!(item, [ pub use A::*; ], "pub use A::*;");
 
     // ItemKind::Static
-    c2!(item, [ pub static S: () = {}; ], "pub static S: () = {};", "pub static S : () = {} ;");
-    c2!(item, [ static mut S: () = {}; ], "static mut S: () = {};", "static mut S : () = {} ;");
-    c2!(item, [ static S: (); ], "static S: ();", "static S : () ;");
-    c2!(item, [ static mut S: (); ], "static mut S: ();", "static mut S : () ;");
+    c1!(item, [ pub static S: () = {}; ], "pub static S: () = {};");
+    c1!(item, [ static mut S: () = {}; ], "static mut S: () = {};");
+    c1!(item, [ static S: (); ], "static S: ();");
+    c1!(item, [ static mut S: (); ], "static mut S: ();");
 
     // ItemKind::Const
-    c2!(item, [ pub const S: () = {}; ], "pub const S: () = {};", "pub const S : () = {} ;");
-    c2!(item, [ const S: (); ], "const S: ();", "const S : () ;");
+    c1!(item, [ pub const S: () = {}; ], "pub const S: () = {};");
+    c1!(item, [ const S: (); ], "const S: ();");
 
     // ItemKind::Fn
     c1!(item,
         [ pub default const async unsafe extern "C" fn f() {} ],
         "pub default const async unsafe extern \"C\" fn f() {}"
     );
-    c2!(item,
-        [ fn g<T>(t: Vec<Vec<Vec<T>>>) {} ],
-        "fn g<T>(t: Vec<Vec<Vec<T>>>) {}",
-        "fn g < T > (t : Vec < Vec < Vec < T >> >) {}"
-    );
-    c2!(item,
+    c1!(item, [ fn g<T>(t: Vec<Vec<Vec<T>>>) {} ], "fn g<T>(t: Vec<Vec<Vec<T>>>) {}");
+    c1!(item,
         [ fn h<'a>(t: &'a Vec<Cell<dyn D>>) {} ],
-        "fn h<'a>(t: &'a Vec<Cell<dyn D>>) {}",
-        "fn h < 'a > (t : & 'a Vec < Cell < dyn D >>) {}"
+        "fn h<'a>(t: &'a Vec<Cell<dyn D>>) {}"
     );
 
     // ItemKind::Mod
-    c2!(item, [ pub mod m; ], "pub mod m;", "pub mod m ;");
+    c1!(item, [ pub mod m; ], "pub mod m;");
     c1!(item, [ mod m {} ], "mod m {}");
-    c2!(item, [ unsafe mod m; ], "unsafe mod m;", "unsafe mod m ;");
+    c1!(item, [ unsafe mod m; ], "unsafe mod m;");
     c1!(item, [ unsafe mod m {} ], "unsafe mod m {}");
 
     // ItemKind::ForeignMod
@@ -423,7 +412,7 @@ fn test_item() {
             = T;
         ],
         "pub default type Type<'a>: Bound where Self: 'a = T;",
-        "pub default type Type < 'a > : Bound where Self : 'a, = T ;"
+        "pub default type Type<'a>: Bound where Self: 'a, = T;"
     );
 
     // ItemKind::Enum
@@ -456,13 +445,13 @@ fn test_item() {
         \x20       t: T,\n\
         \x20   },\n\
         }",
-        "enum Enum < T > where T : 'a, { Unit, Tuple(T), Struct { t : T }, }"
+        "enum Enum<T> where T: 'a, { Unit, Tuple(T), Struct { t: T }, }"
     );
 
     // ItemKind::Struct
-    c2!(item, [ pub struct Unit; ], "pub struct Unit;", "pub struct Unit ;");
-    c2!(item, [ struct Tuple(); ], "struct Tuple();", "struct Tuple() ;");
-    c2!(item, [ struct Tuple(T); ], "struct Tuple(T);", "struct Tuple(T) ;");
+    c1!(item, [ pub struct Unit; ], "pub struct Unit;");
+    c1!(item, [ struct Tuple(); ], "struct Tuple();");
+    c1!(item, [ struct Tuple(T); ], "struct Tuple(T);");
     c1!(item, [ struct Struct {} ], "struct Struct {}");
     c2!(item,
         [
@@ -476,7 +465,7 @@ fn test_item() {
         "struct Struct<T> where T: 'a {\n\
         \x20   t: T,\n\
         }",
-        "struct Struct < T > where T : 'a, { t : T, }"
+        "struct Struct<T> where T: 'a, { t: T, }"
     );
 
     // ItemKind::Union
@@ -490,7 +479,7 @@ fn test_item() {
         "union Union<T> where T: 'a {\n\
         \x20   t: T,\n\
         }",
-        "union Union < T > where T : 'a { t : T, }"
+        "union Union<T> where T: 'a { t: T, }"
     );
 
     // ItemKind::Trait
@@ -504,30 +493,25 @@ fn test_item() {
             }
         ],
         "trait Trait<'a>: Sized where Self: 'a {}",
-        "trait Trait < 'a > : Sized where Self : 'a, {}"
+        "trait Trait<'a>: Sized where Self: 'a, {}"
     );
 
     // ItemKind::TraitAlias
-    c2!(item,
+    c1!(item,
         [ pub trait Trait<T> = Sized where T: 'a; ],
-        "pub trait Trait<T> = Sized where T: 'a;",
-        "pub trait Trait < T > = Sized where T : 'a ;"
+        "pub trait Trait<T> = Sized where T: 'a;"
     );
 
     // ItemKind::Impl
     c1!(item, [ pub impl Struct {} ], "pub impl Struct {}");
-    c2!(item, [ impl<T> Struct<T> {} ], "impl<T> Struct<T> {}", "impl < T > Struct < T > {}");
+    c1!(item, [ impl<T> Struct<T> {} ], "impl<T> Struct<T> {}");
     c1!(item, [ pub impl Trait for Struct {} ], "pub impl Trait for Struct {}");
-    c2!(item,
-        [ impl<T> const Trait for T {} ],
-        "impl<T> const Trait for T {}",
-        "impl < T > const Trait for T {}"
-    );
-    c2!(item, [ impl ~const Struct {} ], "impl ~const Struct {}", "impl ~ const Struct {}");
+    c1!(item, [ impl<T> const Trait for T {} ], "impl<T> const Trait for T {}");
+    c1!(item, [ impl ~const Struct {} ], "impl ~const Struct {}");
 
     // ItemKind::MacCall
-    c2!(item, [ mac!(...); ], "mac!(...);", "mac! (...) ;");
-    c2!(item, [ mac![...]; ], "mac![...];", "mac! [...] ;");
+    c1!(item, [ mac!(...); ], "mac!(...);");
+    c1!(item, [ mac![...]; ], "mac![...];");
     c1!(item, [ mac! { ... } ], "mac! { ... }");
 
     // ItemKind::MacroDef
@@ -537,7 +521,7 @@ fn test_item() {
                 () => {};
             }
         ],
-        "macro_rules! stringify { () => {} ; }"
+        "macro_rules! stringify { () => {}; }"
     );
     c2!(item,
         [ pub macro stringify() {} ],
@@ -551,7 +535,7 @@ fn test_meta() {
     c1!(meta, [ k ], "k");
     c1!(meta, [ k = "v" ], "k = \"v\"");
     c1!(meta, [ list(k1, k2 = "v") ], "list(k1, k2 = \"v\")");
-    c2!(meta, [ serde::k ], "serde::k", "serde :: k");
+    c1!(meta, [ serde::k ], "serde::k");
 }
 
 #[test]
@@ -568,42 +552,35 @@ fn test_pat() {
 
     // PatKind::Struct
     c1!(pat, [ Struct {} ], "Struct {}");
-    c2!(pat, [ Struct::<u8> {} ], "Struct::<u8> {}", "Struct :: < u8 > {}");
-    c2!(pat, [ Struct::<'static> {} ], "Struct::<'static> {}", "Struct :: < 'static > {}");
+    c1!(pat, [ Struct::<u8> {} ], "Struct::<u8> {}");
+    c2!(pat, [ Struct ::< u8 > {} ], "Struct::<u8> {}", "Struct ::< u8 > {}");
+    c1!(pat, [ Struct::<'static> {} ], "Struct::<'static> {}");
     c1!(pat, [ Struct { x } ], "Struct { x }");
-    c2!(pat, [ Struct { x: _x } ], "Struct { x: _x }", "Struct { x : _x }");
+    c1!(pat, [ Struct { x: _x } ], "Struct { x: _x }");
     c1!(pat, [ Struct { .. } ], "Struct { .. }");
     c1!(pat, [ Struct { x, .. } ], "Struct { x, .. }");
-    c2!(pat, [ Struct { x: _x, .. } ], "Struct { x: _x, .. }", "Struct { x : _x, .. }");
-    c2!(pat,
-        [ <Struct as Trait>::Type {} ],
-        "<Struct as Trait>::Type {}",
-        "< Struct as Trait > :: Type {}"
-    );
+    c1!(pat, [ Struct { x: _x, .. } ], "Struct { x: _x, .. }");
+    c1!(pat, [ <Struct as Trait>::Type {} ], "<Struct as Trait>::Type {}");
 
     // PatKind::TupleStruct
     c1!(pat, [ Tuple() ], "Tuple()");
-    c2!(pat, [ Tuple::<u8>() ], "Tuple::<u8>()", "Tuple :: < u8 > ()");
-    c2!(pat, [ Tuple::<'static>() ], "Tuple::<'static>()", "Tuple :: < 'static > ()");
+    c1!(pat, [ Tuple::<u8>() ], "Tuple::<u8>()");
+    c1!(pat, [ Tuple::<'static>() ], "Tuple::<'static>()");
     c1!(pat, [ Tuple(x) ], "Tuple(x)");
     c1!(pat, [ Tuple(..) ], "Tuple(..)");
     c1!(pat, [ Tuple(x, ..) ], "Tuple(x, ..)");
-    c2!(pat,
-        [ <Struct as Trait>::Type() ],
-        "<Struct as Trait>::Type()",
-        "< Struct as Trait > :: Type()"
-    );
+    c1!(pat, [ <Struct as Trait>::Type() ], "<Struct as Trait>::Type()");
 
     // PatKind::Or
     c1!(pat, [ true | false ], "true | false");
     c2!(pat, [ | true ], "true", "| true");
-    c2!(pat, [ |true| false ], "true | false", "| true | false");
+    c2!(pat, [ |true| false ], "true | false", "|true| false");
 
     // PatKind::Path
-    c2!(pat, [ crate::Path ], "crate::Path", "crate :: Path");
-    c2!(pat, [ Path::<u8> ], "Path::<u8>", "Path :: < u8 >");
-    c2!(pat, [ Path::<'static> ], "Path::<'static>", "Path :: < 'static >");
-    c2!(pat, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type", "< Struct as Trait > :: Type");
+    c1!(pat, [ crate::Path ], "crate::Path");
+    c1!(pat, [ Path::<u8> ], "Path::<u8>");
+    c1!(pat, [ Path::<'static> ], "Path::<'static>");
+    c1!(pat, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type");
 
     // PatKind::Tuple
     c1!(pat, [ () ], "()");
@@ -614,18 +591,18 @@ fn test_pat() {
     c1!(pat, [ box pat ], "box pat");
 
     // PatKind::Ref
-    c2!(pat, [ &pat ], "&pat", "& pat");
-    c2!(pat, [ &mut pat ], "&mut pat", "& mut pat");
+    c1!(pat, [ &pat ], "&pat");
+    c1!(pat, [ &mut pat ], "&mut pat");
 
     // PatKind::Lit
     c1!(pat, [ 1_000_i8 ], "1_000_i8");
 
     // PatKind::Range
-    c2!(pat, [ ..1 ], "..1", ".. 1");
-    c2!(pat, [ 0.. ], "0..", "0 ..");
-    c2!(pat, [ 0..1 ], "0..1", "0 .. 1");
-    c2!(pat, [ 0..=1 ], "0..=1", "0 ..= 1");
-    c2!(pat, [ -2..=-1 ], "-2..=-1", "- 2 ..= - 1");
+    c1!(pat, [ ..1 ], "..1");
+    c1!(pat, [ 0.. ], "0..");
+    c1!(pat, [ 0..1 ], "0..1");
+    c1!(pat, [ 0..=1 ], "0..=1");
+    c1!(pat, [ -2..=-1 ], "-2..=-1");
 
     // PatKind::Slice
     c1!(pat, [ [] ], "[]");
@@ -644,20 +621,20 @@ fn test_pat() {
     c1!(pat, [ (pat) ], "(pat)");
 
     // PatKind::MacCall
-    c2!(pat, [ mac!(...) ], "mac!(...)", "mac! (...)");
-    c2!(pat, [ mac![...] ], "mac![...]", "mac! [...]");
+    c1!(pat, [ mac!(...) ], "mac!(...)");
+    c1!(pat, [ mac![...] ], "mac![...]");
     c1!(pat, [ mac! { ... } ], "mac! { ... }");
 }
 
 #[test]
 fn test_path() {
     c1!(path, [ thing ], "thing");
-    c2!(path, [ m::thing ], "m::thing", "m :: thing");
-    c2!(path, [ self::thing ], "self::thing", "self :: thing");
-    c2!(path, [ crate::thing ], "crate::thing", "crate :: thing");
-    c2!(path, [ Self::thing ], "Self::thing", "Self :: thing");
-    c2!(path, [ Self<'static> ], "Self<'static>", "Self < 'static >");
-    c2!(path, [ Self::<'static> ], "Self<'static>", "Self :: < 'static >");
+    c1!(path, [ m::thing ], "m::thing");
+    c1!(path, [ self::thing ], "self::thing");
+    c1!(path, [ crate::thing ], "crate::thing");
+    c1!(path, [ Self::thing ], "Self::thing");
+    c1!(path, [ Self<'static> ], "Self<'static>");
+    c2!(path, [ Self::<'static> ], "Self<'static>", "Self::<'static>");
     c1!(path, [ Self() ], "Self()");
     c1!(path, [ Self() -> () ], "Self() -> ()");
 }
@@ -667,16 +644,16 @@ fn test_stmt() {
     // StmtKind::Local
     c2!(stmt, [ let _ ], "let _;", "let _");
     c2!(stmt, [ let x = true ], "let x = true;", "let x = true");
-    c2!(stmt, [ let x: bool = true ], "let x: bool = true;", "let x : bool = true");
+    c2!(stmt, [ let x: bool = true ], "let x: bool = true;", "let x: bool = true");
     c2!(stmt, [ let (a, b) = (1, 2) ], "let (a, b) = (1, 2);", "let(a, b) = (1, 2)"); // FIXME
     c2!(stmt,
         [ let (a, b): (u32, u32) = (1, 2) ],
         "let (a, b): (u32, u32) = (1, 2);",
-        "let(a, b) : (u32, u32) = (1, 2)"
+        "let(a, b): (u32, u32) = (1, 2)" // FIXME
     );
 
     // StmtKind::Item
-    c2!(stmt, [ struct S; ], "struct S;", "struct S ;");
+    c1!(stmt, [ struct S; ], "struct S;");
     c1!(stmt, [ struct S {} ], "struct S {}");
 
     // StmtKind::Expr
@@ -689,8 +666,8 @@ fn test_stmt() {
     c1!(stmt, [ ; ], ";");
 
     // StmtKind::MacCall
-    c2!(stmt, [ mac!(...) ], "mac!(...)", "mac! (...)");
-    c2!(stmt, [ mac![...] ], "mac![...]", "mac! [...]");
+    c1!(stmt, [ mac!(...) ], "mac!(...)");
+    c1!(stmt, [ mac![...] ], "mac![...]");
     c1!(stmt, [ mac! { ... } ], "mac! { ... }");
 }
 
@@ -700,26 +677,27 @@ fn test_ty() {
     c1!(ty, [ [T] ], "[T]");
 
     // TyKind::Array
-    c2!(ty, [ [T; 0] ], "[T; 0]", "[T ; 0]");
+    c1!(ty, [ [T; 0] ], "[T; 0]");
 
     // TyKind::Ptr
-    c2!(ty, [ *const T ], "*const T", "* const T");
-    c2!(ty, [ *mut T ], "*mut T", "* mut T");
+    c1!(ty, [ *const T ], "*const T");
+    c1!(ty, [ *mut T ], "*mut T");
 
     // TyKind::Ref
-    c2!(ty, [ &T ], "&T", "& T");
-    c2!(ty, [ &mut T ], "&mut T", "& mut T");
-    c2!(ty, [ &'a T ], "&'a T", "& 'a T");
-    c2!(ty, [ &'a mut [T] ], "&'a mut [T]", "& 'a mut [T]");
-    c2!(ty, [ &A<B<C<D<E>>>> ], "&A<B<C<D<E>>>>", "& A < B < C < D < E >> >>");
+    c1!(ty, [ &T ], "&T");
+    c1!(ty, [ &mut T ], "&mut T");
+    c1!(ty, [ &'a T ], "&'a T");
+    c1!(ty, [ &'a mut [T] ], "&'a mut [T]");
+    c1!(ty, [ &A<B<C<D<E>>>> ], "&A<B<C<D<E>>>>");
+    c2!(ty, [ &A<B<C<D<E> > > > ], "&A<B<C<D<E>>>>", "&A<B<C<D<E> > > >");
 
     // TyKind::BareFn
     c1!(ty, [ fn() ], "fn()");
     c1!(ty, [ fn() -> () ], "fn() -> ()");
     c1!(ty, [ fn(u8) ], "fn(u8)");
-    c2!(ty, [ fn(x: u8) ], "fn(x: u8)", "fn(x : u8)");
-    c2!(ty, [ for<> fn() ], "fn()", "for < > fn()");
-    c2!(ty, [ for<'a> fn() ], "for<'a> fn()", "for < 'a > fn()");
+    c1!(ty, [ fn(x: u8) ], "fn(x: u8)");
+    c2!(ty, [ for<> fn() ], "fn()", "for<> fn()");
+    c1!(ty, [ for<'a> fn() ], "for<'a> fn()");
 
     // TyKind::Never
     c1!(ty, [ ! ], "!");
@@ -735,28 +713,28 @@ fn test_ty() {
 
     // TyKind::Path
     c1!(ty, [ T ], "T");
-    c2!(ty, [ Ref<'a> ], "Ref<'a>", "Ref < 'a >");
-    c2!(ty, [ PhantomData<T> ], "PhantomData<T>", "PhantomData < T >");
-    c2!(ty, [ PhantomData::<T> ], "PhantomData<T>", "PhantomData :: < T >");
+    c1!(ty, [ Ref<'a> ], "Ref<'a>");
+    c1!(ty, [ PhantomData<T> ], "PhantomData<T>");
+    c2!(ty, [ PhantomData::<T> ], "PhantomData<T>", "PhantomData::<T>");
     c2!(ty, [ Fn() -> ! ], "Fn() -> !", "Fn() ->!");
     c2!(ty, [ Fn(u8) -> ! ], "Fn(u8) -> !", "Fn(u8) ->!"); // FIXME
-    c2!(ty, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type", "< Struct as Trait > :: Type");
+    c1!(ty, [ <Struct as Trait>::Type ], "<Struct as Trait>::Type");
 
     // TyKind::TraitObject
     c1!(ty, [ dyn Send ], "dyn Send");
     c1!(ty, [ dyn Send + 'a ], "dyn Send + 'a");
     c1!(ty, [ dyn 'a + Send ], "dyn 'a + Send");
-    c2!(ty, [ dyn ?Sized ], "dyn ?Sized", "dyn ? Sized");
-    c2!(ty, [ dyn ~const Clone ], "dyn ~const Clone", "dyn ~ const Clone");
-    c2!(ty, [ dyn for<'a> Send ], "dyn for<'a> Send", "dyn for < 'a > Send");
+    c1!(ty, [ dyn ?Sized ], "dyn ?Sized");
+    c1!(ty, [ dyn ~const Clone ], "dyn ~const Clone");
+    c1!(ty, [ dyn for<'a> Send ], "dyn for<'a> Send");
 
     // TyKind::ImplTrait
     c1!(ty, [ impl Send ], "impl Send");
     c1!(ty, [ impl Send + 'a ], "impl Send + 'a");
     c1!(ty, [ impl 'a + Send ], "impl 'a + Send");
-    c2!(ty, [ impl ?Sized ], "impl ?Sized", "impl ? Sized");
-    c2!(ty, [ impl ~const Clone ], "impl ~const Clone", "impl ~ const Clone");
-    c2!(ty, [ impl for<'a> Send ], "impl for<'a> Send", "impl for < 'a > Send");
+    c1!(ty, [ impl ?Sized ], "impl ?Sized");
+    c1!(ty, [ impl ~const Clone ], "impl ~const Clone");
+    c1!(ty, [ impl for<'a> Send ], "impl for<'a> Send");
 
     // TyKind::Paren
     c1!(ty, [ (T) ], "(T)");
@@ -769,8 +747,8 @@ fn test_ty() {
     // TyKind::ImplicitSelf: there is no syntax for this.
 
     // TyKind::MacCall
-    c2!(ty, [ mac!(...) ], "mac!(...)", "mac! (...)");
-    c2!(ty, [ mac![...] ], "mac![...]", "mac! [...]");
+    c1!(ty, [ mac!(...) ], "mac!(...)");
+    c1!(ty, [ mac![...] ], "mac![...]");
     c1!(ty, [ mac! { ... } ], "mac! { ... }");
 
     // TyKind::Err: untestable.
@@ -791,13 +769,13 @@ fn test_vis() {
     c2!(vis, [ pub(in crate) ], "pub(in crate) ", "pub(in crate)");
     c2!(vis, [ pub(in self) ], "pub(in self) ", "pub(in self)");
     c2!(vis, [ pub(in super) ], "pub(in super) ", "pub(in super)");
-    c2!(vis, [ pub(in path::to) ], "pub(in path::to) ", "pub(in path :: to)");
-    c2!(vis, [ pub(in ::path::to) ], "pub(in ::path::to) ", "pub(in :: path :: to)");
-    c2!(vis, [ pub(in self::path::to) ], "pub(in self::path::to) ", "pub(in self :: path :: to)");
+    c2!(vis, [ pub(in path::to) ], "pub(in path::to) ", "pub(in path::to)");
+    c2!(vis, [ pub(in ::path::to) ], "pub(in ::path::to) ", "pub(in ::path::to)");
+    c2!(vis, [ pub(in self::path::to) ], "pub(in self::path::to) ", "pub(in self::path::to)");
     c2!(vis,
         [ pub(in super::path::to) ],
         "pub(in super::path::to) ",
-        "pub(in super :: path :: to)"
+        "pub(in super::path::to)"
     );
 
     // VisibilityKind::Inherited
@@ -815,7 +793,7 @@ macro_rules! p {
 
 #[test]
 fn test_punct() {
-    // For all these cases, we must preserve spaces between the tokens.
+    // For all these cases, we should preserve spaces between the tokens.
     // Otherwise, any old proc macro that parses pretty-printed code might glue
     // together tokens that shouldn't be glued.
     p!([ = = < < <= <= == == != != >= >= > > ], "= = < < <= <= == == != != >= >= > >");
@@ -828,10 +806,7 @@ fn test_punct() {
     p!([ + + += += - - -= -= * * *= *= / / /= /= ], "+ + += += - - -= -= * * *= *= / / /= /=");
     p!([ % % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>= ],
         "% % %= %= ^ ^ ^= ^= << << <<= <<= >> >> >>= >>=");
-
-    // For these one we must insert spaces between adjacent tokens, again due
-    // to proc macros.
-    p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ? = | > >> @ - -> <- - $$== == =>"); // FIXME
-    p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ", ; ;, * * @ @ $+ $> < < > ? ? += ="); // FIXME
-    p!([ :#!@|$=&*,+;*~? ], ": #! @ | $= & *, + ; * ~ ?"); // FIXME
+    p!([ +! ?= |> >>@ --> <-- $$ =====> ], "+! ?= |> >>@ --> <-- $$=====>");
+    p!([ ,; ;, ** @@ $+$ >< <> ?? +== ], ",; ;, ** @@ $+$>< <> ?? +=="); // FIXME: `$ >` -> `$>`
+    p!([ :#!@|$=&*,+;*~? ], ":#!@|$=&*,+;*~?");
 }
diff --git a/tests/ui/macros/syntax-extension-source-utils.rs b/tests/ui/macros/syntax-extension-source-utils.rs
index f41faddddf6..aa894c83910 100644
--- a/tests/ui/macros/syntax-extension-source-utils.rs
+++ b/tests/ui/macros/syntax-extension-source-utils.rs
@@ -17,7 +17,7 @@ pub fn main() {
     assert_eq!(column!(), 16);
     assert_eq!(indirect_line!(), 18);
     assert!((file!().ends_with("syntax-extension-source-utils.rs")));
-    assert_eq!(stringify!((2*3) + 5).to_string(), "(2 * 3) + 5".to_string());
+    assert_eq!(stringify!((2*3) + 5).to_string(), "(2*3) + 5".to_string());
     assert!(include!("syntax-extension-source-utils-files/includeme.\
                       fragment").to_string()
            == "victory robot 6".to_string());
@@ -32,5 +32,5 @@ pub fn main() {
     // The Windows tests are wrapped in an extra module for some reason
     assert!((m1::m2::where_am_i().ends_with("m1::m2")));
 
-    assert_eq!((35, "(2 * 3) + 5"), (line!(), stringify!((2*3) + 5)));
+    assert_eq!((35, "(2*3) + 5"), (line!(), stringify!((2*3) + 5)));
 }
diff --git a/tests/ui/macros/trace-macro.stderr b/tests/ui/macros/trace-macro.stderr
index 43272248c28..dac4cc12f84 100644
--- a/tests/ui/macros/trace-macro.stderr
+++ b/tests/ui/macros/trace-macro.stderr
@@ -5,5 +5,5 @@ LL |     println!("Hello, World!");
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `println! { "Hello, World!" }`
-   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")) ; }`
+   = note: to `{ $crate :: io :: _print($crate :: format_args_nl! ("Hello, World!")); }`
 
diff --git a/tests/ui/macros/trace_faulty_macros.stderr b/tests/ui/macros/trace_faulty_macros.stderr
index 6a89d3bfd09..81047c7a21a 100644
--- a/tests/ui/macros/trace_faulty_macros.stderr
+++ b/tests/ui/macros/trace_faulty_macros.stderr
@@ -20,7 +20,7 @@ LL |     my_faulty_macro!();
    |     ^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `my_faulty_macro! {  }`
-   = note: to `my_faulty_macro! (bcd) ;`
+   = note: to `my_faulty_macro! (bcd);`
    = note: expanding `my_faulty_macro! { bcd }`
 
 error: recursion limit reached while expanding `my_recursive_macro!`
@@ -42,13 +42,13 @@ LL |     my_recursive_macro!();
    |     ^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expanding `my_recursive_macro! {  }`
-   = note: to `my_recursive_macro! () ;`
+   = note: to `my_recursive_macro! ();`
    = note: expanding `my_recursive_macro! {  }`
-   = note: to `my_recursive_macro! () ;`
+   = note: to `my_recursive_macro! ();`
    = note: expanding `my_recursive_macro! {  }`
-   = note: to `my_recursive_macro! () ;`
+   = note: to `my_recursive_macro! ();`
    = note: expanding `my_recursive_macro! {  }`
-   = note: to `my_recursive_macro! () ;`
+   = note: to `my_recursive_macro! ();`
 
 error: expected expression, found pattern `A { a: a, b: 0, c: _, .. }`
   --> $DIR/trace_faulty_macros.rs:16:9
@@ -98,7 +98,7 @@ LL |     let a = pat_macro!();
    |             ^^^^^^^^^^^^
    |
    = note: expanding `pat_macro! {  }`
-   = note: to `pat_macro! (A { a : a, b : 0, c : _, .. }) ;`
+   = note: to `pat_macro! (A { a : a, b : 0, c : _, .. });`
    = note: expanding `pat_macro! { A { a : a, b : 0, c : _, .. } }`
    = note: to `A { a: a, b: 0, c: _, .. }`
 
@@ -108,7 +108,7 @@ note: trace_macro
 LL |     test!(let x = 1+1);
    |     ^^^^^^^^^^^^^^^^^^
    |
-   = note: expanding `test! { let x = 1 + 1 }`
+   = note: expanding `test! { let x = 1+1 }`
    = note: to `test! ((x, 1 + 1))`
    = note: expanding `test! { (x, 1 + 1) }`
    = note: to `let x = 1 + 1 ;`
diff --git a/tests/ui/mir/mir_raw_fat_ptr.rs b/tests/ui/mir/mir_raw_fat_ptr.rs
index 6aceefbe715..f4a9afd2308 100644
--- a/tests/ui/mir/mir_raw_fat_ptr.rs
+++ b/tests/ui/mir/mir_raw_fat_ptr.rs
@@ -1,7 +1,9 @@
 // run-pass
 // check raw fat pointer ops in mir
 // FIXME: please improve this when we get monomorphization support
+
 #![feature(raw_ref_op)]
+#![allow(ambiguous_wide_pointer_comparisons)]
 
 use std::mem;
 
diff --git a/tests/ui/moves/move-out-of-field.rs b/tests/ui/moves/move-out-of-field.rs
index 9f697db4f79..4166d8dc8e9 100644
--- a/tests/ui/moves/move-out-of-field.rs
+++ b/tests/ui/moves/move-out-of-field.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-use std::string::String;
-
 struct StringBuffer {
     s: String,
 }
diff --git a/tests/ui/overloaded/overloaded-calls-param-vtables.rs b/tests/ui/overloaded/overloaded-calls-param-vtables.rs
index fde1ad20f7d..74ee1c17614 100644
--- a/tests/ui/overloaded/overloaded-calls-param-vtables.rs
+++ b/tests/ui/overloaded/overloaded-calls-param-vtables.rs
@@ -6,7 +6,6 @@
 #![feature(unboxed_closures, fn_traits)]
 
 use std::marker::PhantomData;
-use std::ops::Fn;
 use std::ops::Add;
 
 struct G<A>(PhantomData<A>);
diff --git a/tests/ui/overloaded/overloaded-calls-simple.rs b/tests/ui/overloaded/overloaded-calls-simple.rs
index 41318360799..8fed18b8e29 100644
--- a/tests/ui/overloaded/overloaded-calls-simple.rs
+++ b/tests/ui/overloaded/overloaded-calls-simple.rs
@@ -2,8 +2,6 @@
 
 #![feature(lang_items, unboxed_closures, fn_traits)]
 
-use std::ops::{Fn, FnMut, FnOnce};
-
 struct S1 {
     x: i32,
     y: i32,
diff --git a/tests/ui/overloaded/overloaded-calls-zero-args.rs b/tests/ui/overloaded/overloaded-calls-zero-args.rs
index 69ca88619b8..b1237306790 100644
--- a/tests/ui/overloaded/overloaded-calls-zero-args.rs
+++ b/tests/ui/overloaded/overloaded-calls-zero-args.rs
@@ -2,8 +2,6 @@
 
 #![feature(unboxed_closures, fn_traits)]
 
-use std::ops::FnMut;
-
 struct S {
     x: i32,
     y: i32,
diff --git a/tests/ui/overloaded/overloaded-deref-count.rs b/tests/ui/overloaded/overloaded-deref-count.rs
index e2f1e10b5c8..d2482b12500 100644
--- a/tests/ui/overloaded/overloaded-deref-count.rs
+++ b/tests/ui/overloaded/overloaded-deref-count.rs
@@ -2,7 +2,6 @@
 
 use std::cell::Cell;
 use std::ops::{Deref, DerefMut};
-use std::vec::Vec;
 
 struct DerefCounter<T> {
     count_imm: Cell<usize>,
diff --git a/tests/ui/overloaded/overloaded-deref.rs b/tests/ui/overloaded/overloaded-deref.rs
index 73d8232a322..b08d8f3f767 100644
--- a/tests/ui/overloaded/overloaded-deref.rs
+++ b/tests/ui/overloaded/overloaded-deref.rs
@@ -1,7 +1,6 @@
 // run-pass
 use std::cell::RefCell;
 use std::rc::Rc;
-use std::string::String;
 
 #[derive(PartialEq, Debug)]
 struct Point {
diff --git a/tests/ui/parser/match-arm-without-body.rs b/tests/ui/parser/match-arm-without-body.rs
index c3487c2c658..4723abff8b6 100644
--- a/tests/ui/parser/match-arm-without-body.rs
+++ b/tests/ui/parser/match-arm-without-body.rs
@@ -66,8 +66,6 @@ fn main() {
         pat!()
         //~^ ERROR expected `,` following `match` arm
         //~| HELP missing a comma here
-        //~| ERROR `match` arm with no body
-        //~| HELP add a body after the pattern
         _ => {}
     }
     match Some(false) {
diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr
index 3a06ed050b5..d98c7ec2826 100644
--- a/tests/ui/parser/match-arm-without-body.stderr
+++ b/tests/ui/parser/match-arm-without-body.stderr
@@ -68,19 +68,19 @@ error: `match` arm with no body
   --> $DIR/match-arm-without-body.rs:30:9
    |
 LL |         Some(_) if true
-   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
 
 error: `match` arm with no body
   --> $DIR/match-arm-without-body.rs:40:9
    |
 LL |         Some(_) if true,
-   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
 
 error: `match` arm with no body
   --> $DIR/match-arm-without-body.rs:45:9
    |
 LL |         Some(_) if true,
-   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
 
 error: `match` arm with no body
   --> $DIR/match-arm-without-body.rs:51:9
@@ -98,19 +98,13 @@ error: `match` arm with no body
   --> $DIR/match-arm-without-body.rs:61:9
    |
 LL |         pat!() if true,
-   |         ^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
-
-error: `match` arm with no body
-  --> $DIR/match-arm-without-body.rs:66:9
-   |
-LL |         pat!()
    |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
 
 error: `match` arm with no body
-  --> $DIR/match-arm-without-body.rs:74:9
+  --> $DIR/match-arm-without-body.rs:72:9
    |
 LL |         pat!(),
    |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
 
-error: aborting due to 14 previous errors
+error: aborting due to 13 previous errors
 
diff --git a/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout
index 4f8730053ee..8459f4e6305 100644
--- a/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout
+++ b/tests/ui/proc-macro/allowed-attr-stmt-expr.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi ;
+PRINT-ATTR INPUT (DISPLAY): struct ItemWithSemi;
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct ItemWithSemi ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -45,7 +46,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:53:27: 53:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!";
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_let] let string = "Hello, world!" ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -87,7 +89,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:57:33: 57:34 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro!("{}", string);
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -140,7 +143,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:61:28: 61:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt!(#[allow(dead_code)] struct Bar {});
+PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "second_make_stmt",
@@ -288,7 +292,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/allowed-attr-stmt-expr.rs:68:18: 68:20 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct ;
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] struct NonBracedStruct;
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[rustc_dummy] struct NonBracedStruct ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
diff --git a/tests/ui/proc-macro/attr-complex-fn.stdout b/tests/ui/proc-macro/attr-complex-fn.stdout
index b12eb587fc7..7c23d1ecae4 100644
--- a/tests/ui/proc-macro/attr-complex-fn.stdout
+++ b/tests/ui/proc-macro/attr-complex-fn.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >> > () {}
+PRINT-ATTR INPUT (DISPLAY): fn foo<T: MyTrait<MyStruct<{ true }>>>() {}
+PRINT-ATTR RE-COLLECTED (DISPLAY): fn foo < T : MyTrait < MyStruct < { true } >>> () {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
@@ -76,7 +77,9 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-complex-fn.rs:19:42: 19:44 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #! [rustc_dummy] }
+PRINT-ATTR INPUT (DISPLAY): impl<T> MyTrait<T> for MyStruct<{ true }> { #![rustc_dummy] }
+PRINT-ATTR RE-COLLECTED (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #![rustc_dummy] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): impl < T > MyTrait < T > for MyStruct < { true } > { #! [rustc_dummy] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "impl",
diff --git a/tests/ui/proc-macro/attr-stmt-expr.stdout b/tests/ui/proc-macro/attr-stmt-expr.stdout
index c6d77e0ed0c..5e09198bbd4 100644
--- a/tests/ui/proc-macro/attr-stmt-expr.stdout
+++ b/tests/ui/proc-macro/attr-stmt-expr.stdout
@@ -29,7 +29,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:45:27: 45:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!" ;
+PRINT-ATTR INPUT (DISPLAY): #[expect_let] let string = "Hello, world!";
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_let] let string = "Hello, world!" ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -71,7 +72,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:49:33: 49:34 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
+PRINT-ATTR INPUT (DISPLAY): #[expect_my_macro_stmt] my_macro!("{}", string);
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[expect_my_macro_stmt] my_macro! ("{}", string) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -124,7 +126,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/attr-stmt-expr.rs:53:28: 53:29 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
+PRINT-ATTR INPUT (DISPLAY): second_make_stmt!(#[allow(dead_code)] struct Bar {});
+PRINT-ATTR RE-COLLECTED (DISPLAY): second_make_stmt! (#[allow(dead_code)] struct Bar {}) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "second_make_stmt",
diff --git a/tests/ui/proc-macro/attribute-after-derive.stdout b/tests/ui/proc-macro/attribute-after-derive.stdout
index 1b17d60476a..6d9531df8ca 100644
--- a/tests/ui/proc-macro/attribute-after-derive.stdout
+++ b/tests/ui/proc-macro/attribute-after-derive.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field: u8, }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[derive(Print)] struct AttributeDerive { #[cfg(FALSE)] field : u8, }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
@@ -130,7 +131,8 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: $DIR/attribute-after-derive.rs:23:24: 26:2 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, }
+PRINT-ATTR INPUT (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field: u8, }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct DeriveAttribute { #[cfg(FALSE)] field : u8, }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/tests/ui/proc-macro/attribute-spans-preserved.stdout b/tests/ui/proc-macro/attribute-spans-preserved.stdout
index cf9a97491f0..190098d0211 100644
--- a/tests/ui/proc-macro/attribute-spans-preserved.stdout
+++ b/tests/ui/proc-macro/attribute-spans-preserved.stdout
@@ -1 +1 @@
-fn main() { let y : u32 = "z" ; { let x : u32 = "y" ; } }
+fn main() { let y : u32 = "z" ; { let x: u32 = "y"; } }
diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
index 5b386b46bb7..76346d9a172 100644
--- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
+++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr-rpass.rs
@@ -10,14 +10,14 @@ use proc_macro::TokenStream;
 #[proc_macro_attribute]
 pub fn expect_let(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "let string = \"Hello, world!\" ;");
+    assert_eq!(item.to_string(), "let string = \"Hello, world!\";");
     item
 }
 
 #[proc_macro_attribute]
 pub fn expect_print_stmt(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "println! (\"{}\", string) ;");
+    assert_eq!(item.to_string(), "println!(\"{}\", string);");
     item
 }
 
@@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
 #[proc_macro_attribute]
 pub fn expect_print_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "println! (\"{}\", string)");
+    assert_eq!(item.to_string(), "println!(\"{}\", string)");
     item
 }
 
@@ -40,7 +40,6 @@ pub fn no_output(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
     assert!(!item.to_string().is_empty());
     "".parse().unwrap()
-
 }
 
 #[proc_macro_attribute]
diff --git a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs
index 4d6dc06b4a4..7a29894bbcf 100644
--- a/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs
+++ b/tests/ui/proc-macro/auxiliary/attr-stmt-expr.rs
@@ -31,7 +31,7 @@ pub fn expect_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
 #[proc_macro_attribute]
 pub fn expect_my_macro_expr(attr: TokenStream, item: TokenStream) -> TokenStream {
     assert!(attr.to_string().is_empty());
-    assert_eq!(item.to_string(), "my_macro! (\"{}\", string)");
+    assert_eq!(item.to_string(), "my_macro!(\"{}\", string)");
     item
 }
 
diff --git a/tests/ui/proc-macro/auxiliary/derive-a.rs b/tests/ui/proc-macro/auxiliary/derive-a.rs
index 79a3864bf99..cd2be5fd84d 100644
--- a/tests/ui/proc-macro/auxiliary/derive-a.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-a.rs
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(A)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert!(input.contains("struct A ;"));
+    assert!(input.contains("struct A;"));
     "".parse().unwrap()
 }
diff --git a/tests/ui/proc-macro/auxiliary/derive-atob.rs b/tests/ui/proc-macro/auxiliary/derive-atob.rs
index 207b7fd3203..e78e5bb8f4c 100644
--- a/tests/ui/proc-macro/auxiliary/derive-atob.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-atob.rs
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(AToB)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert_eq!(input, "struct A ;");
+    assert_eq!(input, "struct A;");
     "struct B;".parse().unwrap()
 }
diff --git a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs
index 641a95f78c1..3e6af67a9f4 100644
--- a/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-b-rpass.rs
@@ -10,7 +10,7 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(B, attributes(B, C))]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert!(input.contains("#[B [arbitrary tokens]]"));
+    assert!(input.contains("#[B[arbitrary tokens]]"));
     assert!(input.contains("struct B {"));
     assert!(input.contains("#[C]"));
     "".parse().unwrap()
diff --git a/tests/ui/proc-macro/auxiliary/derive-ctod.rs b/tests/ui/proc-macro/auxiliary/derive-ctod.rs
index 2efe5a91340..dbf44ed1b05 100644
--- a/tests/ui/proc-macro/auxiliary/derive-ctod.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-ctod.rs
@@ -10,6 +10,6 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(CToD)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert_eq!(input, "struct C ;");
+    assert_eq!(input, "struct C;");
     "struct D;".parse().unwrap()
 }
diff --git a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs
index 7598d632cb6..ce7a50d2381 100644
--- a/tests/ui/proc-macro/auxiliary/derive-same-struct.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-same-struct.rs
@@ -10,12 +10,12 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(AToB)]
 pub fn derive1(input: TokenStream) -> TokenStream {
     println!("input1: {:?}", input.to_string());
-    assert_eq!(input.to_string(), "struct A ;");
+    assert_eq!(input.to_string(), "struct A;");
     "#[derive(BToC)] struct B;".parse().unwrap()
 }
 
 #[proc_macro_derive(BToC)]
 pub fn derive2(input: TokenStream) -> TokenStream {
-    assert_eq!(input.to_string(), "struct B ;");
+    assert_eq!(input.to_string(), "struct B;");
     "struct C;".parse().unwrap()
 }
diff --git a/tests/ui/proc-macro/auxiliary/derive-union.rs b/tests/ui/proc-macro/auxiliary/derive-union.rs
index 05883170c6c..d950e1e773c 100644
--- a/tests/ui/proc-macro/auxiliary/derive-union.rs
+++ b/tests/ui/proc-macro/auxiliary/derive-union.rs
@@ -12,7 +12,7 @@ pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
     assert!(input.contains("#[repr(C)]"));
     assert!(input.contains("union Test {"));
-    assert!(input.contains("a : u8,"));
+    assert!(input.contains("a: u8,"));
     assert!(input.contains("}"));
     "".parse().unwrap()
 }
diff --git a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs
index d779d57af14..5155a4b8558 100644
--- a/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs
+++ b/tests/ui/proc-macro/auxiliary/expand-with-a-macro.rs
@@ -11,7 +11,7 @@ use proc_macro::TokenStream;
 #[proc_macro_derive(A)]
 pub fn derive(input: TokenStream) -> TokenStream {
     let input = input.to_string();
-    assert!(input.contains("struct A ;"));
+    assert!(input.contains("struct A;"));
     r#"
         impl A {
             fn a(&self) {
diff --git a/tests/ui/proc-macro/auxiliary/issue-79825.rs b/tests/ui/proc-macro/auxiliary/issue-79825.rs
index 930891b1d43..69cf5904f90 100644
--- a/tests/ui/proc-macro/auxiliary/issue-79825.rs
+++ b/tests/ui/proc-macro/auxiliary/issue-79825.rs
@@ -8,7 +8,7 @@ use proc_macro::TokenStream;
 
 #[proc_macro_attribute]
 pub fn assert_input(args: TokenStream, input: TokenStream) -> TokenStream {
-    assert_eq!(input.to_string(), "trait Alias = Sized ;");
+    assert_eq!(input.to_string(), "trait Alias = Sized;");
     assert!(args.is_empty());
     TokenStream::new()
 }
diff --git a/tests/ui/proc-macro/capture-macro-rules-invoke.stdout b/tests/ui/proc-macro/capture-macro-rules-invoke.stdout
index 01d71ff989b..71e34119ba7 100644
--- a/tests/ui/proc-macro/capture-macro-rules-invoke.stdout
+++ b/tests/ui/proc-macro/capture-macro-rules-invoke.stdout
@@ -14,6 +14,8 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
 PRINT-BANG INPUT (DISPLAY): 1 + 1, { "a" }, let a = 1;, String, my_name, 'a, my_val = 30,
 std::option::Option, pub(in some::path) , [a b c], -30
 PRINT-BANG RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
+std::option::Option, pub(in some::path), [a b c], -30
+PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): 1 + 1, { "a" }, let a = 1, String, my_name, 'a, my_val = 30,
 std :: option :: Option, pub(in some :: path), [a b c], - 30
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Group {
diff --git a/tests/ui/proc-macro/capture-unglued-token.stdout b/tests/ui/proc-macro/capture-unglued-token.stdout
index a0d2178f000..84b7ca35524 100644
--- a/tests/ui/proc-macro/capture-unglued-token.stdout
+++ b/tests/ui/proc-macro/capture-unglued-token.stdout
@@ -1,5 +1,5 @@
 PRINT-BANG INPUT (DISPLAY): Vec<u8>
-PRINT-BANG RE-COLLECTED (DISPLAY): Vec < u8 >
+PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): Vec < u8 >
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Group {
         delimiter: None,
diff --git a/tests/ui/proc-macro/cfg-eval-inner.stdout b/tests/ui/proc-macro/cfg-eval-inner.stdout
index 9d25def587c..43ae47c201f 100644
--- a/tests/ui/proc-macro/cfg-eval-inner.stdout
+++ b/tests/ui/proc-macro/cfg-eval-inner.stdout
@@ -1,4 +1,16 @@
-PRINT-ATTR INPUT (DISPLAY): impl Foo <
+PRINT-ATTR INPUT (DISPLAY): impl
+Foo<[u8;
+{
+    #![rustc_dummy(cursed_inner)] #![allow(unused)] struct Inner
+    { field: [u8; { #![rustc_dummy(another_cursed_inner)] 1 }] } 0
+}]> { #![rustc_dummy(evaluated_attr)] fn bar() {} }
+PRINT-ATTR RE-COLLECTED (DISPLAY): impl Foo <
+[u8;
+{
+    #![rustc_dummy(cursed_inner)] #![allow(unused)] struct Inner
+    { field: [u8; { #![rustc_dummy(another_cursed_inner)] 1 }] } 0
+}] > { #![rustc_dummy(evaluated_attr)] fn bar() {} }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): impl Foo <
 [u8 ;
 {
     #! [rustc_dummy(cursed_inner)] #! [allow(unused)] struct Inner
@@ -35,7 +47,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
                 stream: TokenStream [
                     Punct {
                         ch: '#',
-                        spacing: Alone,
+                        spacing: Joint,
                         span: $DIR/cfg-eval-inner.rs:19:5: 19:6 (#0),
                     },
                     Punct {
@@ -130,7 +142,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
                                         stream: TokenStream [
                                             Punct {
                                                 ch: '#',
-                                                spacing: Alone,
+                                                spacing: Joint,
                                                 span: $DIR/cfg-eval-inner.rs:23:13: 23:14 (#0),
                                             },
                                             Punct {
@@ -195,7 +207,7 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         stream: TokenStream [
             Punct {
                 ch: '#',
-                spacing: Alone,
+                spacing: Joint,
                 span: $DIR/cfg-eval-inner.rs:32:5: 32:6 (#0),
             },
             Punct {
diff --git a/tests/ui/proc-macro/cfg-eval.stdout b/tests/ui/proc-macro/cfg-eval.stdout
index 6732caf08dd..e26e16f5a8c 100644
--- a/tests/ui/proc-macro/cfg-eval.stdout
+++ b/tests/ui/proc-macro/cfg-eval.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, }
+PRINT-ATTR INPUT (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true: u8, }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): struct S1 { #[cfg(all())] #[allow()] field_true : u8, }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/tests/ui/proc-macro/custom-attr-only-one-derive.rs b/tests/ui/proc-macro/custom-attr-only-one-derive.rs
index 2cd5b487301..901394384d5 100644
--- a/tests/ui/proc-macro/custom-attr-only-one-derive.rs
+++ b/tests/ui/proc-macro/custom-attr-only-one-derive.rs
@@ -1,8 +1,6 @@
 // run-pass
 // aux-build:custom-attr-only-one-derive.rs
 
-#![feature(rust_2018_preview)]
-
 #[macro_use]
 extern crate custom_attr_only_one_derive;
 
diff --git a/tests/ui/proc-macro/derive-same-struct.stdout b/tests/ui/proc-macro/derive-same-struct.stdout
index 7478d974140..77605de5e33 100644
--- a/tests/ui/proc-macro/derive-same-struct.stdout
+++ b/tests/ui/proc-macro/derive-same-struct.stdout
@@ -1 +1 @@
-input1: "struct A ;"
+input1: "struct A;"
diff --git a/tests/ui/proc-macro/doc-comment-preserved.stdout b/tests/ui/proc-macro/doc-comment-preserved.stdout
index f4160d7da80..b0ea180d9bd 100644
--- a/tests/ui/proc-macro/doc-comment-preserved.stdout
+++ b/tests/ui/proc-macro/doc-comment-preserved.stdout
@@ -5,7 +5,7 @@ PRINT-BANG INPUT (DISPLAY): /**
 * DOC *
 *******
 */
- pub struct S ;
+ pub struct S;
 PRINT-BANG RE-COLLECTED (DISPLAY): #[doc = "\n*******\n* DOC *\n* DOC *\n* DOC *\n*******\n"] pub struct S ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Punct {
diff --git a/tests/ui/proc-macro/dollar-crate-issue-57089.stdout b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout
index de4f0c000b6..7f97ac9dbc2 100644
--- a/tests/ui/proc-macro/dollar-crate-issue-57089.stdout
+++ b/tests/ui/proc-macro/dollar-crate-issue-57089.stdout
@@ -1,4 +1,5 @@
-PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S);
+PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -38,7 +39,8 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/dollar-crate-issue-57089.rs:17:32: 17:33 (#3),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/tests/ui/proc-macro/dollar-crate-issue-62325.stdout b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout
index c7e72bf4ff5..96161049e30 100644
--- a/tests/ui/proc-macro/dollar-crate-issue-62325.stdout
+++ b/tests/ui/proc-macro/dollar-crate-issue-62325.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S)) ;
+PRINT-ATTR INPUT (DISPLAY): struct A(identity! ($crate :: S));
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A(identity! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -53,7 +54,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/dollar-crate-issue-62325.rs:19:35: 19:36 (#3),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S)) ;
+PRINT-ATTR INPUT (DISPLAY): struct B(identity! ($crate :: S));
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct B(identity! ($crate :: S)) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/tests/ui/proc-macro/dollar-crate.stdout b/tests/ui/proc-macro/dollar-crate.stdout
index 0f5f87ceca2..a6bdab00441 100644
--- a/tests/ui/proc-macro/dollar-crate.stdout
+++ b/tests/ui/proc-macro/dollar-crate.stdout
@@ -1,4 +1,5 @@
-PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S);
+PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -38,7 +39,8 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/dollar-crate.rs:20:36: 20:37 (#3),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -78,7 +80,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/dollar-crate.rs:24:32: 24:33 (#3),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
+PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S);
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -118,7 +121,8 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: $DIR/dollar-crate.rs:27:32: 27:33 (#3),
     },
 ]
-PRINT-BANG INPUT (DISPLAY): struct M($crate :: S) ;
+PRINT-BANG INPUT (DISPLAY): struct M($crate :: S);
+PRINT-BANG RE-COLLECTED (DISPLAY): struct M($crate :: S) ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -158,7 +162,8 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
         span: $DIR/auxiliary/dollar-crate-external.rs:7:32: 7:33 (#14),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S) ;
+PRINT-ATTR INPUT (DISPLAY): struct A($crate :: S);
+PRINT-ATTR RE-COLLECTED (DISPLAY): struct A($crate :: S) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
@@ -198,7 +203,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/auxiliary/dollar-crate-external.rs:11:28: 11:29 (#14),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S) ;
+PRINT-DERIVE INPUT (DISPLAY): struct D($crate :: S);
+PRINT-DERIVE RE-COLLECTED (DISPLAY): struct D($crate :: S) ;
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "struct",
diff --git a/tests/ui/proc-macro/expand-to-derive.stdout b/tests/ui/proc-macro/expand-to-derive.stdout
index 39f00918329..9f03a469aeb 100644
--- a/tests/ui/proc-macro/expand-to-derive.stdout
+++ b/tests/ui/proc-macro/expand-to-derive.stdout
@@ -1,6 +1,11 @@
 PRINT-DERIVE INPUT (DISPLAY): struct Foo
 {
     field :
+    [bool ; { #[rustc_dummy] struct Inner { other_inner_field: u8, } 0 }]
+}
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo
+{
+    field :
     [bool ; { #[rustc_dummy] struct Inner { other_inner_field : u8, } 0 }]
 }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
diff --git a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
index 40181efc0b8..eda2f433bce 100644
--- a/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
+++ b/tests/ui/proc-macro/expr-stmt-nonterminal-tokens.stdout
@@ -122,7 +122,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #3 bytes(306..355),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0; }; 0 }, }
 PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
@@ -202,7 +202,8 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #7 bytes(430..483),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { {} }; 0 }, }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { {} } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
         ident: "enum",
@@ -280,7 +281,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #11 bytes(430..483),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH; }; 0 }, }
 PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
@@ -358,7 +359,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #15 bytes(430..483),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { 0 + 1; }; 0 }, }
 PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { 0 + 1 } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
@@ -449,7 +450,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
         span: #19 bytes(430..483),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; } ; 0 }, }
+PRINT-DERIVE INPUT (DISPLAY): enum E { V = { let _ = { PATH + 1; }; 0 }, }
 PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): enum E { V = { let _ = { PATH + 1 } ; 0 }, }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
diff --git a/tests/ui/proc-macro/inert-attribute-order.stdout b/tests/ui/proc-macro/inert-attribute-order.stdout
index cc215545952..86b27217974 100644
--- a/tests/ui/proc-macro/inert-attribute-order.stdout
+++ b/tests/ui/proc-macro/inert-attribute-order.stdout
@@ -1,7 +1,11 @@
 PRINT-ATTR INPUT (DISPLAY): /// 1
-#[rustfmt :: attr2] #[doc = "3"] #[doc = "4"] #[rustfmt :: attr5] /// 6
-#[print_attr(nodebug)] struct S ;
-PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
+#[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5] /// 6
+#[print_attr(nodebug)] struct S;
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5]
+#[doc = " 6"] #[print_attr(nodebug)] struct S ;
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
 #[rustfmt :: attr5] #[doc = " 6"] #[print_attr(nodebug)] struct S ;
-PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
+PRINT-ATTR INPUT (DISPLAY): #[doc = " 1"] #[rustfmt::attr2] #[doc = "3"] #[doc = "4"] #[rustfmt::attr5]
+#[doc = " 6"] struct S ;
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[doc = " 1"] #[rustfmt :: attr2] #[doc = "3"] #[doc = "4"]
 #[rustfmt :: attr5] #[doc = " 6"] struct S ;
diff --git a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
index 6261d82e2d0..aaec40669e6 100644
--- a/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
+++ b/tests/ui/proc-macro/inner-attr-non-inline-mod.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] }
+PRINT-ATTR INPUT (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #![rustfmt::skip] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[deny(unused_attributes)] mod module_with_attrs { #! [rustfmt :: skip] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
diff --git a/tests/ui/proc-macro/inner-attrs.stdout b/tests/ui/proc-macro/inner-attrs.stdout
index ee8adf0b4a9..037ec044e42 100644
--- a/tests/ui/proc-macro/inner-attrs.stdout
+++ b/tests/ui/proc-macro/inner-attrs.stdout
@@ -6,6 +6,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second)] fn foo()
+{ #![print_target_and_args(third)] #![print_target_and_args(fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_target_and_args(second)] fn foo()
 { #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
@@ -121,6 +123,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): fn foo()
+{ #![print_target_and_args(third)] #![print_target_and_args(fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo()
 { #! [print_target_and_args(third)] #! [print_target_and_args(fourth)] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
@@ -210,7 +214,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:20:30: 20:35 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] }
+PRINT-ATTR INPUT (DISPLAY): fn foo() { #![print_target_and_args(fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn foo() { #! [print_target_and_args(fourth)] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
@@ -298,6 +303,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod
+{ #![print_target_and_args(mod_third)] #![print_target_and_args(mod_fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_target_and_args(mod_second)] mod inline_mod
 {
     #! [print_target_and_args(mod_third)] #!
     [print_target_and_args(mod_fourth)]
@@ -411,6 +418,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-ATTR INPUT (DISPLAY): mod inline_mod
+{ #![print_target_and_args(mod_third)] #![print_target_and_args(mod_fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod
 {
     #! [print_target_and_args(mod_third)] #!
     [print_target_and_args(mod_fourth)]
@@ -498,7 +507,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:27:30: 27:39 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] }
+PRINT-ATTR INPUT (DISPLAY): mod inline_mod { #![print_target_and_args(mod_fourth)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): mod inline_mod { #! [print_target_and_args(mod_fourth)] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "mod",
@@ -569,6 +579,8 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
     },
 ]
 PRINT-DERIVE INPUT (DISPLAY): struct MyDerivePrint
+{ field: [u8; { match true { _ => { #![rustc_dummy(third)] true } }; 0 }] }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct MyDerivePrint
 {
     field :
     [u8 ; { match true { _ => { #! [rustc_dummy(third)] true } } ; 0 }]
@@ -639,7 +651,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                         stream: TokenStream [
                                             Punct {
                                                 ch: '#',
-                                                spacing: Alone,
+                                                spacing: Joint,
                                                 span: $DIR/inner-attrs.rs:40:17: 40:18 (#0),
                                             },
                                             Punct {
@@ -705,7 +717,9 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:49:29: 49:40 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 });
+PRINT-ATTR RE-COLLECTED (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Group {
         delimiter: Parenthesis,
@@ -819,7 +833,9 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/inner-attrs.rs:56:29: 56:40 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR INPUT (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 });
+PRINT-ATTR RE-COLLECTED (DISPLAY): (3, 4, { #![cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): (3, 4, { #! [cfg_attr(not(FALSE), rustc_dummy(innermost))] 5 }) ;
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Group {
         delimiter: Parenthesis,
diff --git a/tests/ui/proc-macro/issue-75734-pp-paren.stdout b/tests/ui/proc-macro/issue-75734-pp-paren.stdout
index 2f7c013e958..ee135366fb6 100644
--- a/tests/ui/proc-macro/issue-75734-pp-paren.stdout
+++ b/tests/ui/proc-macro/issue-75734-pp-paren.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): fn main() { & | _ : u8 | {} ; mul_2! (1 + 1) ; }
+PRINT-ATTR INPUT (DISPLAY): fn main() { &|_: u8| {}; mul_2!(1 + 1); }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): fn main() { &| _ : u8 | {} ; mul_2! (1 + 1) ; }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
diff --git a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
index 31a1c44b6df..47f26451d1c 100644
--- a/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
+++ b/tests/ui/proc-macro/issue-75930-derive-cfg.stdout
@@ -1,5 +1,53 @@
 PRINT-ATTR INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
-struct Foo < #[cfg(FALSE)] A, B >
+struct Foo<#[cfg(FALSE)] A, B>
+{
+    #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
+    bool, third:
+    [u8;
+    {
+        #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner;
+        #[cfg(FALSE)] let a = 25; match true
+        {
+            #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+            false => {}, _ => {}
+        }; #[print_helper(should_be_removed)] fn removed_fn()
+        { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+        { #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum
+        {
+            Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
+            #[cfg(FALSE)] String, u8)
+        } struct
+        TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
+        #[cfg(FALSE)] bool, u8); fn plain_removed_fn()
+        { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0
+    }], #[print_helper(d)] fourth: B
+}
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
+struct Foo <#[cfg(FALSE)] A, B >
+{
+    #[cfg(FALSE)] first: String, #[cfg_attr(FALSE, deny(warnings))] second:
+    bool, third:
+    [u8;
+    {
+        #[cfg(FALSE)] struct Bar; #[cfg(not(FALSE))] struct Inner;
+        #[cfg(FALSE)] let a = 25; match true
+        {
+            #[cfg(FALSE)] true => {}, #[cfg_attr(not(FALSE), allow(warnings))]
+            false => {}, _ => {}
+        }; #[print_helper(should_be_removed)] fn removed_fn()
+        { #![cfg(FALSE)] } #[print_helper(c)] #[cfg(not(FALSE))] fn kept_fn()
+        { #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum
+        {
+            Foo(#[cfg(FALSE)] u8, #[cfg(FALSE)] bool, #[cfg(not(FALSE))] i32,
+            #[cfg(FALSE)] String, u8)
+        } struct
+        TupleStruct(#[cfg(FALSE)] String, #[cfg(not(FALSE))] i32,
+        #[cfg(FALSE)] bool, u8); fn plain_removed_fn()
+        { #![cfg_attr(not(FALSE), cfg(FALSE))] } 0
+    }], #[print_helper(d)] fourth: B
+}
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[derive(Print)] #[print_helper(b)]
+struct Foo <#[cfg(FALSE)] A, B >
 {
     #[cfg(FALSE)] first : String, #[cfg_attr(FALSE, deny(warnings))] second :
     bool, third :
@@ -1272,7 +1320,20 @@ PRINT-ATTR INPUT (DEBUG): TokenStream [
         span: $DIR/issue-75930-derive-cfg.rs:55:32: 102:2 (#0),
     },
 ]
-PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo < B >
+PRINT-DERIVE INPUT (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo <B >
+{
+    second: bool, third:
+    [u8;
+    {
+        #[cfg(not(FALSE))] struct Inner; match true
+        { #[allow(warnings)] false => {}, _ => {} }; #[print_helper(c)]
+        #[cfg(not(FALSE))] fn kept_fn()
+        { #![cfg(not(FALSE))] let my_val = true; } enum TupleEnum
+        { Foo(#[cfg(not(FALSE))] i32, u8) } struct
+        TupleStruct(#[cfg(not(FALSE))] i32, u8); 0
+    }], #[print_helper(d)] fourth: B
+}
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): #[print_helper(a)] #[allow(dead_code)] #[print_helper(b)] struct Foo <B >
 {
     second : bool, third :
     [u8 ;
diff --git a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
index ae5e9400809..37ecf3a8df3 100644
--- a/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
+++ b/tests/ui/proc-macro/issue-78675-captured-inner-attrs.stdout
@@ -46,7 +46,7 @@ PRINT-BANG INPUT (DEBUG): TokenStream [
                         stream: TokenStream [
                             Punct {
                                 ch: '#',
-                                spacing: Alone,
+                                spacing: Joint,
                                 span: $DIR/issue-78675-captured-inner-attrs.rs:28:9: 28:16 (#0),
                             },
                             Punct {
diff --git a/tests/ui/proc-macro/keep-expr-tokens.stdout b/tests/ui/proc-macro/keep-expr-tokens.stdout
index fcd72a0e017..8e4d4785e2e 100644
--- a/tests/ui/proc-macro/keep-expr-tokens.stdout
+++ b/tests/ui/proc-macro/keep-expr-tokens.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 + 1 ; }
+PRINT-ATTR INPUT (DISPLAY): #[rustc_dummy] { 1 +1; }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[rustc_dummy] { 1 + 1 ; }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Punct {
         ch: '#',
diff --git a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
index aee0f966d0f..89817a1efdc 100644
--- a/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
+++ b/tests/ui/proc-macro/macro-rules-derive-cfg.stdout
@@ -4,6 +4,15 @@ PRINT-DERIVE INPUT (DISPLAY): struct Foo
     [bool ;
     {
         let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
+        { #![allow(unused)] 30 }; 0
+    }]
+}
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo
+{
+    val :
+    [bool ;
+    {
+        let a = #[rustc_dummy(first)] #[rustc_dummy(second)]
         { #! [allow(unused)] 30 } ; 0
     }]
 }
@@ -111,7 +120,7 @@ PRINT-DERIVE INPUT (DEBUG): TokenStream [
                                 stream: TokenStream [
                                     Punct {
                                         ch: '#',
-                                        spacing: Alone,
+                                        spacing: Joint,
                                         span: $DIR/macro-rules-derive-cfg.rs:27:5: 27:6 (#0),
                                     },
                                     Punct {
diff --git a/tests/ui/proc-macro/meta-macro-hygiene.stdout b/tests/ui/proc-macro/meta-macro-hygiene.stdout
index eeb7179e6fd..6d10cc604c2 100644
--- a/tests/ui/proc-macro/meta-macro-hygiene.stdout
+++ b/tests/ui/proc-macro/meta-macro-hygiene.stdout
@@ -32,13 +32,13 @@ macro_rules! produce_it
     */ {
     () =>
     {
-        meta_macro :: print_def_site! ($crate :: dummy! ()) ;
+        meta_macro::print_def_site!($crate::dummy!());
         // `print_def_site!` will respan the `$crate` identifier
         // with `Span::def_site()`. This should cause it to resolve
         // relative to `meta_macro`, *not* `make_macro` (despite
         // the fact that `print_def_site` is produced by a
         // `macro_rules!` macro in `make_macro`).
-    } ;
+    };
 }
 
 fn main /* 0#0 */() { ; }
diff --git a/tests/ui/proc-macro/nested-derive-cfg.stdout b/tests/ui/proc-macro/nested-derive-cfg.stdout
index 9a562c971c8..c94808c3c0f 100644
--- a/tests/ui/proc-macro/nested-derive-cfg.stdout
+++ b/tests/ui/proc-macro/nested-derive-cfg.stdout
@@ -1,4 +1,6 @@
 PRINT-DERIVE INPUT (DISPLAY): struct Foo
+{ my_array: [bool; { struct Inner { non_removed_inner_field: usize } 0 }] }
+PRINT-DERIVE DEEP-RE-COLLECTED (DISPLAY): struct Foo
 { my_array : [bool ; { struct Inner { non_removed_inner_field : usize } 0 }] }
 PRINT-DERIVE INPUT (DEBUG): TokenStream [
     Ident {
diff --git a/tests/ui/proc-macro/nonterminal-expansion.stdout b/tests/ui/proc-macro/nonterminal-expansion.stdout
index b2557af18ca..c671f623925 100644
--- a/tests/ui/proc-macro/nonterminal-expansion.stdout
+++ b/tests/ui/proc-macro/nonterminal-expansion.stdout
@@ -1,5 +1,5 @@
 PRINT-ATTR_ARGS INPUT (DISPLAY): a, line!(), b
-PRINT-ATTR_ARGS RE-COLLECTED (DISPLAY): a, line! (), b
+PRINT-ATTR_ARGS DEEP-RE-COLLECTED (DISPLAY): a, line! (), b
 PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
     Ident {
         ident: "a",
diff --git a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
index c437853ac72..5c70e780f74 100644
--- a/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
+++ b/tests/ui/proc-macro/nonterminal-token-hygiene.stdout
@@ -1,5 +1,5 @@
 PRINT-BANG INPUT (DISPLAY): struct S;
-PRINT-BANG RE-COLLECTED (DISPLAY): struct S ;
+PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): struct S ;
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Group {
         delimiter: None,
@@ -51,11 +51,11 @@ macro_rules! outer
     /*
     0#0
     */ {
-    ($item : item) =>
+    ($item:item) =>
     {
-        macro inner() { print_bang! { $item } } inner! () ;
+        macro inner() { print_bang! { $item } } inner!();
 
-    } ;
+    };
 }
 
 struct S /* 0#0 */;
diff --git a/tests/ui/proc-macro/pretty-print-tts.stdout b/tests/ui/proc-macro/pretty-print-tts.stdout
index f52e97a8604..fbe8640a01a 100644
--- a/tests/ui/proc-macro/pretty-print-tts.stdout
+++ b/tests/ui/proc-macro/pretty-print-tts.stdout
@@ -1,4 +1,5 @@
-PRINT-BANG INPUT (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; }
+PRINT-BANG INPUT (DISPLAY): { #![rustc_dummy] let a = "hello".len(); matches!(a, 5); }
+PRINT-BANG DEEP-RE-COLLECTED (DISPLAY): { #! [rustc_dummy] let a = "hello".len() ; matches! (a, 5) ; }
 PRINT-BANG INPUT (DEBUG): TokenStream [
     Group {
         delimiter: Brace,
diff --git a/tests/ui/proc-macro/trailing-plus.stdout b/tests/ui/proc-macro/trailing-plus.stdout
index b90057cd6d5..b20401190d8 100644
--- a/tests/ui/proc-macro/trailing-plus.stdout
+++ b/tests/ui/proc-macro/trailing-plus.stdout
@@ -1,4 +1,5 @@
-PRINT-ATTR INPUT (DISPLAY): fn foo < T > () where T : Copy + {}
+PRINT-ATTR INPUT (DISPLAY): fn foo<T>() where T: Copy + {}
+PRINT-ATTR RE-COLLECTED (DISPLAY): fn foo < T > () where T : Copy + {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "fn",
diff --git a/tests/ui/proc-macro/weird-braces.stdout b/tests/ui/proc-macro/weird-braces.stdout
index 9bf56221734..7da769ef0d2 100644
--- a/tests/ui/proc-macro/weird-braces.stdout
+++ b/tests/ui/proc-macro/weird-braces.stdout
@@ -5,7 +5,18 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/weird-braces.rs:16:25: 16:36 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo <
+PRINT-ATTR INPUT (DISPLAY): #[print_target_and_args(second_outer)] impl Bar<{ 1 > 0 }> for Foo<{ true }>
+{
+    #![print_target_and_args(first_inner)]
+    #![print_target_and_args(second_inner)]
+}
+PRINT-ATTR RE-COLLECTED (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo <
+{ true } >
+{
+    #![print_target_and_args(first_inner)]
+    #![print_target_and_args(second_inner)]
+}
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): #[print_target_and_args(second_outer)] impl Bar < { 1 > 0 } > for Foo <
 { true } >
 {
     #! [print_target_and_args(first_inner)] #!
@@ -180,7 +191,17 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/weird-braces.rs:17:25: 17:37 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+PRINT-ATTR INPUT (DISPLAY): impl Bar<{ 1 > 0 }> for Foo<{ true }>
+{
+    #![print_target_and_args(first_inner)]
+    #![print_target_and_args(second_inner)]
+}
+PRINT-ATTR RE-COLLECTED (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+{
+    #![print_target_and_args(first_inner)]
+    #![print_target_and_args(second_inner)]
+}
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
 {
     #! [print_target_and_args(first_inner)] #!
     [print_target_and_args(second_inner)]
@@ -329,7 +350,11 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/weird-braces.rs:19:30: 19:41 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+PRINT-ATTR INPUT (DISPLAY): impl Bar<{ 1 > 0 }> for Foo<{ true }>
+{ #![print_target_and_args(second_inner)] }
+PRINT-ATTR RE-COLLECTED (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
+{ #![print_target_and_args(second_inner)] }
+PRINT-ATTR DEEP-RE-COLLECTED (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } >
 { #! [print_target_and_args(second_inner)] }
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
@@ -445,7 +470,8 @@ PRINT-ATTR_ARGS INPUT (DEBUG): TokenStream [
         span: $DIR/weird-braces.rs:20:30: 20:42 (#0),
     },
 ]
-PRINT-ATTR INPUT (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {}
+PRINT-ATTR INPUT (DISPLAY): impl Bar<{ 1 > 0 }> for Foo<{ true }> {}
+PRINT-ATTR RE-COLLECTED (DISPLAY): impl Bar < { 1 > 0 } > for Foo < { true } > {}
 PRINT-ATTR INPUT (DEBUG): TokenStream [
     Ident {
         ident: "impl",
diff --git a/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs b/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs
index b6a89e29ecc..2c455fc3563 100644
--- a/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs
+++ b/tests/ui/regions/regions-lifetime-static-items-enclosing-scopes.rs
@@ -3,9 +3,6 @@
 // This test verifies that temporary lifetime is correctly computed
 // for static objects in enclosing scopes.
 
-
-use std::cmp::PartialEq;
-
 fn f<T:PartialEq+std::fmt::Debug>(o: &mut Option<T>) {
     assert_eq!(*o, None);
 }
diff --git a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
index a20a6062c13..1a26f34a52d 100644
--- a/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
+++ b/tests/ui/rfcs/rfc-2361-dbg-macro/dbg-macro-expected-behavior.run.stderr
@@ -12,7 +12,7 @@
 [$DIR/dbg-macro-expected-behavior.rs:42] &a = NoCopy(
     1337,
 )
-[$DIR/dbg-macro-expected-behavior.rs:42] dbg!(& a) = NoCopy(
+[$DIR/dbg-macro-expected-behavior.rs:42] dbg!(&a) = NoCopy(
     1337,
 )
 [$DIR/dbg-macro-expected-behavior.rs:47] f(&42) = 42
diff --git a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
index 82c4120b4c7..67de50a1d92 100644
--- a/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
+++ b/tests/ui/rfcs/rfc-2565-param-attrs/auxiliary/param-attrs.rs
@@ -17,27 +17,26 @@ macro_rules! checker {
     }
 }
 
-checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1 : i32, #[a2] ...) ; }"#);
-checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1 : i32, #[a1] mut args : ...) {}"#);
-checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...) ;");
-checker!(attr_free, "fn free(#[a1] arg1 : u8) { let lam = | #[a2] W(x), #[a3] y | () ; }");
-checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1 : u8) {}");
-checker!(attr_inherent_2, "fn inherent2(#[a1] & self, #[a2] arg1 : u8) {}");
-checker!(attr_inherent_3, "fn inherent3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) {}");
-checker!(attr_inherent_4, "fn inherent4 < 'a > (#[a1] self : Box < Self >, #[a2] arg1 : u8) {}");
-checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) {}");
-checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1 : u8) ;");
-checker!(attr_trait_2, "fn trait2(#[a1] & self, #[a2] arg1 : u8) ;");
-checker!(attr_trait_3, "fn trait3 < 'a > (#[a1] & 'a mut self, #[a2] arg1 : u8) ;");
-checker!(attr_trait_4, r#"fn trait4 < 'a >
-(#[a1] self : Box < Self >, #[a2] arg1 : u8, #[a3] Vec < u8 >) ;"#);
-checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1 : u8, #[a3] arg2 : u8) ;");
+checker!(attr_extern, r#"extern "C" { fn ffi(#[a1] arg1: i32, #[a2] ...); }"#);
+checker!(attr_extern_cvar, r#"unsafe extern "C" fn cvar(arg1: i32, #[a1] mut args: ...) {}"#);
+checker!(attr_alias, "type Alias = fn(#[a1] u8, #[a2] ...);");
+checker!(attr_free, "fn free(#[a1] arg1: u8) { let lam = |#[a2] W(x), #[a3] y| (); }");
+checker!(attr_inherent_1, "fn inherent1(#[a1] self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_2, "fn inherent2(#[a1] &self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_3, "fn inherent3<'a>(#[a1] &'a mut self, #[a2] arg1: u8) {}");
+checker!(attr_inherent_4, "fn inherent4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8) {}");
+checker!(attr_inherent_issue_64682, "fn inherent5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8) {}");
+checker!(attr_trait_1, "fn trait1(#[a1] self, #[a2] arg1: u8);");
+checker!(attr_trait_2, "fn trait2(#[a1] &self, #[a2] arg1: u8);");
+checker!(attr_trait_3, "fn trait3<'a>(#[a1] &'a mut self, #[a2] arg1: u8);");
+checker!(attr_trait_4, r#"fn trait4<'a>(#[a1] self: Box<Self>, #[a2] arg1: u8, #[a3] Vec<u8>);"#);
+checker!(attr_trait_issue_64682, "fn trait5(#[a1] #[a2] arg1: u8, #[a3] arg2: u8);");
 checker!(rename_params, r#"impl Foo
 {
-    fn hello(#[angery(true)] a : i32, #[a2] b : i32, #[what = "how"] c : u32)
+    fn hello(#[angery(true)] a: i32, #[a2] b: i32, #[what = "how"] c: u32) {}
+    fn
+    hello2(#[a1] #[a2] a: i32, #[what = "how"] b: i32, #[angery(true)] c: u32)
     {} fn
-    hello2(#[a1] #[a2] a : i32, #[what = "how"] b : i32, #[angery(true)] c :
-    u32) {} fn
-    hello_self(#[a1] #[a2] & self, #[a1] #[a2] a : i32, #[what = "how"] b :
-    i32, #[angery(true)] c : u32) {}
+    hello_self(#[a1] #[a2] &self, #[a1] #[a2] a: i32, #[what = "how"] b: i32,
+    #[angery(true)] c: u32) {}
 }"#);
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
index 8d809907a53..93d520f29ef 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-const-trait-method-fail.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `u32: ~const Plus` is not satisfied
   --> $DIR/call-const-trait-method-fail.rs:25:5
    |
 LL |     a.plus(b)
-   |     ^ the trait `Plus` is not implemented for `u32`
+   |     ^ the trait `~const Plus` is not implemented for `u32`
    |
    = help: the trait `Plus` is implemented for `u32`
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
index 5120e6bfb41..50c46579086 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.rs
@@ -1,4 +1,4 @@
-// known-bug: #110395
+// check-pass
 #![feature(const_trait_impl)]
 
 #[const_trait]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr
deleted file mode 100644
index 4007fd455f8..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-in-impl.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-in-impl.rs:9:16
-   |
-LL | impl<T: ~const PartialEq> const MyPartialEq for T {
-   |                ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs
index 3febb328a83..0df370bff8d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.rs
@@ -1,8 +1,8 @@
 //! Basic test for calling methods on generic type parameters in `const fn`.
 
-// known-bug: #110395
+// check-pass
 
-#![feature(const_trait_impl)]
+#![feature(const_trait_impl, effects)]
 
 struct S;
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr
deleted file mode 100644
index 37faa3f6bce..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-chain.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-chain.rs:18:32
-   |
-LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
-   |                                ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-chain.rs:22:40
-   |
-LL | const fn equals_self_wrapper<T: ~const PartialEq>(t: &T) -> bool {
-   |                                        ^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
index e618160d3b6..b0d5d068515 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.rs
@@ -1,6 +1,6 @@
-// known-bug: #110395
+// check-pass
 
-#![feature(const_trait_impl)]
+#![feature(const_trait_impl, effects)]
 
 struct S;
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr
deleted file mode 100644
index 90cfe04a9a8..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-dup-bound.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-dup-bound.rs:18:44
-   |
-LL | const fn equals_self<T: PartialEq + ~const PartialEq>(t: &T) -> bool {
-   |                                            ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-dup-bound.rs:25:37
-   |
-LL | const fn equals_self2<T: A + ~const PartialEq>(t: &T) -> bool {
-   |                                     ^^^^^^^^^
-
-error: aborting due to 2 previous errors
-
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
index 53778b3af3d..043939750a8 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.rs
@@ -1,10 +1,9 @@
-// FIXME(effects)
-// check-pass
 #![feature(const_trait_impl, effects)]
 
 pub const fn equals_self<T: PartialEq>(t: &T) -> bool {
     *t == *t
-    // (remove this) ~^ ERROR can't compare
+    //~^ ERROR mismatched types
+    // FIXME(effects): diagnostic
 }
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
new file mode 100644
index 00000000000..5074c4a2261
--- /dev/null
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-fail.stderr
@@ -0,0 +1,12 @@
+error[E0308]: mismatched types
+  --> $DIR/call-generic-method-fail.rs:4:5
+   |
+LL |     *t == *t
+   |     ^^^^^^^^ expected `host`, found `true`
+   |
+   = note: expected constant `host`
+              found constant `true`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
index b9331caaf8e..76bc738123d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.rs
@@ -21,7 +21,6 @@ const fn equals_self<T: ~const Foo>(t: &T) -> bool {
 // it not using the impl.
 
 pub const EQ: bool = equals_self(&S);
-//~^ ERROR
-// FIXME(effects) the diagnostics here isn't ideal, we shouldn't get `<false>`
+//~^ ERROR: the trait bound `S: ~const Foo` is not satisfied
 
 fn main() {}
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
index 4fe296d4d3f..aea9a39b261 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-nonconst.stderr
@@ -1,8 +1,8 @@
-error[E0277]: the trait bound `S: ~const Foo<false>` is not satisfied
+error[E0277]: the trait bound `S: ~const Foo` is not satisfied
   --> $DIR/call-generic-method-nonconst.rs:23:34
    |
 LL | pub const EQ: bool = equals_self(&S);
-   |                      ----------- ^^ the trait `Foo<false>` is not implemented for `S`
+   |                      ----------- ^^ the trait `~const Foo` is not implemented for `S`
    |                      |
    |                      required by a bound introduced by this call
    |
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs
index 09f35a27737..abd5d2fdb39 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.rs
@@ -1,8 +1,8 @@
 //! Basic test for calling methods on generic type parameters in `const fn`.
 
-// known-bug: #110395
+// check-pass
 
-#![feature(const_trait_impl)]
+#![feature(const_trait_impl, effects)]
 
 struct S;
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr
deleted file mode 100644
index 1f7cf689e95..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/call-generic-method-pass.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/call-generic-method-pass.rs:18:32
-   |
-LL | const fn equals_self<T: ~const PartialEq>(t: &T) -> bool {
-   |                                ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
index 111a6a3fc7f..f39e6dcadba 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-default-method-bodies.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `NonConstImpl: ~const ConstDefaultFn` is not satis
   --> $DIR/const-default-method-bodies.rs:24:18
    |
 LL |     NonConstImpl.a();
-   |                  ^ the trait `ConstDefaultFn` is not implemented for `NonConstImpl`
+   |                  ^ the trait `~const ConstDefaultFn` is not implemented for `NonConstImpl`
    |
    = help: the trait `ConstDefaultFn` is implemented for `NonConstImpl`
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
index 8e4de57b019..14d306fc31f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.rs
@@ -3,6 +3,7 @@
 #![feature(
     associated_type_bounds,
     const_trait_impl,
+    effects,
     const_cmp,
 )]
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
index 4a9090d0b53..ddedf8f1d8d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const-impl-trait.stderr
@@ -1,39 +1,28 @@
-error[E0635]: unknown feature `const_cmp`
-  --> $DIR/const-impl-trait.rs:6:5
+error[E0277]: can't compare `impl PartialEq + Destruct + Copy` with `impl PartialEq + Destruct + Copy`
+  --> $DIR/const-impl-trait.rs:28:17
    |
-LL |     const_cmp,
-   |     ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:11:30
-   |
-LL | const fn cmp(a: &impl ~const PartialEq) -> bool {
-   |                              ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:15:30
-   |
-LL | const fn wrap(x: impl ~const PartialEq + ~const Destruct)
-   |                              ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:16:20
+LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no implementation for `impl PartialEq + Destruct + Copy == impl PartialEq + Destruct + Copy`
    |
-LL |     -> impl ~const PartialEq + ~const Destruct
-   |                    ^^^^^^^^^
-
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:23:29
+   = help: the trait `~const PartialEq` is not implemented for `impl PartialEq + Destruct + Copy`
+note: required by a bound in `Foo::{opaque#0}`
+  --> $DIR/const-impl-trait.rs:24:22
    |
 LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
-   |                             ^^^^^^^^^
+   |                      ^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
 
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/const-impl-trait.rs:27:29
+error[E0277]: can't drop `impl PartialEq + Destruct + Copy`
+  --> $DIR/const-impl-trait.rs:28:17
    |
 LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy {
-   |                             ^^^^^^^^^
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `~const Destruct` is not implemented for `impl PartialEq + Destruct + Copy`
+   |
+note: required by a bound in `Foo::{opaque#0}`
+  --> $DIR/const-impl-trait.rs:24:41
+   |
+LL |     fn huh() -> impl ~const PartialEq + ~const Destruct + Copy;
+   |                                         ^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
 
-error: aborting due to 6 previous errors
+error: aborting due to 2 previous errors
 
-For more information about this error, try `rustc --explain E0635`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
index 69098542b7e..42d7283699f 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.rs
@@ -1,5 +1,6 @@
 // known-bug: #110395
-#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+
+#![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
 
 pub struct A;
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
index 046dbae0eae..c561f80653c 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-use.stderr
@@ -1,15 +1,28 @@
-error[E0635]: unknown feature `const_cmp`
-  --> $DIR/derive-const-use.rs:2:30
-   |
-LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
-   |                              ^^^^^^^^^
-
 error[E0635]: unknown feature `const_default_impls`
-  --> $DIR/derive-const-use.rs:2:41
+  --> $DIR/derive-const-use.rs:3:41
    |
-LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const)]
+LL | #![feature(const_trait_impl, const_cmp, const_default_impls, derive_const, effects)]
    |                                         ^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+  --> $DIR/derive-const-use.rs:7:12
+   |
+LL | impl const Default for A {
+   |            ^^^^^^^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
+
+error: const `impl` for trait `Default` which is not marked with `#[const_trait]`
+  --> $DIR/derive-const-use.rs:15:16
+   |
+LL | #[derive_const(Default, PartialEq)]
+   |                ^^^^^^^
+   |
+   = note: marking a trait with `#[const_trait]` ensures all default method bodies are `const`
+   = note: adding a non-const method body in the future would be a breaking change
+   = note: this error originates in the derive macro `Default` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0635`.
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
index 2a5d0176ba0..b479c967b0d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.rs
@@ -1,7 +1,7 @@
-// known-bug: #110395
+// check-pass
 
 #![feature(derive_const)]
-#![feature(const_trait_impl)]
+#![feature(const_trait_impl, effects)]
 
 #[derive_const(PartialEq)]
 pub struct Reverse<T>(T);
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr
deleted file mode 100644
index 3a8c4833414..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/const_derives/derive-const-with-params.stderr
+++ /dev/null
@@ -1,10 +0,0 @@
-error: ~const can only be applied to `#[const_trait]` traits
-  --> $DIR/derive-const-with-params.rs:6:16
-   |
-LL | #[derive_const(PartialEq)]
-   |                ^^^^^^^^^
-   |
-   = note: this error originates in the derive macro `PartialEq` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
index ed647aee8c3..f0ac953fd5d 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/cross-crate.gatednc.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `cross_crate::NonConst: ~const cross_crate::MyTrai
   --> $DIR/cross-crate.rs:17:14
    |
 LL |     NonConst.func();
-   |              ^^^^ the trait `cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
+   |              ^^^^ the trait `~const cross_crate::MyTrait` is not implemented for `cross_crate::NonConst`
    |
    = help: the trait `cross_crate::MyTrait` is implemented for `cross_crate::NonConst`
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
index d8e2c0ffb81..29db6109a98 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/default-method-body-is-const-same-trait-ck.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `(): ~const Tr` is not satisfied
   --> $DIR/default-method-body-is-const-same-trait-ck.rs:8:12
    |
 LL |         ().a()
-   |            ^ the trait `Tr` is not implemented for `()`
+   |            ^ the trait `~const Tr` is not implemented for `()`
    |
    = help: the trait `Tr` is implemented for `()`
 
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
index ede0c2e8eaf..3bfa6d2c254 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.fixed
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod foo {
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
index 48b091ddb45..14039626545 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.rs
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod foo {
diff --git a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
index c0a322edcd6..036b9ccab4f 100644
--- a/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-fully-qualified-paths.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:19:25
+  --> $DIR/edition-lint-fully-qualified-paths.rs:18:25
    |
 LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
@@ -7,13 +7,13 @@ LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/edition-lint-fully-qualified-paths.rs:4:9
+  --> $DIR/edition-lint-fully-qualified-paths.rs:3:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:19:25
+  --> $DIR/edition-lint-fully-qualified-paths.rs:18:25
    |
 LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    |                         ^^^^^^^^^^ help: use `crate`: `crate::foo::Foo`
@@ -23,7 +23,7 @@ LL |     let _: <foo::Baz as ::foo::Foo>::Bar = ();
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-fully-qualified-paths.rs:25:13
+  --> $DIR/edition-lint-fully-qualified-paths.rs:24:13
    |
 LL |     let _: <::foo::Baz as foo::Foo>::Bar = ();
    |             ^^^^^^^^^^ help: use `crate`: `crate::foo::Baz`
diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed b/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed
index f25d46ce30d..fd23e9f5562 100644
--- a/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.fixed
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused_imports)]
 #![allow(dead_code)]
diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs b/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs
index 9be1680c1ce..f3fb012a584 100644
--- a/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.rs
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused_imports)]
 #![allow(dead_code)]
diff --git a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
index 041572be844..4174c2fa9ad 100644
--- a/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-nested-empty-paths.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-empty-paths.rs:17:5
+  --> $DIR/edition-lint-nested-empty-paths.rs:16:5
    |
 LL | use foo::{bar::{baz::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}}}`
@@ -7,13 +7,13 @@ LL | use foo::{bar::{baz::{}}};
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/edition-lint-nested-empty-paths.rs:4:9
+  --> $DIR/edition-lint-nested-empty-paths.rs:3:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-empty-paths.rs:21:5
+  --> $DIR/edition-lint-nested-empty-paths.rs:20:5
    |
 LL | use foo::{bar::{XX, baz::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}`
@@ -22,7 +22,7 @@ LL | use foo::{bar::{XX, baz::{}}};
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-empty-paths.rs:21:5
+  --> $DIR/edition-lint-nested-empty-paths.rs:20:5
    |
 LL | use foo::{bar::{XX, baz::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{XX, baz::{}}}`
@@ -32,7 +32,7 @@ LL | use foo::{bar::{XX, baz::{}}};
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-empty-paths.rs:27:5
+  --> $DIR/edition-lint-nested-empty-paths.rs:26:5
    |
 LL | use foo::{bar::{baz::{}, baz1::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}`
@@ -41,7 +41,7 @@ LL | use foo::{bar::{baz::{}, baz1::{}}};
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-empty-paths.rs:27:5
+  --> $DIR/edition-lint-nested-empty-paths.rs:26:5
    |
 LL | use foo::{bar::{baz::{}, baz1::{}}};
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{bar::{baz::{}, baz1::{}}}`
diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.fixed b/tests/ui/rust-2018/edition-lint-nested-paths.fixed
index a04937ae8ee..0e47e70bb02 100644
--- a/tests/ui/rust-2018/edition-lint-nested-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-nested-paths.fixed
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 use crate::foo::{a, b};
diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.rs b/tests/ui/rust-2018/edition-lint-nested-paths.rs
index e622a8e24be..d261c10e36d 100644
--- a/tests/ui/rust-2018/edition-lint-nested-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-nested-paths.rs
@@ -1,6 +1,5 @@
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 use foo::{a, b};
diff --git a/tests/ui/rust-2018/edition-lint-nested-paths.stderr b/tests/ui/rust-2018/edition-lint-nested-paths.stderr
index 4a70bb7e5c8..d059a2533a9 100644
--- a/tests/ui/rust-2018/edition-lint-nested-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-nested-paths.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-paths.rs:6:5
+  --> $DIR/edition-lint-nested-paths.rs:5:5
    |
 LL | use foo::{a, b};
    |     ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}`
@@ -7,13 +7,13 @@ LL | use foo::{a, b};
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/edition-lint-nested-paths.rs:4:9
+  --> $DIR/edition-lint-nested-paths.rs:3:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-paths.rs:6:5
+  --> $DIR/edition-lint-nested-paths.rs:5:5
    |
 LL | use foo::{a, b};
    |     ^^^^^^^^^^^ help: use `crate`: `crate::foo::{a, b}`
@@ -23,7 +23,7 @@ LL | use foo::{a, b};
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-paths.rs:23:13
+  --> $DIR/edition-lint-nested-paths.rs:22:13
    |
 LL |         use foo::{self as x, c};
    |             ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}`
@@ -32,7 +32,7 @@ LL |         use foo::{self as x, c};
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-nested-paths.rs:23:13
+  --> $DIR/edition-lint-nested-paths.rs:22:13
    |
 LL |         use foo::{self as x, c};
    |             ^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::{self as x, c}`
diff --git a/tests/ui/rust-2018/edition-lint-paths.fixed b/tests/ui/rust-2018/edition-lint-paths.fixed
index 47f82c51dae..5057453c926 100644
--- a/tests/ui/rust-2018/edition-lint-paths.fixed
+++ b/tests/ui/rust-2018/edition-lint-paths.fixed
@@ -1,7 +1,6 @@
 // aux-build:edition-lint-paths.rs
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2018/edition-lint-paths.rs b/tests/ui/rust-2018/edition-lint-paths.rs
index e278983da4a..2c4a070ce83 100644
--- a/tests/ui/rust-2018/edition-lint-paths.rs
+++ b/tests/ui/rust-2018/edition-lint-paths.rs
@@ -1,7 +1,6 @@
 // aux-build:edition-lint-paths.rs
 // run-rustfix
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 #![allow(unused)]
 
diff --git a/tests/ui/rust-2018/edition-lint-paths.stderr b/tests/ui/rust-2018/edition-lint-paths.stderr
index fde17338d98..553a3bfdaa8 100644
--- a/tests/ui/rust-2018/edition-lint-paths.stderr
+++ b/tests/ui/rust-2018/edition-lint-paths.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:12:9
+  --> $DIR/edition-lint-paths.rs:11:9
    |
 LL |     use bar::Bar;
    |         ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
@@ -7,13 +7,13 @@ LL |     use bar::Bar;
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/edition-lint-paths.rs:5:9
+  --> $DIR/edition-lint-paths.rs:4:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:19:9
+  --> $DIR/edition-lint-paths.rs:18:9
    |
 LL |     use bar;
    |         ^^^ help: use `crate`: `crate::bar`
@@ -22,7 +22,7 @@ LL |     use bar;
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:25:9
+  --> $DIR/edition-lint-paths.rs:24:9
    |
 LL |     use {main, Bar as SomethingElse};
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}`
@@ -31,7 +31,7 @@ LL |     use {main, Bar as SomethingElse};
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:25:9
+  --> $DIR/edition-lint-paths.rs:24:9
    |
 LL |     use {main, Bar as SomethingElse};
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}`
@@ -41,7 +41,7 @@ LL |     use {main, Bar as SomethingElse};
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:25:9
+  --> $DIR/edition-lint-paths.rs:24:9
    |
 LL |     use {main, Bar as SomethingElse};
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::{main, Bar as SomethingElse}`
@@ -51,7 +51,7 @@ LL |     use {main, Bar as SomethingElse};
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:40:5
+  --> $DIR/edition-lint-paths.rs:39:5
    |
 LL | use bar::Bar;
    |     ^^^^^^^^ help: use `crate`: `crate::bar::Bar`
@@ -60,7 +60,7 @@ LL | use bar::Bar;
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:52:9
+  --> $DIR/edition-lint-paths.rs:51:9
    |
 LL |     use *;
    |         ^ help: use `crate`: `crate::*`
@@ -69,7 +69,7 @@ LL |     use *;
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:57:6
+  --> $DIR/edition-lint-paths.rs:56:6
    |
 LL | impl ::foo::SomeTrait for u32 {}
    |      ^^^^^^^^^^^^^^^^ help: use `crate`: `crate::foo::SomeTrait`
@@ -78,7 +78,7 @@ LL | impl ::foo::SomeTrait for u32 {}
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/edition-lint-paths.rs:62:13
+  --> $DIR/edition-lint-paths.rs:61:13
    |
 LL |     let x = ::bar::Bar;
    |             ^^^^^^^^^^ help: use `crate`: `crate::bar::Bar`
diff --git a/tests/ui/rust-2018/extern-crate-idiomatic.fixed b/tests/ui/rust-2018/extern-crate-idiomatic.fixed
index 3111b1dabcb..6a0639099b1 100644
--- a/tests/ui/rust-2018/extern-crate-idiomatic.fixed
+++ b/tests/ui/rust-2018/extern-crate-idiomatic.fixed
@@ -6,7 +6,6 @@
 // The "normal case". Ideally we would remove the `extern crate` here,
 // but we don't.
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths;
diff --git a/tests/ui/rust-2018/extern-crate-idiomatic.rs b/tests/ui/rust-2018/extern-crate-idiomatic.rs
index 3111b1dabcb..6a0639099b1 100644
--- a/tests/ui/rust-2018/extern-crate-idiomatic.rs
+++ b/tests/ui/rust-2018/extern-crate-idiomatic.rs
@@ -6,7 +6,6 @@
 // The "normal case". Ideally we would remove the `extern crate` here,
 // but we don't.
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths;
diff --git a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed
index 11b9a67ed70..c4a3dd9415c 100644
--- a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed
+++ b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.fixed
@@ -6,7 +6,6 @@
 // rather than being accessed directly. Unless we rewrite that path,
 // we can't drop the extern crate.
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths;
diff --git a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs
index 11b9a67ed70..c4a3dd9415c 100644
--- a/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs
+++ b/tests/ui/rust-2018/extern-crate-referenced-by-self-path.rs
@@ -6,7 +6,6 @@
 // rather than being accessed directly. Unless we rewrite that path,
 // we can't drop the extern crate.
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths;
diff --git a/tests/ui/rust-2018/extern-crate-rename.fixed b/tests/ui/rust-2018/extern-crate-rename.fixed
index ea832ef3e7d..5e2bf64a2e2 100644
--- a/tests/ui/rust-2018/extern-crate-rename.fixed
+++ b/tests/ui/rust-2018/extern-crate-rename.fixed
@@ -4,7 +4,6 @@
 // Oddball: crate is renamed, making it harder for us to rewrite
 // paths. We don't (and we leave the `extern crate` in place).
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths as my_crate;
diff --git a/tests/ui/rust-2018/extern-crate-rename.rs b/tests/ui/rust-2018/extern-crate-rename.rs
index b1f617dd884..290fcd6b7db 100644
--- a/tests/ui/rust-2018/extern-crate-rename.rs
+++ b/tests/ui/rust-2018/extern-crate-rename.rs
@@ -4,7 +4,6 @@
 // Oddball: crate is renamed, making it harder for us to rewrite
 // paths. We don't (and we leave the `extern crate` in place).
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 extern crate edition_lint_paths as my_crate;
diff --git a/tests/ui/rust-2018/extern-crate-rename.stderr b/tests/ui/rust-2018/extern-crate-rename.stderr
index 36986c89c62..6b251208030 100644
--- a/tests/ui/rust-2018/extern-crate-rename.stderr
+++ b/tests/ui/rust-2018/extern-crate-rename.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/extern-crate-rename.rs:12:5
+  --> $DIR/extern-crate-rename.rs:11:5
    |
 LL | use my_crate::foo;
    |     ^^^^^^^^^^^^^ help: use `crate`: `crate::my_crate::foo`
@@ -7,7 +7,7 @@ LL | use my_crate::foo;
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/extern-crate-rename.rs:8:9
+  --> $DIR/extern-crate-rename.rs:7:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2018/extern-crate-submod.fixed b/tests/ui/rust-2018/extern-crate-submod.fixed
index 9b0b0dd8ee1..dd31710414c 100644
--- a/tests/ui/rust-2018/extern-crate-submod.fixed
+++ b/tests/ui/rust-2018/extern-crate-submod.fixed
@@ -5,7 +5,6 @@
 // us to rewrite paths. We don't (and we leave the `extern crate` in
 // place).
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod m {
diff --git a/tests/ui/rust-2018/extern-crate-submod.rs b/tests/ui/rust-2018/extern-crate-submod.rs
index dfce9128c51..cb0cd7a8331 100644
--- a/tests/ui/rust-2018/extern-crate-submod.rs
+++ b/tests/ui/rust-2018/extern-crate-submod.rs
@@ -5,7 +5,6 @@
 // us to rewrite paths. We don't (and we leave the `extern crate` in
 // place).
 
-#![feature(rust_2018_preview)]
 #![deny(absolute_paths_not_starting_with_crate)]
 
 mod m {
diff --git a/tests/ui/rust-2018/extern-crate-submod.stderr b/tests/ui/rust-2018/extern-crate-submod.stderr
index 85e26d72a67..0d45d32d568 100644
--- a/tests/ui/rust-2018/extern-crate-submod.stderr
+++ b/tests/ui/rust-2018/extern-crate-submod.stderr
@@ -1,5 +1,5 @@
 error: absolute paths must start with `self`, `super`, `crate`, or an external crate name in the 2018 edition
-  --> $DIR/extern-crate-submod.rs:19:5
+  --> $DIR/extern-crate-submod.rs:18:5
    |
 LL | use m::edition_lint_paths::foo;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use `crate`: `crate::m::edition_lint_paths::foo`
@@ -7,7 +7,7 @@ LL | use m::edition_lint_paths::foo;
    = warning: this is accepted in the current edition (Rust 2015) but is a hard error in Rust 2018!
    = note: for more information, see issue #53130 <https://github.com/rust-lang/rust/issues/53130>
 note: the lint level is defined here
-  --> $DIR/extern-crate-submod.rs:9:9
+  --> $DIR/extern-crate-submod.rs:8:9
    |
 LL | #![deny(absolute_paths_not_starting_with_crate)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/rust-2018/issue-51008-1.rs b/tests/ui/rust-2018/issue-51008-1.rs
index 8ae5e827846..da7b8ef65c5 100644
--- a/tests/ui/rust-2018/issue-51008-1.rs
+++ b/tests/ui/rust-2018/issue-51008-1.rs
@@ -4,8 +4,6 @@
 //
 // run-pass
 
-#![feature(rust_2018_preview)]
-
 trait A {
 
 }
diff --git a/tests/ui/rust-2018/issue-51008.rs b/tests/ui/rust-2018/issue-51008.rs
index b62609e329d..56517b9adee 100644
--- a/tests/ui/rust-2018/issue-51008.rs
+++ b/tests/ui/rust-2018/issue-51008.rs
@@ -4,8 +4,6 @@
 //
 // run-pass
 
-#![feature(rust_2018_preview)]
-
 trait A {
 
 }
diff --git a/tests/ui/rust-2018/proc-macro-crate-in-paths.rs b/tests/ui/rust-2018/proc-macro-crate-in-paths.rs
index 2d4cb6514ec..37e00a3936e 100644
--- a/tests/ui/rust-2018/proc-macro-crate-in-paths.rs
+++ b/tests/ui/rust-2018/proc-macro-crate-in-paths.rs
@@ -4,7 +4,6 @@
 
 #![crate_type = "proc-macro"]
 #![deny(rust_2018_compatibility)]
-#![feature(rust_2018_preview)]
 
 extern crate proc_macro;
 
diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed
index f5afbad9f78..d9e39a3b748 100644
--- a/tests/ui/rust-2018/suggestions-not-always-applicable.fixed
+++ b/tests/ui/rust-2018/suggestions-not-always-applicable.fixed
@@ -4,7 +4,6 @@
 // rustfix-only-machine-applicable
 // check-pass
 
-#![feature(rust_2018_preview)]
 #![warn(rust_2018_compatibility)]
 
 extern crate suggestions_not_always_applicable as foo;
diff --git a/tests/ui/rust-2018/suggestions-not-always-applicable.rs b/tests/ui/rust-2018/suggestions-not-always-applicable.rs
index f5afbad9f78..d9e39a3b748 100644
--- a/tests/ui/rust-2018/suggestions-not-always-applicable.rs
+++ b/tests/ui/rust-2018/suggestions-not-always-applicable.rs
@@ -4,7 +4,6 @@
 // rustfix-only-machine-applicable
 // check-pass
 
-#![feature(rust_2018_preview)]
 #![warn(rust_2018_compatibility)]
 
 extern crate suggestions_not_always_applicable as foo;
diff --git a/tests/ui/simd/repr_packed.rs b/tests/ui/simd/repr_packed.rs
new file mode 100644
index 00000000000..df2d59a58b8
--- /dev/null
+++ b/tests/ui/simd/repr_packed.rs
@@ -0,0 +1,59 @@
+// run-pass
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd, packed)]
+struct Simd<T, const N: usize>([T; N]);
+
+#[repr(simd)]
+struct FullSimd<T, const N: usize>([T; N]);
+
+fn check_size_align<T, const N: usize>() {
+    use std::mem;
+    assert_eq!(mem::size_of::<Simd<T, N>>(), mem::size_of::<[T; N]>());
+    assert_eq!(mem::size_of::<Simd<T, N>>() % mem::align_of::<Simd<T, N>>(), 0);
+}
+
+fn check_ty<T>() {
+    check_size_align::<T, 1>();
+    check_size_align::<T, 2>();
+    check_size_align::<T, 3>();
+    check_size_align::<T, 4>();
+    check_size_align::<T, 8>();
+    check_size_align::<T, 9>();
+    check_size_align::<T, 15>();
+}
+
+extern "platform-intrinsic" {
+    fn simd_add<T>(a: T, b: T) -> T;
+}
+
+fn main() {
+    check_ty::<u8>();
+    check_ty::<i16>();
+    check_ty::<u32>();
+    check_ty::<i64>();
+    check_ty::<usize>();
+    check_ty::<f32>();
+    check_ty::<f64>();
+
+    unsafe {
+        // powers-of-two have no padding and work as usual
+        let x: Simd<f64, 4> =
+            simd_add(Simd::<f64, 4>([0., 1., 2., 3.]), Simd::<f64, 4>([2., 2., 2., 2.]));
+        assert_eq!(std::mem::transmute::<_, [f64; 4]>(x), [2., 3., 4., 5.]);
+
+        // non-powers-of-two have padding and need to be expanded to full vectors
+        fn load<T, const N: usize>(v: Simd<T, N>) -> FullSimd<T, N> {
+            unsafe {
+                let mut tmp = core::mem::MaybeUninit::<FullSimd<T, N>>::uninit();
+                std::ptr::copy_nonoverlapping(&v as *const _, tmp.as_mut_ptr().cast(), 1);
+                tmp.assume_init()
+            }
+        }
+        let x: FullSimd<f64, 3> =
+            simd_add(load(Simd::<f64, 3>([0., 1., 2.])), load(Simd::<f64, 3>([2., 2., 2.])));
+        assert_eq!(x.0, [2., 3., 4.]);
+    }
+}
diff --git a/tests/ui/specialization/specialization-translate-projections.rs b/tests/ui/specialization/specialization-translate-projections.rs
index 92ea9e2b85d..a9753376135 100644
--- a/tests/ui/specialization/specialization-translate-projections.rs
+++ b/tests/ui/specialization/specialization-translate-projections.rs
@@ -5,7 +5,6 @@
 
 #![feature(specialization)] //~ WARN the feature `specialization` is incomplete
 
-use std::convert::Into;
 
 trait Trait {
     fn to_u8(&self) -> u8;
diff --git a/tests/ui/stdlib-unit-tests/istr.rs b/tests/ui/stdlib-unit-tests/istr.rs
index dca6d40d59a..219b47789b8 100644
--- a/tests/ui/stdlib-unit-tests/istr.rs
+++ b/tests/ui/stdlib-unit-tests/istr.rs
@@ -1,7 +1,5 @@
 // run-pass
 
-use std::string::String;
-
 fn test_stack_assign() {
     let s: String = "a".to_string();
     println!("{}", s.clone());
diff --git a/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs b/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs
index 9100bfbde95..7fbffb8fa98 100644
--- a/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs
+++ b/tests/ui/stdlib-unit-tests/minmax-stability-issue-23687.rs
@@ -1,7 +1,7 @@
 // run-pass
 
 use std::fmt::Debug;
-use std::cmp::{self, PartialOrd, Ordering};
+use std::cmp::{self, Ordering};
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq)]
 struct Foo {
diff --git a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs
index f870096fdd4..989f0a275f7 100644
--- a/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs
+++ b/tests/ui/structs-enums/class-cast-to-trait-cross-crate-2.rs
@@ -3,7 +3,6 @@
 
 extern crate cci_class_cast;
 
-use std::string::ToString;
 use cci_class_cast::kitty::cat;
 
 fn print_out(thing: Box<dyn ToString>, expected: String) {
diff --git a/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs b/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs
index ae267e7988e..1d52d44d169 100644
--- a/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs
+++ b/tests/ui/structs-enums/enum-nullable-const-null-with-fields.rs
@@ -1,8 +1,5 @@
 // run-pass
 
-use std::result::Result;
-use std::result::Result::Ok;
-
 static C: Result<(), Box<isize>> = Ok(());
 
 // This is because of yet another bad assertion (ICE) about the null side of a nullable enum.
diff --git a/tests/ui/suggestions/derive-clone-for-eq.fixed b/tests/ui/suggestions/derive-clone-for-eq.fixed
index f07784d53b3..a74487019ad 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.fixed
+++ b/tests/ui/suggestions/derive-clone-for-eq.fixed
@@ -1,8 +1,6 @@
 // run-rustfix
 // https://github.com/rust-lang/rust/issues/79076
 
-use std::cmp::PartialEq;
-
 #[derive(Clone, Eq)] //~ ERROR [E0277]
 pub struct Struct<T: std::clone::Clone>(T);
 
diff --git a/tests/ui/suggestions/derive-clone-for-eq.rs b/tests/ui/suggestions/derive-clone-for-eq.rs
index 15c0d4659fb..99956ed9879 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.rs
+++ b/tests/ui/suggestions/derive-clone-for-eq.rs
@@ -1,8 +1,6 @@
 // run-rustfix
 // https://github.com/rust-lang/rust/issues/79076
 
-use std::cmp::PartialEq;
-
 #[derive(Clone, Eq)] //~ ERROR [E0277]
 pub struct Struct<T>(T);
 
diff --git a/tests/ui/suggestions/derive-clone-for-eq.stderr b/tests/ui/suggestions/derive-clone-for-eq.stderr
index eb95f729d1e..680890e880c 100644
--- a/tests/ui/suggestions/derive-clone-for-eq.stderr
+++ b/tests/ui/suggestions/derive-clone-for-eq.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/derive-clone-for-eq.rs:6:17
+  --> $DIR/derive-clone-for-eq.rs:4:17
    |
 LL | #[derive(Clone, Eq)]
    |                 ^^ the trait `Clone` is not implemented for `T`
    |
 note: required for `Struct<T>` to implement `PartialEq`
-  --> $DIR/derive-clone-for-eq.rs:9:19
+  --> $DIR/derive-clone-for-eq.rs:7:19
    |
 LL | impl<T: Clone, U> PartialEq<U> for Struct<T>
    |         -----     ^^^^^^^^^^^^     ^^^^^^^^^
diff --git a/tests/ui/suggestions/invalid-bin-op.stderr b/tests/ui/suggestions/invalid-bin-op.stderr
index 018250c8c1b..2bd745c645a 100644
--- a/tests/ui/suggestions/invalid-bin-op.stderr
+++ b/tests/ui/suggestions/invalid-bin-op.stderr
@@ -16,10 +16,6 @@ help: consider annotating `S<T>` with `#[derive(PartialEq)]`
 LL + #[derive(PartialEq)]
 LL | struct S<T>(T);
    |
-help: consider introducing a `where` clause, but there might be an alternative better way to express this requirement
-   |
-LL | pub fn foo<T>(s: S<T>, t: S<T>) where S<T>: PartialEq {
-   |                                 +++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/tool_lints_2018_preview.rs b/tests/ui/tool_lints_2018_preview.rs
index 190f0b99dc8..e467d34376f 100644
--- a/tests/ui/tool_lints_2018_preview.rs
+++ b/tests/ui/tool_lints_2018_preview.rs
@@ -1,6 +1,5 @@
 // run-pass
 
-#![feature(rust_2018_preview)]
 #![deny(unknown_lints)]
 
 #[allow(clippy::almost_swapped)]
diff --git a/tests/ui/traits/inheritance/num0.rs b/tests/ui/traits/inheritance/num0.rs
index cee52542d38..c9c73ee00e6 100644
--- a/tests/ui/traits/inheritance/num0.rs
+++ b/tests/ui/traits/inheritance/num0.rs
@@ -4,8 +4,6 @@
 
 // pretty-expanded FIXME #23616
 
-use std::cmp::PartialOrd;
-
 pub trait NumCast: Sized {
     fn from(i: i32) -> Option<Self>;
 }
diff --git a/tests/ui/traits/inheritance/overloading-simple.rs b/tests/ui/traits/inheritance/overloading-simple.rs
index c306aa2cda0..800d7bc6b1f 100644
--- a/tests/ui/traits/inheritance/overloading-simple.rs
+++ b/tests/ui/traits/inheritance/overloading-simple.rs
@@ -1,6 +1,5 @@
 // run-pass
 #![allow(dead_code)]
-use std::cmp::PartialEq;
 
 trait MyNum : PartialEq { }
 
diff --git a/tests/ui/traits/inheritance/overloading.rs b/tests/ui/traits/inheritance/overloading.rs
index 083643e821f..f126847da09 100644
--- a/tests/ui/traits/inheritance/overloading.rs
+++ b/tests/ui/traits/inheritance/overloading.rs
@@ -1,5 +1,4 @@
 // run-pass
-use std::cmp::PartialEq;
 use std::ops::{Add, Sub, Mul};
 
 trait MyNum : Add<Output=Self> + Sub<Output=Self> + Mul<Output=Self> + PartialEq + Clone { }
diff --git a/tests/ui/traits/issue-22019.rs b/tests/ui/traits/issue-22019.rs
index 1a887f0f39f..605fee510b1 100644
--- a/tests/ui/traits/issue-22019.rs
+++ b/tests/ui/traits/issue-22019.rs
@@ -8,8 +8,6 @@
 #![allow(missing_copy_implementations)]
 #![allow(unused_variables)]
 
-use std::borrow::ToOwned;
-
 pub struct CFGNode;
 
 pub type Node<'a> = &'a CFGNode;
diff --git a/tests/ui/traits/multidispatch2.rs b/tests/ui/traits/multidispatch2.rs
index 20608aabb3b..21aa13fd487 100644
--- a/tests/ui/traits/multidispatch2.rs
+++ b/tests/ui/traits/multidispatch2.rs
@@ -1,7 +1,6 @@
 // run-pass
 
 use std::fmt::Debug;
-use std::default::Default;
 
 trait MyTrait<T> {
     fn get(&self) -> T;
diff --git a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
index a1042f8310a..0bc611c26ca 100644
--- a/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
+++ b/tests/ui/traits/negative-impls/negated-auto-traits-rpass.rs
@@ -2,8 +2,6 @@
 #![allow(unused_variables)]
 #![feature(negative_impls)]
 
-use std::marker::Send;
-
 pub struct WaitToken;
 impl !Send for WaitToken {}
 
diff --git a/tests/ui/traits/wf-object/reverse-order.rs b/tests/ui/traits/wf-object/reverse-order.rs
index 4f676cbe338..74b2ef48533 100644
--- a/tests/ui/traits/wf-object/reverse-order.rs
+++ b/tests/ui/traits/wf-object/reverse-order.rs
@@ -2,8 +2,6 @@
 
 // Ensure that `dyn $($AutoTrait)+ ObjSafe` is well-formed.
 
-use std::marker::Unpin;
-
 // Some arbitrary object-safe trait:
 trait Obj {}
 
diff --git a/tests/ui/ufcs/ufcs-polymorphic-paths.rs b/tests/ui/ufcs/ufcs-polymorphic-paths.rs
index a14ebd6a41f..71b9de8184c 100644
--- a/tests/ui/ufcs/ufcs-polymorphic-paths.rs
+++ b/tests/ui/ufcs/ufcs-polymorphic-paths.rs
@@ -1,7 +1,6 @@
 // run-pass
 
-use std::borrow::{Cow, ToOwned};
-use std::default::Default;
+use std::borrow::Cow;
 use std::iter::FromIterator;
 use std::ops::Add;
 use std::option::IntoIter as OptionIter;
diff --git a/tests/ui/unboxed-closures/unboxed-closures-boxed.rs b/tests/ui/unboxed-closures/unboxed-closures-boxed.rs
index 3f550fd0425..53f0523da70 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-boxed.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-boxed.rs
@@ -1,6 +1,5 @@
 // run-pass
 
-use std::ops::FnMut;
 
  fn make_adder(x: i32) -> Box<dyn FnMut(i32)->i32+'static> {
     Box::new(move |y: i32| -> i32 { x + y }) as
diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs
index 9b8a3f4098c..8a40c1d4785 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-autoderef.rs
@@ -1,8 +1,6 @@
 // run-pass
 // Test that the call operator autoderefs when calling a bounded type parameter.
 
-use std::ops::FnMut;
-
 fn call_with_2<F>(x: &mut F) -> isize
     where F : FnMut(isize) -> isize
 {
diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs
index d47ceea0f4f..2433f0757aa 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object-autoderef.rs
@@ -1,8 +1,6 @@
 // run-pass
 // Test that the call operator autoderefs when calling to an object type.
 
-use std::ops::FnMut;
-
 fn make_adder(x: isize) -> Box<dyn FnMut(isize)->isize + 'static> {
     Box::new(move |y| { x + y })
 }
diff --git a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs
index f77733d106d..b27d6104959 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-call-sugar-object.rs
@@ -1,6 +1,4 @@
 // run-pass
-use std::ops::FnMut;
-
 fn make_adder(x: isize) -> Box<dyn FnMut(isize)->isize + 'static> {
     Box::new(move |y| { x + y })
 }
diff --git a/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs b/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs
index 677cd259a4e..d07e871b10d 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-extern-fn.rs
@@ -1,7 +1,6 @@
 // run-pass
 // Checks that extern fn pointers implement the full range of Fn traits.
 
-use std::ops::{Fn,FnMut,FnOnce};
 
 fn square(x: isize) -> isize { x * x }
 
diff --git a/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs
index 851f3d2fe9b..db1bea0e115 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-fn-as-fnmut-and-fnonce.rs
@@ -4,8 +4,6 @@
 
 #![feature(unboxed_closures, fn_traits)]
 
-use std::ops::{Fn,FnMut,FnOnce};
-
 struct S;
 
 impl Fn<(i32,)> for S {
diff --git a/tests/ui/unboxed-closures/unboxed-closures-generic.rs b/tests/ui/unboxed-closures/unboxed-closures-generic.rs
index 740b8b2a72f..524e756e69b 100644
--- a/tests/ui/unboxed-closures/unboxed-closures-generic.rs
+++ b/tests/ui/unboxed-closures/unboxed-closures-generic.rs
@@ -1,6 +1,4 @@
 // run-pass
-use std::ops::FnMut;
-
 fn call_it<F:FnMut(i32,i32)->i32>(y: i32, mut f: F) -> i32 {
     f(2, y)
 }
diff --git a/tests/ui/zero-sized/zero-sized-binary-heap-push.rs b/tests/ui/zero-sized/zero-sized-binary-heap-push.rs
index 6553c5adbe7..14cf6c2036b 100644
--- a/tests/ui/zero-sized/zero-sized-binary-heap-push.rs
+++ b/tests/ui/zero-sized/zero-sized-binary-heap-push.rs
@@ -1,7 +1,6 @@
 // run-pass
 #![allow(unused_variables)]
 use std::collections::BinaryHeap;
-use std::iter::Iterator;
 
 fn main() {
     const N: usize = 8;
diff --git a/tests/ui/zero-sized/zero-sized-linkedlist-push.rs b/tests/ui/zero-sized/zero-sized-linkedlist-push.rs
index 03724085f5f..301f03110b7 100644
--- a/tests/ui/zero-sized/zero-sized-linkedlist-push.rs
+++ b/tests/ui/zero-sized/zero-sized-linkedlist-push.rs
@@ -1,6 +1,5 @@
 // run-pass
 use std::collections::LinkedList;
-use std::iter::Iterator;
 
 fn main() {
     const N: usize = 8;