about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml11
-rw-r--r--Cargo.lock65
-rw-r--r--RELEASES.md105
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs3
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs11
-rw-r--r--compiler/rustc_borrowck/src/consumers.rs2
-rw-r--r--compiler/rustc_borrowck/src/invalidation.rs6
-rw-r--r--compiler/rustc_borrowck/src/lib.rs10
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs8
-rw-r--r--compiler/rustc_codegen_cranelift/src/base.rs4
-rw-r--r--compiler/rustc_codegen_cranelift/src/constant.rs4
-rw-r--r--compiler/rustc_codegen_gcc/src/debuginfo.rs2
-rw-r--r--compiler/rustc_codegen_llvm/src/attributes.rs5
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs35
-rw-r--r--compiler/rustc_codegen_llvm/src/debuginfo/mod.rs76
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs38
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/analyze.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/block.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/debuginfo.rs68
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/mod.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/debuginfo.rs2
-rw-r--r--compiler/rustc_const_eval/src/const_eval/error.rs4
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs64
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs6
-rw-r--r--compiler/rustc_const_eval/src/interpret/intrinsics.rs16
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs14
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs7
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/check.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs4
-rw-r--r--compiler/rustc_const_eval/src/transform/validate.rs60
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0132.md2
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0152.md4
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0191.md6
-rw-r--r--compiler/rustc_errors/src/lib.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/macro_parser.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs2
-rw-r--r--compiler/rustc_expand/src/mbe/metavar_expr.rs12
-rw-r--r--compiler/rustc_expand/src/mbe/transcribe.rs7
-rw-r--r--compiler/rustc_feature/src/active.rs2
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs1
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/errors.rs16
-rw-r--r--compiler/rustc_hir_analysis/src/check/compare_impl_item.rs9
-rw-r--r--compiler/rustc_hir_analysis/src/check/mod.rs1
-rw-r--r--compiler/rustc_hir_typeck/src/cast.rs32
-rw-r--r--compiler/rustc_hir_typeck/src/closure.rs13
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/demand.rs6
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs29
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs5
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs11
-rw-r--r--compiler/rustc_hir_typeck/src/method/prelude2021.rs21
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs20
-rw-r--r--compiler/rustc_index/src/lib.rs12
-rw-r--r--compiler/rustc_infer/src/traits/mod.rs24
-rw-r--r--compiler/rustc_lint/src/context.rs8
-rw-r--r--compiler/rustc_lint/src/levels.rs28
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs42
-rw-r--r--compiler/rustc_lint_defs/src/lib.rs7
-rw-r--r--compiler/rustc_macros/src/serialize.rs4
-rw-r--r--compiler/rustc_middle/src/hir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/mir/coverage.rs15
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/patch.rs8
-rw-r--r--compiler/rustc_middle/src/mir/pretty.rs9
-rw-r--r--compiler/rustc_middle/src/mir/spanview.rs45
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs30
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs26
-rw-r--r--compiler/rustc_middle/src/mir/visit.rs5
-rw-r--r--compiler/rustc_middle/src/ty/diagnostics.rs9
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs1
-rw-r--r--compiler/rustc_mir_build/src/build/custom/parse/instruction.rs19
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/scope.rs14
-rw-r--r--compiler/rustc_mir_build/src/lints.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs4
-rw-r--r--compiler/rustc_mir_dataflow/src/value_analysis.rs4
-rw-r--r--compiler/rustc_mir_transform/src/check_unsafety.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/const_prop_lint.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/counters.rs87
-rw-r--r--compiler/rustc_mir_transform/src/coverage/debug.rs73
-rw-r--r--compiler/rustc_mir_transform/src/coverage/graph.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/mod.rs68
-rw-r--r--compiler/rustc_mir_transform/src/coverage/spans.rs4
-rw-r--r--compiler/rustc_mir_transform/src/coverage/tests.rs9
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs7
-rw-r--r--compiler/rustc_mir_transform/src/deduce_param_attrs.rs7
-rw-r--r--compiler/rustc_mir_transform/src/dest_prop.rs4
-rw-r--r--compiler/rustc_mir_transform/src/elaborate_drops.rs2
-rw-r--r--compiler/rustc_mir_transform/src/generator.rs35
-rw-r--r--compiler/rustc_mir_transform/src/inline.rs10
-rw-r--r--compiler/rustc_mir_transform/src/ref_prop.rs8
-rw-r--r--compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs20
-rw-r--r--compiler/rustc_mir_transform/src/separate_const_switch.rs8
-rw-r--r--compiler/rustc_mir_transform/src/shim.rs23
-rw-r--r--compiler/rustc_monomorphize/src/collector.rs4
-rw-r--r--compiler/rustc_parse/messages.ftl4
-rw-r--r--compiler/rustc_parse/src/errors.rs19
-rw-r--r--compiler/rustc_parse/src/lexer/unescape_error_reporting.rs22
-rw-r--r--compiler/rustc_parse/src/parser/expr.rs43
-rw-r--r--compiler/rustc_parse/src/parser/mod.rs33
-rw-r--r--compiler/rustc_parse/src/parser/nonterminal.rs87
-rw-r--r--compiler/rustc_parse/src/parser/ty.rs24
-rw-r--r--compiler/rustc_passes/src/layout_test.rs1
-rw-r--r--compiler/rustc_passes/src/liveness.rs1
-rw-r--r--compiler/rustc_resolve/src/late.rs79
-rw-r--r--compiler/rustc_resolve/src/rustdoc.rs75
-rw-r--r--compiler/rustc_session/messages.ftl3
-rw-r--r--compiler/rustc_session/src/config.rs12
-rw-r--r--compiler/rustc_session/src/errors.rs6
-rw-r--r--compiler/rustc_session/src/parse.rs17
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs4
-rw-r--r--compiler/rustc_smir/src/stable_mir/mod.rs2
-rw-r--r--compiler/rustc_span/src/symbol.rs9
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs1
-rw-r--r--compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs1
-rw-r--r--compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs56
-rw-r--r--compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs13
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs1
-rw-r--r--library/alloc/src/boxed.rs4
-rw-r--r--library/alloc/src/lib.rs2
-rw-r--r--library/alloc/src/slice.rs2
-rw-r--r--library/alloc/src/sync.rs6
-rw-r--r--library/core/src/ffi/c_str.rs4
-rw-r--r--library/core/src/intrinsics/mir.rs9
-rw-r--r--library/core/src/lib.rs2
-rw-r--r--library/core/src/mem/mod.rs4
-rw-r--r--library/core/src/num/int_macros.rs1
-rw-r--r--library/core/src/num/uint_macros.rs1
-rw-r--r--library/core/src/str/mod.rs2
-rw-r--r--library/std/src/collections/hash/map.rs6
-rw-r--r--library/std/src/collections/hash/set.rs7
-rw-r--r--library/std/src/error.rs2
-rw-r--r--library/std/src/f32.rs11
-rw-r--r--library/std/src/f64.rs11
-rw-r--r--library/std/src/io/mod.rs6
-rw-r--r--library/std/src/lib.rs1
-rw-r--r--library/std/src/sys/solid/os.rs30
-rw-r--r--library/std/src/sys/unix/os.rs21
-rw-r--r--library/std/src/sys/wasi/os.rs23
-rw-r--r--library/std/src/sys/windows/os.rs8
-rw-r--r--library/std/src/sys_common/thread_parking/id.rs17
-rw-r--r--library/std/tests/env.rs20
-rw-r--r--src/bootstrap/bootstrap.py9
-rw-r--r--src/bootstrap/download.rs2
-rw-r--r--src/bootstrap/test.rs7
-rw-r--r--src/bootstrap/tool.rs2
-rw-r--r--src/ci/github-actions/ci.yml12
-rw-r--r--src/doc/rustc/src/platform-support.md8
-rw-r--r--src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md1
-rw-r--r--src/doc/rustdoc/src/how-to-write-documentation.md13
-rw-r--r--src/doc/rustdoc/src/lints.md34
-rw-r--r--src/doc/unstable-book/src/language-features/lang-items.md311
-rw-r--r--src/doc/unstable-book/src/language-features/start.md59
-rw-r--r--src/librustdoc/html/markdown.rs107
-rw-r--r--src/librustdoc/html/static/css/rustdoc.css26
-rw-r--r--src/librustdoc/html/static/css/themes/ayu.css1
-rw-r--r--src/librustdoc/html/static/css/themes/dark.css1
-rw-r--r--src/librustdoc/html/static/css/themes/light.css1
-rw-r--r--src/librustdoc/lint.rs12
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs104
-rw-r--r--src/librustdoc/passes/lint.rs2
-rw-r--r--src/librustdoc/passes/lint/redundant_explicit_links.rs347
m---------src/tools/cargo0
-rw-r--r--src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs103
-rw-r--r--src/tools/clippy/clippy_lints/src/useless_conversion.rs18
-rw-r--r--src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs4
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-11065.rs19
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs35
-rw-r--r--src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.fixed14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.rs14
-rw-r--r--src/tools/clippy/tests/ui/useless_conversion.stderr20
-rw-r--r--src/tools/miri/.github/workflows/ci.yml2
-rw-r--r--src/tools/miri/CONTRIBUTING.md46
-rw-r--r--src/tools/miri/Cargo.lock21
-rw-r--r--src/tools/miri/Cargo.toml2
-rw-r--r--src/tools/miri/README.md6
-rw-r--r--src/tools/miri/cargo-miri/Cargo.lock20
-rw-r--r--src/tools/miri/cargo-miri/Cargo.toml3
-rwxr-xr-xsrc/tools/miri/ci.sh2
-rwxr-xr-xsrc/tools/miri/miri2
-rw-r--r--src/tools/miri/miri-script/Cargo.lock125
-rw-r--r--src/tools/miri/miri-script/Cargo.toml1
-rw-r--r--src/tools/miri/miri-script/src/commands.rs82
-rw-r--r--src/tools/miri/miri-script/src/main.rs2
-rw-r--r--src/tools/miri/rust-version2
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs20
-rw-r--r--src/tools/miri/src/diagnostics.rs16
-rw-r--r--src/tools/miri/src/helpers.rs65
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs67
-rw-r--r--src/tools/miri/src/range_map.rs42
-rw-r--r--src/tools/miri/src/shims/foreign_items.rs15
-rw-r--r--src/tools/miri/src/shims/intrinsics/mod.rs101
-rw-r--r--src/tools/miri/src/shims/intrinsics/simd.rs47
-rw-r--r--src/tools/miri/src/shims/panic.rs19
-rw-r--r--src/tools/miri/src/shims/x86/sse.rs44
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.lock16
-rw-r--r--src/tools/miri/test-cargo-miri/Cargo.toml3
-rwxr-xr-xsrc/tools/miri/test-cargo-miri/run-test.py4
-rw-r--r--src/tools/miri/tests/compiletest.rs13
-rw-r--r--src/tools/miri/tests/fail/alloc/deallocate-twice.stderr12
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr12
-rw-r--r--src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr12
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr7
-rw-r--r--src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr7
-rw-r--r--src/tools/miri/tests/fail/breakpoint.rs2
-rw-r--r--src/tools/miri/tests/fail/breakpoint.stderr4
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr12
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read1.stderr8
-rw-r--r--src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read2.stderr8
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr16
-rw-r--r--src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr16
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs4
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr6
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr27
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr27
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr2
-rw-r--r--src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs7
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs2
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr4
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs6
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr8
-rw-r--r--src/tools/miri/tests/fail/generator-pinned-moved.stderr12
-rw-r--r--src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr7
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr4
-rw-r--r--src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr8
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs6
-rw-r--r--src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr22
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs7
-rw-r--r--src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr22
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.rs3
-rw-r--r--src/tools/miri/tests/fail/panic/double_panic.stderr24
-rw-r--r--src/tools/miri/tests/fail/rc_as_ptr.stderr12
-rw-r--r--src/tools/miri/tests/fail/shims/memchr_null.stderr4
-rw-r--r--src/tools/miri/tests/fail/shims/memcmp_null.stderr4
-rw-r--r--src/tools/miri/tests/fail/shims/memcmp_zero.rs13
-rw-r--r--src/tools/miri/tests/fail/shims/memcmp_zero.stderr15
-rw-r--r--src/tools/miri/tests/fail/shims/memrchr_null.stderr4
-rw-r--r--src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr19
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.rs8
-rw-r--r--src/tools/miri/tests/fail/terminate-terminator.stderr28
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.rs6
-rw-r--r--src/tools/miri/tests/fail/unwind-action-terminate.stderr26
-rw-r--r--src/tools/miri/tests/fail/zst2.stderr12
-rw-r--r--src/tools/miri/tests/fail/zst3.stderr7
-rw-r--r--src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs2
-rw-r--r--src/tools/rust-analyzer/Cargo.lock12
-rw-r--r--src/tools/rust-analyzer/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/fixture.rs4
-rw-r--r--src/tools/rust-analyzer/crates/base-db/src/input.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/attr.rs10
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs7
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs20
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/data.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/db.rs3
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/find_path.rs81
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/generics.rs85
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs11
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/import_map.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs477
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs51
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs27
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs12
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/lib.rs44
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs65
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres.rs72
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs434
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs85
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs80
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs18
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs32
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/primitives.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs82
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/resolver.rs189
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/src.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir-expand/src/lib.rs19
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/builder.rs13
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs53
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/display.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer.rs8
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs21
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs48
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lib.rs17
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/lower.rs121
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir.rs4
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs6
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs31
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs102
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs42
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs52
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/attrs.rs183
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/display.rs68
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/lib.rs68
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/semantics.rs91
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs9
-rw-r--r--src/tools/rust-analyzer/crates/hir/src/symbols.rs40
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs105
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs190
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs21
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs123
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs9
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs37
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs5
-rw-r--r--src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs71
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs87
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context.rs53
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs145
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs54
-rw-r--r--src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs294
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/defs.rs12
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/helpers.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/lib.rs3
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs44
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/search.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs11
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt203
-rw-r--r--src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs16
-rw-r--r--src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs6
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links.rs10
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs56
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/expand_macro.rs47
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/extend_selection.rs29
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_definition.rs54
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs15
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/highlight_related.rs17
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover.rs4
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/hover/tests.rs107
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/moniker.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/navigation_target.rs8
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/references.rs2
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/signature_help.rs32
-rw-r--r--src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs4
-rw-r--r--src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs1
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar.rs4
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs2
-rw-r--r--src/tools/rust-analyzer/crates/parser/src/shortcuts.rs13
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast6
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast15
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast17
-rw-r--r--src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast9
-rw-r--r--src/tools/rust-analyzer/crates/profile/src/stop_watch.rs20
-rw-r--r--src/tools/rust-analyzer/crates/project-model/src/workspace.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs8
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs3
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs13
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs2
-rw-r--r--src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs7
-rw-r--r--src/tools/rust-analyzer/crates/syntax/rust.ungram2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs2
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/make.rs7
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs8
-rw-r--r--src/tools/rust-analyzer/crates/syntax/src/lib.rs12
-rw-r--r--src/tools/rust-analyzer/crates/test-utils/src/fixture.rs2
-rw-r--r--src/tools/rust-analyzer/docs/user/generated_config.adoc15
-rw-r--r--src/tools/rust-analyzer/editors/code/package.json18
-rw-r--r--src/tools/rust-analyzer/editors/code/src/bootstrap.ts2
-rw-r--r--src/tools/rust-analyzer/editors/code/src/commands.ts7
-rw-r--r--src/tools/rust-analyzer/editors/code/src/config.ts33
-rw-r--r--src/tools/rust-analyzer/editors/code/src/ctx.ts18
-rw-r--r--src/tools/rust-analyzer/editors/code/src/main.ts1
-rw-r--r--src/tools/rust-analyzer/editors/code/src/util.ts9
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/Cargo.toml5
-rw-r--r--src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs5
-rw-r--r--src/tools/rust-analyzer/xtask/src/metrics.rs4
-rw-r--r--src/version2
-rw-r--r--tests/codegen/debuginfo-inline-callsite-location.rs26
-rw-r--r--tests/codegen/slice-ref-equality.rs32
-rw-r--r--tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir2
-rw-r--r--tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir2
-rw-r--r--tests/mir-opt/building/custom/terminators.rs4
-rw-r--r--tests/mir-opt/copy-prop/borrowed_local.rs4
-rw-r--r--tests/mir-opt/copy-prop/custom_move_arg.rs4
-rw-r--r--tests/mir-opt/copy-prop/move_projection.rs4
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff11
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff11
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir5
-rw-r--r--tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir5
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff22
-rw-r--r--tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff22
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir5
-rw-r--r--tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir5
-rw-r--r--tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir7
-rw-r--r--tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir3
-rw-r--r--tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir93
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir109
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir109
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir10
-rw-r--r--tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir10
-rw-r--r--tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir234
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir128
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir128
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir15
-rw-r--r--tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir15
-rw-r--r--tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff59
-rw-r--r--tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff9
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff68
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff51
-rw-r--r--tests/mir-opt/reference_prop.rs10
-rw-r--r--tests/run-make/optimization-remarks-dir-pgo/Makefile1
-rw-r--r--tests/run-make/panic-abort-eh_frame/Makefile2
-rw-r--r--tests/run-make/panic-abort-eh_frame/foo.rs24
-rw-r--r--tests/rustdoc-gui/docblock-table.goml16
-rw-r--r--tests/rustdoc-gui/search-form-elements.goml386
-rw-r--r--tests/rustdoc-gui/src/test_docs/lib.rs12
-rw-r--r--tests/rustdoc-gui/warning-block.goml45
-rw-r--r--tests/rustdoc-ui/lints/inline-doc-link.rs13
-rw-r--r--tests/rustdoc-ui/lints/no-redundancy.rs7
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs18
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.fixed158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.rs158
-rw-r--r--tests/rustdoc-ui/lints/redundant_explicit_links.stderr1007
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.rs1
-rw-r--r--tests/rustdoc-ui/unescaped_backticks.stderr128
-rw-r--r--tests/rustdoc/description.rs1
-rw-r--r--tests/rustdoc/intra-doc/basic.rs2
-rw-r--r--tests/rustdoc/intra-doc/generic-params.rs1
-rw-r--r--tests/rustdoc/intra-doc/issue-108459.rs1
-rw-r--r--tests/ui/abi/relocation_model_pic.rs9
-rw-r--r--tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs2
-rw-r--r--tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr16
-rw-r--r--tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs12
-rw-r--r--tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr24
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed13
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.rs2
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr6
-rw-r--r--tests/ui/async-await/deep-futures-are-freeze.rs179
-rw-r--r--tests/ui/async-await/normalize-output-in-signature-deduction.rs19
-rw-r--r--tests/ui/consts/assert-type-intrinsics.stderr6
-rw-r--r--tests/ui/consts/assoc-const-elided-lifetime.rs19
-rw-r--r--tests/ui/consts/assoc-const-elided-lifetime.stderr33
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed2
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.rs2
-rw-r--r--tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr12
-rw-r--r--tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs32
-rw-r--r--tests/ui/inference/str-as-char.fixed1
-rw-r--r--tests/ui/inference/str-as-char.rs1
-rw-r--r--tests/ui/inference/str-as-char.stderr13
-rw-r--r--tests/ui/inline-const/required-const.rs13
-rw-r--r--tests/ui/inline-const/required-const.stderr11
-rw-r--r--tests/ui/macros/macro-interpolation.rs4
-rw-r--r--tests/ui/macros/macro-interpolation.stderr16
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs14
-rw-r--r--tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr19
-rw-r--r--tests/ui/mir/debug-ref-undef.rs57
-rw-r--r--tests/ui/or-patterns/missing-bindings.stderr68
-rw-r--r--tests/ui/parser/trait-object-delimiters.rs4
-rw-r--r--tests/ui/parser/trait-object-delimiters.stderr12
-rw-r--r--tests/ui/resolve/resolve-inconsistent-names.stderr18
-rw-r--r--tests/ui/span/issue-39698.stderr20
-rw-r--r--tests/ui/suggestions/copied-and-cloned.fixed18
-rw-r--r--tests/ui/suggestions/copied-and-cloned.rs16
-rw-r--r--tests/ui/suggestions/copied-and-cloned.stderr37
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs17
-rw-r--r--tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr38
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs73
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs75
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr9
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr37
-rw-r--r--tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs21
-rw-r--r--tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs10
-rw-r--r--tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr6
-rw-r--r--tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr6
-rw-r--r--triagebot.toml7
516 files changed, 10588 insertions, 4100 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index b55ab229811..3680136d89f 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -323,17 +323,6 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
             os: macos-13
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: "./x.py dist bootstrap --include-default-paths"
-              RUST_CONFIGURE_ARGS: "--enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false"
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              SELECT_XCODE: /Applications/Xcode_13.4.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            os: macos-13
           - name: x86_64-apple-1
             env:
               SCRIPT: "./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps"
diff --git a/Cargo.lock b/Cargo.lock
index 8d707067bb9..4ebbb16442e 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -167,9 +167,9 @@ dependencies = [
 
 [[package]]
 name = "anyhow"
-version = "1.0.71"
+version = "1.0.75"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
+checksum = "a4668cab20f66d8d020e1fbc0ebe47217433c1b6c8f2040faf858554e394ace6"
 dependencies = [
  "backtrace",
 ]
@@ -218,7 +218,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -500,7 +500,7 @@ dependencies = [
  "heck",
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -525,7 +525,7 @@ dependencies = [
  "regex",
  "rustc_tools_util",
  "serde",
- "syn 2.0.27",
+ "syn 2.0.29",
  "tempfile",
  "termize",
  "tester",
@@ -849,7 +849,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "strsim",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -860,7 +860,7 @@ checksum = "836a9bbc7ad63342d6d6e7b815ccab164bc77a2d95d84bc3117a8c0d5c98e2d5"
 dependencies = [
  "darling_core",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -875,7 +875,7 @@ version = "0.1.73"
 dependencies = [
  "itertools",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -911,7 +911,7 @@ dependencies = [
  "darling",
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -988,7 +988,7 @@ checksum = "487585f4d0c6655fe74905e2504d8ad6908e4db67f744eb140876906c2f3175d"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -1354,7 +1354,7 @@ checksum = "89ca545a94061b6365f2c7355b4b32bd20df3ff95f02da9329b34ccc3bd6ee72"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2334,6 +2334,7 @@ dependencies = [
  "rand",
  "regex",
  "rustc_version",
+ "serde",
  "smallvec",
  "ui_test",
 ]
@@ -2503,7 +2504,7 @@ checksum = "a948666b637a0f465e8564c73e89d4dde00d72d4d473cc972f390fc3dcee7d9c"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -2691,7 +2692,7 @@ dependencies = [
  "pest_meta",
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -3636,7 +3637,7 @@ dependencies = [
  "fluent-syntax",
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
  "unic-langid",
 ]
 
@@ -3906,7 +3907,7 @@ version = "0.1.0"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
  "synstructure 0.13.0",
 ]
 
@@ -4514,7 +4515,7 @@ dependencies = [
  "proc-macro2",
  "quote",
  "serde",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4666,22 +4667,22 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.164"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "9e8c8cf938e98f769bc164923b06dce91cea1751522f46f8466461af04c9027d"
+checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.164"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d9735b638ccc51c28bf6914d90a2e9725b377144fc612c49a611fddd1b631d68"
+checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -4962,9 +4963,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.27"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b60f673f44a8255b9c8c657daf66a596d435f2da81a555b06dc644d080ba45e0"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -4991,7 +4992,7 @@ checksum = "285ba80e733fac80aa4270fbcdf83772a79b80aa35c97075320abfee4a915b06"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
  "unicode-xid",
 ]
 
@@ -5126,9 +5127,9 @@ checksum = "aac81b6fd6beb5884b0cf3321b8117e6e5d47ecb6fc89f414cfdcca8b2fe2dd8"
 
 [[package]]
 name = "thiserror"
-version = "1.0.40"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "978c9a314bd8dc99be594bc3c175faaa9794be04a5a5e153caba6915336cebac"
+checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
 dependencies = [
  "thiserror-impl",
 ]
@@ -5155,13 +5156,13 @@ dependencies = [
 
 [[package]]
 name = "thiserror-impl"
-version = "1.0.40"
+version = "1.0.47"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f9456a42c5b0d803c8cd86e73dd7cc9edd429499f37a3550d286d5e86720569f"
+checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -5382,7 +5383,7 @@ checksum = "5f4f31f56159e98206da9efd823404b79b6ef3143b4a7ab76e67b1751b25a4ab"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
 ]
 
 [[package]]
@@ -5777,7 +5778,7 @@ dependencies = [
  "once_cell",
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
  "wasm-bindgen-shared",
 ]
 
@@ -5811,7 +5812,7 @@ checksum = "54681b18a46765f095758388f2d0cf16eb8d4169b639ab575a8f5693af210c7b"
 dependencies = [
  "proc-macro2",
  "quote",
- "syn 2.0.27",
+ "syn 2.0.29",
  "wasm-bindgen-backend",
  "wasm-bindgen-shared",
 ]
diff --git a/RELEASES.md b/RELEASES.md
index e8c79c573f9..242b1c2eefd 100644
--- a/RELEASES.md
+++ b/RELEASES.md
@@ -1,3 +1,108 @@
+Version 1.72.0 (2023-08-24)
+==========================
+
+<a id="1.72.0-Language"></a>
+
+Language
+--------
+
+- [Replace const eval limit by a lint and add an exponential backoff warning](https://github.com/rust-lang/rust/pull/103877/)
+- [expand: Change how `#![cfg(FALSE)]` behaves on crate root](https://github.com/rust-lang/rust/pull/110141/)
+- [Stabilize inline asm for LoongArch64](https://github.com/rust-lang/rust/pull/111235/)
+- [Uplift `clippy::undropped_manually_drops` lint](https://github.com/rust-lang/rust/pull/111530/)
+- [Uplift `clippy::invalid_utf8_in_unchecked` lint](https://github.com/rust-lang/rust/pull/111543/)
+- [Uplift `clippy::cast_ref_to_mut` lint](https://github.com/rust-lang/rust/pull/111567/)
+- [Uplift `clippy::cmp_nan` lint](https://github.com/rust-lang/rust/pull/111818/)
+- [resolve: Remove artificial import ambiguity errors](https://github.com/rust-lang/rust/pull/112086/)
+- [Don't require associated types with Self: Sized bounds in `dyn Trait` objects](https://github.com/rust-lang/rust/pull/112319/)
+
+<a id="1.72.0-Compiler"></a>
+
+Compiler
+--------
+
+- [Remember names of `cfg`-ed out items to mention them in diagnostics](https://github.com/rust-lang/rust/pull/109005/)
+- [Support for native WASM exceptions](https://github.com/rust-lang/rust/pull/111322/)
+- [Add support for NetBSD/aarch64-be (big-endian arm64).](https://github.com/rust-lang/rust/pull/111326/)
+- [Write to stdout if `-` is given as output file](https://github.com/rust-lang/rust/pull/111626/)
+- [Force all native libraries to be statically linked when linking a static binary](https://github.com/rust-lang/rust/pull/111698/)
+- [Add Tier 3 support for `loongarch64-unknown-none*`](https://github.com/rust-lang/rust/pull/112310/)
+- [Prevent `.eh_frame` from being emitted for `-C panic=abort`](https://github.com/rust-lang/rust/pull/112403/)
+- [Support 128-bit enum variant in debuginfo codegen](https://github.com/rust-lang/rust/pull/112474/)
+- [compiler: update solaris/illumos to enable tsan support.](https://github.com/rust-lang/rust/pull/112039/)
+
+Refer to Rust's [platform support page][platform-support-doc]
+for more information on Rust's tiered platform support.
+
+<a id="1.72.0-Libraries"></a>
+
+Libraries
+---------
+
+- [Document memory orderings of `thread::{park, unpark}`](https://github.com/rust-lang/rust/pull/99587/)
+- [io: soften ‘at most one write attempt’ requirement in io::Write::write](https://github.com/rust-lang/rust/pull/107200/)
+- [Specify behavior of HashSet::insert](https://github.com/rust-lang/rust/pull/107619/)
+- [Relax implicit `T: Sized` bounds on `BufReader<T>`, `BufWriter<T>` and `LineWriter<T>`](https://github.com/rust-lang/rust/pull/111074/)
+- [Update runtime guarantee for `select_nth_unstable`](https://github.com/rust-lang/rust/pull/111974/)
+- [Return `Ok` on kill if process has already exited](https://github.com/rust-lang/rust/pull/112594/)
+- [Implement PartialOrd for `Vec`s over different allocators](https://github.com/rust-lang/rust/pull/112632/)
+- [Use 128 bits for TypeId hash](https://github.com/rust-lang/rust/pull/109953/)
+- [Don't drain-on-drop in DrainFilter impls of various collections.](https://github.com/rust-lang/rust/pull/104455/)
+- [Make `{Arc,Rc,Weak}::ptr_eq` ignore pointer metadata](https://github.com/rust-lang/rust/pull/106450/)
+
+<a id="1.72.0-Rustdoc"></a>
+
+Rustdoc
+-------
+
+- [Allow whitespace as path separator like double colon](https://github.com/rust-lang/rust/pull/108537/)
+- [Add search result item types after their name](https://github.com/rust-lang/rust/pull/110688/)
+- [Search for slices and arrays by type with `[]`](https://github.com/rust-lang/rust/pull/111958/)
+- [Clean up type unification and "unboxing"](https://github.com/rust-lang/rust/pull/112233/)
+
+<a id="1.72.0-Stabilized-APIs"></a>
+
+Stabilized APIs
+---------------
+
+- [`impl<T: Send> Sync for mpsc::Sender<T>`](https://doc.rust-lang.org/stable/std/sync/mpsc/struct.Sender.html#impl-Sync-for-Sender%3CT%3E)
+- [`impl TryFrom<&OsStr> for &str`](https://doc.rust-lang.org/stable/std/primitive.str.html#impl-TryFrom%3C%26'a+OsStr%3E-for-%26'a+str)
+- [`String::leak`](https://doc.rust-lang.org/stable/alloc/string/struct.String.html#method.leak)
+
+These APIs are now stable in const contexts:
+
+- [`CStr::from_bytes_with_nul`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.from_bytes_with_nul)
+- [`CStr::to_bytes`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_bytes)
+- [`CStr::to_bytes_with_nul`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_bytes_with_nul)
+- [`CStr::to_str`](https://doc.rust-lang.org/stable/std/ffi/struct.CStr.html#method.to_str)
+
+<a id="1.72.0-Cargo"></a>
+
+Cargo
+-----
+
+- Enable `-Zdoctest-in-workspace` by default. When running each documentation
+  test, the working directory is set to the root directory of the package the
+  test belongs to.
+  [docs](https://doc.rust-lang.org/nightly/cargo/commands/cargo-test.html#working-directory-of-tests)
+  [#12221](https://github.com/rust-lang/cargo/pull/12221)
+  [#12288](https://github.com/rust-lang/cargo/pull/12288)
+- Add support of the "default" keyword to reset previously set `build.jobs`
+  parallelism back to the default.
+  [#12222](https://github.com/rust-lang/cargo/pull/12222)
+
+<a id="1.72.0-Compatibility-Notes"></a>
+
+Compatibility Notes
+-------------------
+
+- [Alter `Display` for `Ipv6Addr` for IPv4-compatible addresses](https://github.com/rust-lang/rust/pull/112606/)
+- Cargo changed feature name validation check to a hard error. The warning was
+  added in Rust 1.49. These extended characters aren't allowed on crates.io, so
+  this should only impact users of other registries, or people who don't publish
+  to a registry.
+  [#12291](https://github.com/rust-lang/cargo/pull/12291)
+
 Version 1.71.0 (2023-07-13)
 ==========================
 
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index bae3979fbf9..48e9b180b74 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -13,6 +13,7 @@ use crate::tokenstream::*;
 use crate::{ast::*, StaticItem};
 
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_data_structures::sync::Lrc;
 use rustc_span::source_map::Spanned;
 use rustc_span::symbol::Ident;
@@ -1369,7 +1370,7 @@ pub fn noop_visit_expr<T: MutVisitor>(
         ExprKind::If(cond, tr, fl) => {
             vis.visit_expr(cond);
             vis.visit_block(tr);
-            visit_opt(fl, |fl| vis.visit_expr(fl));
+            visit_opt(fl, |fl| ensure_sufficient_stack(|| vis.visit_expr(fl)));
         }
         ExprKind::While(cond, body, label) => {
             vis.visit_expr(cond);
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 068b255e9f2..58ce73047bc 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -150,6 +150,8 @@ pub fn print_crate<'a>(
 /// and also addresses some specific regressions described in #63896 and #73345.
 fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
     if let TokenTree::Token(token, _) = prev {
+        // No space after these tokens, e.g. `x.y`, `$e`
+        // (The carets point to `prev`.)       ^     ^
         if matches!(token.kind, token::Dot | token::Dollar) {
             return false;
         }
@@ -158,10 +160,19 @@ fn tt_prepend_space(tt: &TokenTree, prev: &TokenTree) -> bool {
         }
     }
     match tt {
+        // No space before these tokens, e.g. `foo,`, `println!`, `x.y`
+        // (The carets point to `token`.)         ^           ^     ^
+        //
+        // FIXME: having `Not` here works well for macro invocations like
+        // `println!()`, but is bad when `!` means "logical not" or "the never
+        // type", where the lack of space causes ugliness like this:
+        // `Fn() ->!`, `x =! y`, `if! x { f(); }`.
         TokenTree::Token(token, _) => !matches!(token.kind, token::Comma | token::Not | token::Dot),
+        // No space before parentheses if preceded by these tokens, e.g. `foo(...)`
         TokenTree::Delimited(_, Delimiter::Parenthesis, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Ident(..), .. }, _))
         }
+        // No space before brackets if preceded by these tokens, e.g. `#[...]`
         TokenTree::Delimited(_, Delimiter::Bracket, _) => {
             !matches!(prev, TokenTree::Token(Token { kind: token::Pound, .. }, _))
         }
diff --git a/compiler/rustc_borrowck/src/consumers.rs b/compiler/rustc_borrowck/src/consumers.rs
index d257145373f..becfa535a59 100644
--- a/compiler/rustc_borrowck/src/consumers.rs
+++ b/compiler/rustc_borrowck/src/consumers.rs
@@ -30,7 +30,7 @@ pub use super::{
 /// will be retrieved.
 #[derive(Debug, Copy, Clone)]
 pub enum ConsumerOptions {
-    /// Retrieve the [`Body`] along with the [`BorrowSet`](super::borrow_set::BorrowSet)
+    /// Retrieve the [`Body`] along with the [`BorrowSet`]
     /// and [`RegionInferenceContext`]. If you would like the body only, use
     /// [`TyCtxt::mir_promoted`].
     ///
diff --git a/compiler/rustc_borrowck/src/invalidation.rs b/compiler/rustc_borrowck/src/invalidation.rs
index df5e383ad40..d4c42a75874 100644
--- a/compiler/rustc_borrowck/src/invalidation.rs
+++ b/compiler/rustc_borrowck/src/invalidation.rs
@@ -159,7 +159,9 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
 
                 self.mutate_place(location, *resume_arg, Deep);
             }
-            TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
+            TerminatorKind::UnwindResume
+            | TerminatorKind::Return
+            | TerminatorKind::GeneratorDrop => {
                 // Invalidate all borrows of local places
                 let borrow_set = self.borrow_set;
                 let start = self.location_table.start_index(location);
@@ -200,7 +202,7 @@ impl<'cx, 'tcx> Visitor<'tcx> for InvalidationGenerator<'cx, 'tcx> {
                 }
             }
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
             | TerminatorKind::FalseUnwind { real_target: _, unwind: _ } => {
diff --git a/compiler/rustc_borrowck/src/lib.rs b/compiler/rustc_borrowck/src/lib.rs
index efe525c224d..ef2788efbcf 100644
--- a/compiler/rustc_borrowck/src/lib.rs
+++ b/compiler/rustc_borrowck/src/lib.rs
@@ -770,9 +770,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
             }
 
             TerminatorKind::Goto { target: _ }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Unreachable
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::FalseEdge { real_target: _, imaginary_target: _ }
@@ -803,7 +803,9 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                 }
             }
 
-            TerminatorKind::Resume | TerminatorKind::Return | TerminatorKind::GeneratorDrop => {
+            TerminatorKind::UnwindResume
+            | TerminatorKind::Return
+            | TerminatorKind::GeneratorDrop => {
                 // Returning from the function implicitly kills storage for all locals and statics.
                 // Often, the storage will already have been killed by an explicit
                 // StorageDead, but we don't always emit those (notably on unwind paths),
@@ -815,7 +817,7 @@ impl<'cx, 'tcx, R> rustc_mir_dataflow::ResultsVisitor<'cx, 'tcx, R> for MirBorro
                 }
             }
 
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index 50d875dfae9..d91a3d94045 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -1333,8 +1333,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         debug!("terminator kind: {:?}", term.kind);
         match &term.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
@@ -1608,12 +1608,12 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.assert_iscleanup(body, block_data, *target, is_cleanup);
                 }
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "resume on non-cleanup block!")
                 }
             }
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 if !is_cleanup {
                     span_mirbug!(self, block_data, "abort on non-cleanup block!")
                 }
diff --git a/compiler/rustc_codegen_cranelift/src/base.rs b/compiler/rustc_codegen_cranelift/src/base.rs
index 522dd7189fe..ed371a04c53 100644
--- a/compiler/rustc_codegen_cranelift/src/base.rs
+++ b/compiler/rustc_codegen_cranelift/src/base.rs
@@ -474,10 +474,10 @@ fn codegen_fn_body(fx: &mut FunctionCx<'_, '_, '_>, start_block: Block) {
                     *destination,
                 );
             }
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 codegen_panic_cannot_unwind(fx, source_info);
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 // FIXME implement unwinding
                 fx.bcx.ins().trap(TrapCode::UnreachableCodeReached);
             }
diff --git a/compiler/rustc_codegen_cranelift/src/constant.rs b/compiler/rustc_codegen_cranelift/src/constant.rs
index c3153574295..7db5f79eead 100644
--- a/compiler/rustc_codegen_cranelift/src/constant.rs
+++ b/compiler/rustc_codegen_cranelift/src/constant.rs
@@ -550,8 +550,8 @@ pub(crate) fn mir_operand_get_const_val<'tcx>(
                 match &bb_data.terminator().kind {
                     TerminatorKind::Goto { .. }
                     | TerminatorKind::SwitchInt { .. }
-                    | TerminatorKind::Resume
-                    | TerminatorKind::Terminate
+                    | TerminatorKind::UnwindResume
+                    | TerminatorKind::UnwindTerminate
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
                     | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_codegen_gcc/src/debuginfo.rs b/compiler/rustc_codegen_gcc/src/debuginfo.rs
index a81585d4128..d1bfd833cd8 100644
--- a/compiler/rustc_codegen_gcc/src/debuginfo.rs
+++ b/compiler/rustc_codegen_gcc/src/debuginfo.rs
@@ -55,7 +55,7 @@ impl<'gcc, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'gcc, 'tcx> {
         _fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         _llfn: RValue<'gcc>,
         _mir: &mir::Body<'tcx>,
-    ) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>> {
+    ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>> {
         // TODO(antoyo)
         None
     }
diff --git a/compiler/rustc_codegen_llvm/src/attributes.rs b/compiler/rustc_codegen_llvm/src/attributes.rs
index 4c9094bf1f5..b6c01545f30 100644
--- a/compiler/rustc_codegen_llvm/src/attributes.rs
+++ b/compiler/rustc_codegen_llvm/src/attributes.rs
@@ -128,7 +128,10 @@ fn instrument_function_attr<'ll>(cx: &CodegenCx<'ll, '_>) -> SmallVec<[&'ll Attr
 
         // The function name varies on platforms.
         // See test/CodeGen/mcount.c in clang.
-        let mcount_name = cx.sess().target.mcount.as_ref();
+        let mcount_name = match &cx.sess().target.llvm_mcount_intrinsic {
+            Some(llvm_mcount_intrinsic) => llvm_mcount_intrinsic.as_ref(),
+            None => cx.sess().target.mcount.as_ref(),
+        };
 
         attrs.push(llvm::CreateAttrStringValue(
             cx.llcx,
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
index d174a3593b9..7a68c291aa5 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/create_scope_map.rs
@@ -20,7 +20,7 @@ pub fn compute_mir_scopes<'ll, 'tcx>(
     cx: &CodegenCx<'ll, 'tcx>,
     instance: Instance<'tcx>,
     mir: &Body<'tcx>,
-    debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
+    debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>,
 ) {
     // Find all scopes with variables defined in them.
     let variables = if cx.sess().opts.debuginfo == DebugInfo::Full {
@@ -51,7 +51,7 @@ fn make_mir_scope<'ll, 'tcx>(
     instance: Instance<'tcx>,
     mir: &Body<'tcx>,
     variables: &Option<BitSet<SourceScope>>,
-    debug_context: &mut FunctionDebugContext<&'ll DIScope, &'ll DILocation>,
+    debug_context: &mut FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>,
     instantiated: &mut BitSet<SourceScope>,
     scope: SourceScope,
 ) {
@@ -84,7 +84,6 @@ fn make_mir_scope<'ll, 'tcx>(
     }
 
     let loc = cx.lookup_debug_loc(scope_data.span.lo());
-    let file_metadata = file_metadata(cx, &loc.file);
 
     let dbg_scope = match scope_data.inlined {
         Some((callee, _)) => {
@@ -95,18 +94,26 @@ fn make_mir_scope<'ll, 'tcx>(
                 ty::ParamEnv::reveal_all(),
                 ty::EarlyBinder::bind(callee),
             );
-            let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
-            cx.dbg_scope_fn(callee, callee_fn_abi, None)
+            debug_context.inlined_function_scopes.entry(callee).or_insert_with(|| {
+                let callee_fn_abi = cx.fn_abi_of_instance(callee, ty::List::empty());
+                cx.dbg_scope_fn(callee, callee_fn_abi, None)
+            })
+        }
+        None => {
+            let file_metadata = file_metadata(cx, &loc.file);
+            debug_context
+                .lexical_blocks
+                .entry((parent_scope.dbg_scope, loc.line, loc.col, file_metadata))
+                .or_insert_with(|| unsafe {
+                    llvm::LLVMRustDIBuilderCreateLexicalBlock(
+                        DIB(cx),
+                        parent_scope.dbg_scope,
+                        file_metadata,
+                        loc.line,
+                        loc.col,
+                    )
+                })
         }
-        None => unsafe {
-            llvm::LLVMRustDIBuilderCreateLexicalBlock(
-                DIB(cx),
-                parent_scope.dbg_scope,
-                file_metadata,
-                loc.line,
-                loc.col,
-            )
-        },
     };
 
     let inlined_at = scope_data.inlined.map(|(_, callsite_span)| {
diff --git a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
index 40714a0afe9..9cdeae2841b 100644
--- a/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
+++ b/compiler/rustc_codegen_llvm/src/debuginfo/mod.rs
@@ -5,7 +5,7 @@ use rustc_codegen_ssa::mir::debuginfo::VariableKind::*;
 use self::metadata::{file_metadata, type_di_node};
 use self::metadata::{UNKNOWN_COLUMN_NUMBER, UNKNOWN_LINE_NUMBER};
 use self::namespace::mangled_name_of_instance;
-use self::utils::{create_DIArray, is_node_local_to_unit, DIB};
+use self::utils::{create_DIArray, debug_context, is_node_local_to_unit, DIB};
 
 use crate::abi::FnAbi;
 use crate::builder::Builder;
@@ -67,6 +67,8 @@ pub struct CodegenUnitDebugContext<'ll, 'tcx> {
     type_map: metadata::TypeMap<'ll, 'tcx>,
     namespace_map: RefCell<DefIdMap<&'ll DIScope>>,
     recursion_marker_type: OnceCell<&'ll DIType>,
+    /// Maps a variable (name, scope, kind (argument or local), span) to its debug information.
+    variables: RefCell<FxHashMap<(Symbol, &'ll DIScope, VariableKind, Span), &'ll DIVariable>>,
 }
 
 impl Drop for CodegenUnitDebugContext<'_, '_> {
@@ -91,6 +93,7 @@ impl<'ll, 'tcx> CodegenUnitDebugContext<'ll, 'tcx> {
             type_map: Default::default(),
             namespace_map: RefCell::new(Default::default()),
             recursion_marker_type: OnceCell::new(),
+            variables: RefCell::new(Default::default()),
         }
     }
 
@@ -292,7 +295,7 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         llfn: &'ll Value,
         mir: &mir::Body<'tcx>,
-    ) -> Option<FunctionDebugContext<&'ll DIScope, &'ll DILocation>> {
+    ) -> Option<FunctionDebugContext<'tcx, &'ll DIScope, &'ll DILocation>> {
         if self.sess().opts.debuginfo == DebugInfo::None {
             return None;
         }
@@ -304,8 +307,11 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
             file_start_pos: BytePos(0),
             file_end_pos: BytePos(0),
         };
-        let mut fn_debug_context =
-            FunctionDebugContext { scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes) };
+        let mut fn_debug_context = FunctionDebugContext {
+            scopes: IndexVec::from_elem(empty_scope, &mir.source_scopes),
+            inlined_function_scopes: Default::default(),
+            lexical_blocks: Default::default(),
+        };
 
         // Fill in all the scopes, with the information from the MIR body.
         compute_mir_scopes(self, instance, mir, &mut fn_debug_context);
@@ -606,33 +612,39 @@ impl<'ll, 'tcx> DebugInfoMethods<'tcx> for CodegenCx<'ll, 'tcx> {
         variable_kind: VariableKind,
         span: Span,
     ) -> &'ll DIVariable {
-        let loc = self.lookup_debug_loc(span.lo());
-        let file_metadata = file_metadata(self, &loc.file);
-
-        let type_metadata = type_di_node(self, variable_type);
-
-        let (argument_index, dwarf_tag) = match variable_kind {
-            ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
-            LocalVariable => (0, DW_TAG_auto_variable),
-        };
-        let align = self.align_of(variable_type);
-
-        let name = variable_name.as_str();
-        unsafe {
-            llvm::LLVMRustDIBuilderCreateVariable(
-                DIB(self),
-                dwarf_tag,
-                scope_metadata,
-                name.as_ptr().cast(),
-                name.len(),
-                file_metadata,
-                loc.line,
-                type_metadata,
-                true,
-                DIFlags::FlagZero,
-                argument_index,
-                align.bytes() as u32,
-            )
-        }
+        debug_context(self)
+            .variables
+            .borrow_mut()
+            .entry((variable_name, scope_metadata, variable_kind, span))
+            .or_insert_with(|| {
+                let loc = self.lookup_debug_loc(span.lo());
+                let file_metadata = file_metadata(self, &loc.file);
+
+                let type_metadata = type_di_node(self, variable_type);
+
+                let (argument_index, dwarf_tag) = match variable_kind {
+                    ArgumentVariable(index) => (index as c_uint, DW_TAG_arg_variable),
+                    LocalVariable => (0, DW_TAG_auto_variable),
+                };
+                let align = self.align_of(variable_type);
+
+                let name = variable_name.as_str();
+                unsafe {
+                    llvm::LLVMRustDIBuilderCreateVariable(
+                        DIB(self),
+                        dwarf_tag,
+                        scope_metadata,
+                        name.as_ptr().cast(),
+                        name.len(),
+                        file_metadata,
+                        loc.line,
+                        type_metadata,
+                        true,
+                        DIFlags::FlagZero,
+                        argument_index,
+                        align.bytes() as u32,
+                    )
+                }
+            })
     }
 }
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 0be84c9fa83..4c854740753 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -16,6 +16,7 @@ use rustc_metadata::fs::METADATA_FILENAME;
 use rustc_metadata::EncodedMetadata;
 use rustc_session::cstore::MetadataLoader;
 use rustc_session::Session;
+use rustc_span::sym;
 use rustc_target::abi::Endian;
 use rustc_target::spec::{ef_avr_arch, RelocModel, Target};
 
@@ -272,35 +273,38 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
         Architecture::Riscv32 | Architecture::Riscv64 => {
             // Source: https://github.com/riscv-non-isa/riscv-elf-psabi-doc/blob/079772828bd10933d34121117a222b4cc0ee2200/riscv-elf.adoc
             let mut e_flags: u32 = 0x0;
-            let features = &sess.target.options.features;
+
             // Check if compressed is enabled
-            if features.contains("+c") {
+            // `unstable_target_features` is used here because "c" is gated behind riscv_target_feature.
+            if sess.unstable_target_features.contains(&sym::c) {
                 e_flags |= elf::EF_RISCV_RVC;
             }
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE;
-            } else {
-                e_flags |= elf::EF_RISCV_FLOAT_ABI_SOFT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `RISCVELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "" | "ilp32" | "lp64" => (),
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_RISCV_FLOAT_ABI_SINGLE,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_RISCV_FLOAT_ABI_DOUBLE,
+                "ilp32e" => e_flags |= elf::EF_RISCV_RVE,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::LoongArch64 => {
             // Source: https://github.com/loongson/la-abi-specs/blob/release/laelf.adoc#e_flags-identifies-abi-type-and-version
             let mut e_flags: u32 = elf::EF_LARCH_OBJABI_V1;
-            let features = &sess.target.options.features;
 
-            // Select the appropriate floating-point ABI
-            if features.contains("+d") {
-                e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT;
-            } else if features.contains("+f") {
-                e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT;
-            } else {
-                e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT;
+            // Set the appropriate flag based on ABI
+            // This needs to match LLVM `LoongArchELFStreamer.cpp`
+            match &*sess.target.llvm_abiname {
+                "ilp32s" | "lp64s" => e_flags |= elf::EF_LARCH_ABI_SOFT_FLOAT,
+                "ilp32f" | "lp64f" => e_flags |= elf::EF_LARCH_ABI_SINGLE_FLOAT,
+                "ilp32d" | "lp64d" => e_flags |= elf::EF_LARCH_ABI_DOUBLE_FLOAT,
+                _ => bug!("unknown RISC-V ABI name"),
             }
+
             e_flags
         }
         Architecture::Avr => {
diff --git a/compiler/rustc_codegen_ssa/src/mir/analyze.rs b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
index 22c1f05974d..3f5b46333d9 100644
--- a/compiler/rustc_codegen_ssa/src/mir/analyze.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/analyze.rs
@@ -284,8 +284,8 @@ pub fn cleanup_kinds(mir: &mir::Body<'_>) -> IndexVec<mir::BasicBlock, CleanupKi
         for (bb, data) in mir.basic_blocks.iter_enumerated() {
             match data.terminator().kind {
                 TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
-                | TerminatorKind::Terminate
+                | TerminatorKind::UnwindResume
+                | TerminatorKind::UnwindTerminate
                 | TerminatorKind::Return
                 | TerminatorKind::GeneratorDrop
                 | TerminatorKind::Unreachable
diff --git a/compiler/rustc_codegen_ssa/src/mir/block.rs b/compiler/rustc_codegen_ssa/src/mir/block.rs
index 4f26383ed05..19228183462 100644
--- a/compiler/rustc_codegen_ssa/src/mir/block.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/block.rs
@@ -1224,12 +1224,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
         self.set_debug_loc(bx, terminator.source_info);
         match terminator.kind {
-            mir::TerminatorKind::Resume => {
+            mir::TerminatorKind::UnwindResume => {
                 self.codegen_resume_terminator(helper, bx);
                 MergingSucc::False
             }
 
-            mir::TerminatorKind::Terminate => {
+            mir::TerminatorKind::UnwindTerminate => {
                 self.codegen_terminate_terminator(helper, bx, terminator);
                 MergingSucc::False
             }
diff --git a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
index 4167a85ccd5..7df830692d3 100644
--- a/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/debuginfo.rs
@@ -1,10 +1,12 @@
 use crate::traits::*;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_index::IndexVec;
 use rustc_middle::middle::codegen_fn_attrs::CodegenFnAttrFlags;
 use rustc_middle::mir;
 use rustc_middle::ty;
 use rustc_middle::ty::layout::TyAndLayout;
 use rustc_middle::ty::layout::{HasTyCtxt, LayoutOf};
+use rustc_middle::ty::Instance;
 use rustc_middle::ty::Ty;
 use rustc_session::config::DebugInfo;
 use rustc_span::symbol::{kw, Symbol};
@@ -17,11 +19,19 @@ use super::{FunctionCx, LocalRef};
 
 use std::ops::Range;
 
-pub struct FunctionDebugContext<S, L> {
+pub struct FunctionDebugContext<'tcx, S, L> {
+    /// Maps from source code to the corresponding debug info scope.
     pub scopes: IndexVec<mir::SourceScope, DebugScope<S, L>>,
+
+    /// Maps from a given inlined function to its debug info declaration.
+    pub inlined_function_scopes: FxHashMap<Instance<'tcx>, S>,
+
+    /// Maps from a lexical block (parent scope, line, column, file) to its debug info declaration.
+    /// This is particularily useful if the parent scope is an inlined function.
+    pub lexical_blocks: FxHashMap<(S, u32, u32, S), S>,
 }
 
-#[derive(Copy, Clone)]
+#[derive(Copy, Clone, Eq, PartialEq, Hash)]
 pub enum VariableKind {
     ArgumentVariable(usize /*index*/),
     LocalVariable,
@@ -42,9 +52,6 @@ pub struct PerLocalVarDebugInfo<'tcx, D> {
 
     /// `.place.projection` from `mir::VarDebugInfo`.
     pub projection: &'tcx ty::List<mir::PlaceElem<'tcx>>,
-
-    /// `references` from `mir::VarDebugInfo`.
-    pub references: u8,
 }
 
 #[derive(Clone, Copy, Debug)]
@@ -323,7 +330,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     dbg_var,
                     fragment: None,
                     projection: ty::List::empty(),
-                    references: 0,
                 })
             }
         } else {
@@ -399,15 +405,14 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         &self,
         bx: &mut Bx,
         local: mir::Local,
-        mut base: PlaceRef<'tcx, Bx::Value>,
+        base: PlaceRef<'tcx, Bx::Value>,
         var: PerLocalVarDebugInfo<'tcx, Bx::DIVariable>,
     ) {
         let Some(dbg_var) = var.dbg_var else { return };
         let Some(dbg_loc) = self.dbg_loc(var.source_info) else { return };
 
-        let DebugInfoOffset { mut direct_offset, indirect_offsets, result: _ } =
+        let DebugInfoOffset { direct_offset, indirect_offsets, result: _ } =
             calculate_debuginfo_offset(bx, local, &var, base.layout);
-        let mut indirect_offsets = &indirect_offsets[..];
 
         // When targeting MSVC, create extra allocas for arguments instead of pointing multiple
         // dbg_var_addr() calls into the same alloca with offsets. MSVC uses CodeView records
@@ -421,9 +426,12 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             // LLVM can handle simple things but anything more complex than just a direct
             // offset or one indirect offset of 0 is too complex for it to generate CV records
             // correctly.
-            && (direct_offset != Size::ZERO || !matches!(indirect_offsets, [Size::ZERO] | []));
+            && (direct_offset != Size::ZERO || !matches!(&indirect_offsets[..], [Size::ZERO] | []));
+
+        if should_create_individual_allocas {
+            let DebugInfoOffset { direct_offset: _, indirect_offsets: _, result: place } =
+                calculate_debuginfo_offset(bx, local, &var, base);
 
-        let create_alloca = |bx: &mut Bx, place: PlaceRef<'tcx, Bx::Value>, refcount| {
             // Create a variable which will be a pointer to the actual value
             let ptr_ty = Ty::new_ptr(
                 bx.tcx(),
@@ -431,35 +439,16 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             );
             let ptr_layout = bx.layout_of(ptr_ty);
             let alloca = PlaceRef::alloca(bx, ptr_layout);
-            bx.set_var_name(alloca.llval, &format!("{}.ref{}.dbg.spill", var.name, refcount));
+            bx.set_var_name(alloca.llval, &(var.name.to_string() + ".dbg.spill"));
 
             // Write the pointer to the variable
             bx.store(place.llval, alloca.llval, alloca.align);
 
             // Point the debug info to `*alloca` for the current variable
-            alloca
-        };
-
-        if var.references > 0 {
-            base = calculate_debuginfo_offset(bx, local, &var, base).result;
-
-            // Point the debug info to `&...&base == alloca` for the current variable
-            for refcount in 0..var.references {
-                base = create_alloca(bx, base, refcount);
-            }
-
-            direct_offset = Size::ZERO;
-            indirect_offsets = &[];
-        } else if should_create_individual_allocas {
-            let place = calculate_debuginfo_offset(bx, local, &var, base).result;
-
-            // Point the debug info to `*alloca` for the current variable
-            base = create_alloca(bx, place, 0);
-            direct_offset = Size::ZERO;
-            indirect_offsets = &[Size::ZERO];
+            bx.dbg_var_addr(dbg_var, dbg_loc, alloca.llval, Size::ZERO, &[Size::ZERO], None);
+        } else {
+            bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, &indirect_offsets, None);
         }
-
-        bx.dbg_var_addr(dbg_var, dbg_loc, base.llval, direct_offset, indirect_offsets, None);
     }
 
     pub fn debug_introduce_locals(&self, bx: &mut Bx) {
@@ -492,7 +481,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             };
 
             let dbg_var = dbg_scope_and_span.map(|(dbg_scope, _, span)| {
-                let (mut var_ty, var_kind) = match var.value {
+                let (var_ty, var_kind) = match var.value {
                     mir::VarDebugInfoContents::Place(place) => {
                         let var_ty = self.monomorphized_place_ty(place.as_ref());
                         let var_kind = if let Some(arg_index) = var.argument_index
@@ -529,13 +518,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     }
                 };
 
-                for _ in 0..var.references {
-                    var_ty = Ty::new_ptr(
-                        bx.tcx(),
-                        ty::TypeAndMut { mutbl: mir::Mutability::Mut, ty: var_ty },
-                    );
-                }
-
                 self.cx.create_dbg_var(var.name, var_ty, dbg_scope, var_kind, span)
             });
 
@@ -547,7 +529,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                         dbg_var,
                         fragment: None,
                         projection: place.projection,
-                        references: var.references,
                     });
                 }
                 mir::VarDebugInfoContents::Const(c) => {
@@ -601,7 +582,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                                 Some(fragment_start..fragment_start + fragment_layout.size)
                             },
                             projection: place.projection,
-                            references: var.references,
                         });
                     }
                 }
diff --git a/compiler/rustc_codegen_ssa/src/mir/mod.rs b/compiler/rustc_codegen_ssa/src/mir/mod.rs
index 3464f910829..ccf93f208d5 100644
--- a/compiler/rustc_codegen_ssa/src/mir/mod.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/mod.rs
@@ -45,7 +45,7 @@ pub struct FunctionCx<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> {
 
     mir: &'tcx mir::Body<'tcx>,
 
-    debug_context: Option<FunctionDebugContext<Bx::DIScope, Bx::DILocation>>,
+    debug_context: Option<FunctionDebugContext<'tcx, Bx::DIScope, Bx::DILocation>>,
 
     llfn: Bx::Function,
 
diff --git a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
index 63fecaf34fd..4acc0ea076c 100644
--- a/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/debuginfo.rs
@@ -26,7 +26,7 @@ pub trait DebugInfoMethods<'tcx>: BackendTypes {
         fn_abi: &FnAbi<'tcx, Ty<'tcx>>,
         llfn: Self::Function,
         mir: &mir::Body<'tcx>,
-    ) -> Option<FunctionDebugContext<Self::DIScope, Self::DILocation>>;
+    ) -> Option<FunctionDebugContext<'tcx, Self::DIScope, Self::DILocation>>;
 
     // FIXME(eddyb) find a common convention for all of the debuginfo-related
     // names (choose between `dbg`, `debug`, `debuginfo`, `debug_info` etc.).
diff --git a/compiler/rustc_const_eval/src/const_eval/error.rs b/compiler/rustc_const_eval/src/const_eval/error.rs
index d39a7e8a192..f146b93ff0c 100644
--- a/compiler/rustc_const_eval/src/const_eval/error.rs
+++ b/compiler/rustc_const_eval/src/const_eval/error.rs
@@ -18,7 +18,6 @@ pub enum ConstEvalErrKind {
     ModifiedGlobal,
     AssertFailure(AssertKind<ConstInt>),
     Panic { msg: Symbol, line: u32, col: u32, file: Symbol },
-    Abort(String),
 }
 
 impl MachineStopType for ConstEvalErrKind {
@@ -30,7 +29,6 @@ impl MachineStopType for ConstEvalErrKind {
             ModifiedGlobal => const_eval_modified_global,
             Panic { .. } => const_eval_panic,
             AssertFailure(x) => x.diagnostic_message(),
-            Abort(msg) => msg.to_string().into(),
         }
     }
     fn add_args(
@@ -39,7 +37,7 @@ impl MachineStopType for ConstEvalErrKind {
     ) {
         use ConstEvalErrKind::*;
         match *self {
-            ConstAccessesStatic | ModifiedGlobal | Abort(_) => {}
+            ConstAccessesStatic | ModifiedGlobal => {}
             AssertFailure(kind) => kind.add_args(adder),
             Panic { msg, line, col, file } => {
                 adder("msg".into(), msg.into_diagnostic_arg());
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index 032f4be6c99..f16aea6f34b 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -427,52 +427,48 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
 
     fn find_mir_or_eval_fn(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
-        instance: ty::Instance<'tcx>,
+        orig_instance: ty::Instance<'tcx>,
         _abi: CallAbi,
         args: &[FnArg<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction, // unwinding is not supported in consts
     ) -> InterpResult<'tcx, Option<(&'mir mir::Body<'tcx>, ty::Instance<'tcx>)>> {
-        debug!("find_mir_or_eval_fn: {:?}", instance);
+        debug!("find_mir_or_eval_fn: {:?}", orig_instance);
+
+        // Replace some functions.
+        let Some(instance) = ecx.hook_special_const_fn(orig_instance, args, dest, ret)? else {
+            // Call has already been handled.
+            return Ok(None);
+        };
 
         // Only check non-glue functions
         if let ty::InstanceDef::Item(def) = instance.def {
             // Execution might have wandered off into other crates, so we cannot do a stability-
-            // sensitive check here. But we can at least rule out functions that are not const
-            // at all.
-            if !ecx.tcx.is_const_fn_raw(def) {
-                // allow calling functions inside a trait marked with #[const_trait].
-                if !ecx.tcx.is_const_default_method(def) {
-                    // We certainly do *not* want to actually call the fn
-                    // though, so be sure we return here.
-                    throw_unsup_format!("calling non-const function `{}`", instance)
-                }
-            }
-
-            let Some(new_instance) = ecx.hook_special_const_fn(instance, args, dest, ret)? else {
-                return Ok(None);
-            };
-
-            if new_instance != instance {
-                // We call another const fn instead.
-                // However, we return the *original* instance to make backtraces work out
-                // (and we hope this does not confuse the FnAbi checks too much).
-                return Ok(Self::find_mir_or_eval_fn(
-                    ecx,
-                    new_instance,
-                    _abi,
-                    args,
-                    dest,
-                    ret,
-                    _unwind,
-                )?
-                .map(|(body, _instance)| (body, instance)));
+            // sensitive check here. But we can at least rule out functions that are not const at
+            // all. That said, we have to allow calling functions inside a trait marked with
+            // #[const_trait]. These *are* const-checked!
+            // FIXME: why does `is_const_fn_raw` not classify them as const?
+            if (!ecx.tcx.is_const_fn_raw(def) && !ecx.tcx.is_const_default_method(def))
+                || ecx.tcx.has_attr(def, sym::rustc_do_not_const_check)
+            {
+                // We certainly do *not* want to actually call the fn
+                // though, so be sure we return here.
+                throw_unsup_format!("calling non-const function `{}`", instance)
             }
         }
 
         // This is a const fn. Call it.
-        Ok(Some((ecx.load_mir(instance.def, None)?, instance)))
+        // In case of replacement, we return the *original* instance to make backtraces work out
+        // (and we hope this does not confuse the FnAbi checks too much).
+        Ok(Some((ecx.load_mir(instance.def, None)?, orig_instance)))
+    }
+
+    fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
+        let msg = Symbol::intern(msg);
+        let span = ecx.find_closest_untracked_caller_location();
+        let (file, line, col) = ecx.location_triple_for_span(span);
+        Err(ConstEvalErrKind::Panic { msg, file, line, col }.into())
     }
 
     fn call_intrinsic(
@@ -595,10 +591,6 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         Err(ConstEvalErrKind::AssertFailure(err).into())
     }
 
-    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: String) -> InterpResult<'tcx, !> {
-        Err(ConstEvalErrKind::Abort(msg).into())
-    }
-
     fn binary_ptr_op(
         _ecx: &InterpCx<'mir, 'tcx, Self>,
         _bin_op: mir::BinOp,
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 3ac6f07e8b7..61d3de5c405 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -765,7 +765,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             }
             mir::UnwindAction::Terminate => {
                 self.frame_mut().loc = Right(self.frame_mut().body.span);
-                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
+                M::unwind_terminate(self)?;
+                // This might have pushed a new stack frame, or it terminated execution.
+                // Either way, `loc` will not be updated.
+                return Ok(());
             }
         };
         Ok(())
@@ -865,6 +868,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     panic!("encountered StackPopCleanup::Root when unwinding!")
                 }
             };
+            // This must be the very last thing that happens, since it can in fact push a new stack frame.
             self.unwind_to_block(unwind)
         } else {
             // Follow the normal return edge.
diff --git a/compiler/rustc_const_eval/src/interpret/intrinsics.rs b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
index f22cd919c36..d6ca6fe73a6 100644
--- a/compiler/rustc_const_eval/src/interpret/intrinsics.rs
+++ b/compiler/rustc_const_eval/src/interpret/intrinsics.rs
@@ -125,15 +125,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     ) -> InterpResult<'tcx, bool> {
         let instance_args = instance.args;
         let intrinsic_name = self.tcx.item_name(instance.def_id());
-
-        // First handle intrinsics without return place.
-        let ret = match ret {
-            None => match intrinsic_name {
-                sym::abort => M::abort(self, "the program aborted execution".to_owned())?,
-                // Unsupported diverging intrinsic.
-                _ => return Ok(false),
-            },
-            Some(p) => p,
+        let Some(ret) = ret else {
+            // We don't support any intrinsic without return place.
+            return Ok(false);
         };
 
         match intrinsic_name {
@@ -410,7 +404,9 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         ValidityRequirement::Uninit => bug!("assert_uninit_valid doesn't exist"),
                     };
 
-                    M::abort(self, msg)?;
+                    M::panic_nounwind(self, &msg)?;
+                    // Skip the `go_to_block` at the end.
+                    return Ok(true);
                 }
             }
             sym::simd_insert => {
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index e101785b6e2..d3c73b896c0 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -218,10 +218,11 @@ pub trait Machine<'mir, 'tcx: 'mir>: Sized {
         unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx>;
 
-    /// Called to abort evaluation.
-    fn abort(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: String) -> InterpResult<'tcx, !> {
-        throw_unsup_format!("aborting execution is not supported")
-    }
+    /// Called to trigger a non-unwinding panic.
+    fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx>;
+
+    /// Called when unwinding reached a state where execution should be terminated.
+    fn unwind_terminate(_ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx>;
 
     /// Called for all binary operations where the LHS has pointer type.
     ///
@@ -500,6 +501,11 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
     }
 
     #[inline(always)]
+    fn unwind_terminate(_ecx: &mut InterpCx<$mir, $tcx, Self>) -> InterpResult<$tcx> {
+        unreachable!("unwinding cannot happen during compile-time evaluation")
+    }
+
+    #[inline(always)]
     fn call_extra_fn(
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
         fn_val: !,
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 3c03172bbef..b2ebcceceb3 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -196,15 +196,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
             }
 
-            Terminate => {
-                // FIXME: maybe should call `panic_no_unwind` lang item instead.
-                M::abort(self, "panic in a function that cannot unwind".to_owned())?;
+            UnwindTerminate => {
+                M::unwind_terminate(self)?;
             }
 
             // When we encounter Resume, we've finished unwinding
             // cleanup for the current stack frame. We pop it in order
             // to continue unwinding the next frame
-            Resume => {
+            UnwindResume => {
                 trace!("unwinding: resuming from cleanup");
                 // By definition, a Resume terminator means
                 // that we're unwinding
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 fae047bff9e..e67098a3ac3 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -1037,7 +1037,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
                 self.check_op(ops::Generator(hir::GeneratorKind::Gen))
             }
 
-            TerminatorKind::Terminate => {
+            TerminatorKind::UnwindTerminate => {
                 // Cleanup blocks are skipped for const checking (see `visit_basic_block_data`).
                 span_bug!(self.span, "`Terminate` terminator outside of cleanup block")
             }
@@ -1046,7 +1046,7 @@ impl<'tcx> Visitor<'tcx> for Checker<'_, 'tcx> {
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
index e3377bd10c6..a8c61d2c8fd 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/post_drop_elaboration.rs
@@ -106,7 +106,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
                 }
             }
 
-            mir::TerminatorKind::Terminate
+            mir::TerminatorKind::UnwindTerminate
             | mir::TerminatorKind::Call { .. }
             | mir::TerminatorKind::Assert { .. }
             | mir::TerminatorKind::FalseEdge { .. }
@@ -114,7 +114,7 @@ impl<'tcx> Visitor<'tcx> for CheckLiveDrops<'_, 'tcx> {
             | mir::TerminatorKind::GeneratorDrop
             | mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::InlineAsm { .. }
-            | mir::TerminatorKind::Resume
+            | mir::TerminatorKind::UnwindResume
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::SwitchInt { .. }
             | mir::TerminatorKind::Unreachable
diff --git a/compiler/rustc_const_eval/src/transform/validate.rs b/compiler/rustc_const_eval/src/transform/validate.rs
index 83004492c8b..0dfbbf73dce 100644
--- a/compiler/rustc_const_eval/src/transform/validate.rs
+++ b/compiler/rustc_const_eval/src/transform/validate.rs
@@ -18,6 +18,7 @@ use rustc_mir_dataflow::impls::MaybeStorageLive;
 use rustc_mir_dataflow::storage::always_storage_live_locals;
 use rustc_mir_dataflow::{Analysis, ResultsCursor};
 use rustc_target::abi::{Size, FIRST_VARIANT};
+use rustc_target::spec::abi::Abi;
 
 #[derive(Copy, Clone, Debug, PartialEq, Eq)]
 enum EdgeKind {
@@ -58,6 +59,25 @@ impl<'tcx> MirPass<'tcx> for Validator {
             .iterate_to_fixpoint()
             .into_results_cursor(body);
 
+        let can_unwind = if mir_phase <= MirPhase::Runtime(RuntimePhase::Initial) {
+            // In this case `AbortUnwindingCalls` haven't yet been executed.
+            true
+        } else if !tcx.def_kind(def_id).is_fn_like() {
+            true
+        } else {
+            let body_ty = tcx.type_of(def_id).skip_binder();
+            let body_abi = match body_ty.kind() {
+                ty::FnDef(..) => body_ty.fn_sig(tcx).abi(),
+                ty::Closure(..) => Abi::RustCall,
+                ty::Generator(..) => Abi::Rust,
+                _ => {
+                    span_bug!(body.span, "unexpected body ty: {:?} phase {:?}", body_ty, mir_phase)
+                }
+            };
+
+            ty::layout::fn_can_unwind(tcx, Some(def_id), body_abi)
+        };
+
         let mut cfg_checker = CfgChecker {
             when: &self.when,
             body,
@@ -68,6 +88,7 @@ impl<'tcx> MirPass<'tcx> for Validator {
             storage_liveness,
             place_cache: FxHashSet::default(),
             value_cache: FxHashSet::default(),
+            can_unwind,
         };
         cfg_checker.visit_body(body);
         cfg_checker.check_cleanup_control_flow();
@@ -99,6 +120,9 @@ struct CfgChecker<'a, 'tcx> {
     storage_liveness: ResultsCursor<'a, 'tcx, MaybeStorageLive<'static>>,
     place_cache: FxHashSet<PlaceRef<'tcx>>,
     value_cache: FxHashSet<u128>,
+    // If `false`, then the MIR must not contain `UnwindAction::Continue` or
+    // `TerminatorKind::Resume`.
+    can_unwind: bool,
 }
 
 impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
@@ -237,13 +261,17 @@ impl<'a, 'tcx> CfgChecker<'a, 'tcx> {
         match unwind {
             UnwindAction::Cleanup(unwind) => {
                 if is_cleanup {
-                    self.fail(location, "unwind on cleanup block");
+                    self.fail(location, "`UnwindAction::Cleanup` in cleanup block");
                 }
                 self.check_edge(location, unwind, EdgeKind::Unwind);
             }
             UnwindAction::Continue => {
                 if is_cleanup {
-                    self.fail(location, "unwind on cleanup block");
+                    self.fail(location, "`UnwindAction::Continue` in cleanup block");
+                }
+
+                if !self.can_unwind {
+                    self.fail(location, "`UnwindAction::Continue` in no-unwind function");
                 }
             }
             UnwindAction::Unreachable | UnwindAction::Terminate => (),
@@ -464,13 +492,19 @@ impl<'a, 'tcx> Visitor<'tcx> for CfgChecker<'a, 'tcx> {
                     );
                 }
             }
-            TerminatorKind::Resume | TerminatorKind::Terminate => {
+            TerminatorKind::UnwindResume => {
                 let bb = location.block;
                 if !self.body.basic_blocks[bb].is_cleanup {
-                    self.fail(
-                        location,
-                        "Cannot `Resume` or `Terminate` from non-cleanup basic block",
-                    )
+                    self.fail(location, "Cannot `UnwindResume` from non-cleanup basic block")
+                }
+                if !self.can_unwind {
+                    self.fail(location, "Cannot `UnwindResume` in a function that cannot unwind")
+                }
+            }
+            TerminatorKind::UnwindTerminate => {
+                let bb = location.block;
+                if !self.body.basic_blocks[bb].is_cleanup {
+                    self.fail(location, "Cannot `UnwindTerminate` from non-cleanup basic block")
                 }
             }
             TerminatorKind::Return => {
@@ -665,7 +699,7 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
                                 return;
                             };
 
-                            f_ty.ty
+                            ty::EarlyBinder::bind(f_ty.ty).instantiate(self.tcx, args)
                         } else {
                             let Some(&f_ty) = args.as_generator().prefix_tys().get(f.index())
                             else {
@@ -701,12 +735,6 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             VarDebugInfoContents::Const(_) => {}
             VarDebugInfoContents::Place(place) => {
                 check_place(self, place);
-                if debuginfo.references != 0 && place.projection.last() == Some(&PlaceElem::Deref) {
-                    self.fail(
-                        START_BLOCK.start_location(),
-                        format!("debuginfo {debuginfo:?}, has both ref and deref"),
-                    );
-                }
             }
             VarDebugInfoContents::Composite { ty, ref fragments } => {
                 for f in fragments {
@@ -1204,8 +1232,8 @@ impl<'a, 'tcx> Visitor<'tcx> for TypeChecker<'a, 'tcx> {
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::InlineAsm { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable => {}
         }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0132.md b/compiler/rustc_error_codes/src/error_codes/E0132.md
index a23cc988bdb..51258739b89 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0132.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0132.md
@@ -13,7 +13,7 @@ It is not possible to declare type parameters on a function that has the `start`
 attribute. Such a function must have the following type signature (for more
 information, view [the unstable book][1]):
 
-[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
+[1]: https://doc.rust-lang.org/unstable-book/language-features/start.html
 
 ```
 # let _:
diff --git a/compiler/rustc_error_codes/src/error_codes/E0152.md b/compiler/rustc_error_codes/src/error_codes/E0152.md
index ef17b8b4c75..d862766571d 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0152.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0152.md
@@ -20,6 +20,6 @@ attributes:
 #![no_std]
 ```
 
-See also the [unstable book][1].
+See also [this section of the Rustonomicon][beneath std].
 
-[1]: https://doc.rust-lang.org/unstable-book/language-features/lang-items.html#writing-an-executable-without-stdlib
+[beneath std]: https://doc.rust-lang.org/nomicon/beneath-std.html
diff --git a/compiler/rustc_error_codes/src/error_codes/E0191.md b/compiler/rustc_error_codes/src/error_codes/E0191.md
index 46b773bdc50..344ac221698 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0191.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0191.md
@@ -7,8 +7,8 @@ trait Trait {
     type Bar;
 }
 
-type Foo = Trait; // error: the value of the associated type `Bar` (from
-                  //        the trait `Trait`) must be specified
+type Foo = dyn Trait; // error: the value of the associated type `Bar` (from
+                      //        the trait `Trait`) must be specified
 ```
 
 Trait objects need to have all associated types specified. Please verify that
@@ -20,5 +20,5 @@ trait Trait {
     type Bar;
 }
 
-type Foo = Trait<Bar=i32>; // ok!
+type Foo = dyn Trait<Bar=i32>; // ok!
 ```
diff --git a/compiler/rustc_errors/src/lib.rs b/compiler/rustc_errors/src/lib.rs
index 7d660d2dbaa..34518b53759 100644
--- a/compiler/rustc_errors/src/lib.rs
+++ b/compiler/rustc_errors/src/lib.rs
@@ -452,11 +452,11 @@ struct HandlerInner {
     /// have been converted.
     check_unstable_expect_diagnostics: bool,
 
-    /// Expected [`Diagnostic`][diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
+    /// Expected [`Diagnostic`][struct@diagnostic::Diagnostic]s store a [`LintExpectationId`] as part of
     /// the lint level. [`LintExpectationId`]s created early during the compilation
     /// (before `HirId`s have been defined) are not stable and can therefore not be
     /// stored on disk. This buffer stores these diagnostics until the ID has been
-    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][diagnostic::Diagnostic]s are the
+    /// replaced by a stable [`LintExpectationId`]. The [`Diagnostic`][struct@diagnostic::Diagnostic]s are the
     /// submitted for storage and added to the list of fulfilled expectations.
     unstable_expect_diagnostics: Vec<Diagnostic>,
 
diff --git a/compiler/rustc_expand/src/mbe/macro_parser.rs b/compiler/rustc_expand/src/mbe/macro_parser.rs
index 05c0cd952b8..7e85beaadcb 100644
--- a/compiler/rustc_expand/src/mbe/macro_parser.rs
+++ b/compiler/rustc_expand/src/mbe/macro_parser.rs
@@ -81,7 +81,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_data_structures::sync::Lrc;
 use rustc_errors::ErrorGuaranteed;
 use rustc_lint_defs::pluralize;
-use rustc_parse::parser::{NtOrTt, Parser};
+use rustc_parse::parser::{ParseNtResult, Parser};
 use rustc_span::symbol::Ident;
 use rustc_span::symbol::MacroRulesNormalizedIdent;
 use rustc_span::Span;
@@ -692,8 +692,8 @@ impl TtParser {
                             Ok(nt) => nt,
                         };
                         let m = match nt {
-                            NtOrTt::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
-                            NtOrTt::Tt(tt) => MatchedTokenTree(tt),
+                            ParseNtResult::Nt(nt) => MatchedNonterminal(Lrc::new(nt)),
+                            ParseNtResult::Tt(tt) => MatchedTokenTree(tt),
                         };
                         mp.push_match(next_metavar, seq_depth, m);
                         mp.idx += 1;
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index ce8b4621720..a5959d68fbc 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -1328,7 +1328,7 @@ fn is_in_follow(tok: &mbe::TokenTree, kind: NonterminalKind) -> IsInFollow {
                     _ => IsInFollow::No(TOKENS),
                 }
             }
-            NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatWithOr => {
                 const TOKENS: &[&str] = &["`=>`", "`,`", "`=`", "`if`", "`in`"];
                 match tok {
                     TokenTree::Token(token) => match token.kind {
diff --git a/compiler/rustc_expand/src/mbe/metavar_expr.rs b/compiler/rustc_expand/src/mbe/metavar_expr.rs
index b6382dcb894..7c37aadc67a 100644
--- a/compiler/rustc_expand/src/mbe/metavar_expr.rs
+++ b/compiler/rustc_expand/src/mbe/metavar_expr.rs
@@ -93,7 +93,17 @@ fn parse_count<'sess>(
     span: Span,
 ) -> PResult<'sess, MetaVarExpr> {
     let ident = parse_ident(iter, sess, span)?;
-    let depth = if try_eat_comma(iter) { Some(parse_depth(iter, sess, span)?) } else { None };
+    let depth = if try_eat_comma(iter) {
+        if iter.look_ahead(0).is_none() {
+            return Err(sess.span_diagnostic.struct_span_err(
+                span,
+                "`count` followed by a comma must have an associated index indicating its depth",
+            ));
+        }
+        Some(parse_depth(iter, sess, span)?)
+    } else {
+        None
+    };
     Ok(MetaVarExpr::Count(ident, depth))
 }
 
diff --git a/compiler/rustc_expand/src/mbe/transcribe.rs b/compiler/rustc_expand/src/mbe/transcribe.rs
index a5f83b88f7e..15e7ab3fe3e 100644
--- a/compiler/rustc_expand/src/mbe/transcribe.rs
+++ b/compiler/rustc_expand/src/mbe/transcribe.rs
@@ -220,16 +220,15 @@ pub(super) fn transcribe<'a>(
                         MatchedTokenTree(tt) => {
                             // `tt`s are emitted into the output stream directly as "raw tokens",
                             // without wrapping them into groups.
-                            let token = tt.clone();
-                            result.push(token);
+                            result.push(tt.clone());
                         }
                         MatchedNonterminal(nt) => {
                             // Other variables are emitted into the output stream as groups with
                             // `Delimiter::Invisible` to maintain parsing priorities.
                             // `Interpolated` is currently used for such groups in rustc parser.
                             marker.visit_span(&mut sp);
-                            let token = TokenTree::token_alone(token::Interpolated(nt.clone()), sp);
-                            result.push(token);
+                            result
+                                .push(TokenTree::token_alone(token::Interpolated(nt.clone()), sp));
                         }
                         MatchedSeq(..) => {
                             // We were unable to descend far enough. This is an error.
diff --git a/compiler/rustc_feature/src/active.rs b/compiler/rustc_feature/src/active.rs
index 953ea1bf523..f5708f933d5 100644
--- a/compiler/rustc_feature/src/active.rs
+++ b/compiler/rustc_feature/src/active.rs
@@ -352,6 +352,8 @@ declare_features! (
     (active, c_variadic, "1.34.0", Some(44930), None),
     /// Allows the use of `#[cfg(overflow_checks)` to check if integer overflow behaviour.
     (active, cfg_overflow_checks, "1.71.0", Some(111466), None),
+    /// Provides the relocation model information as cfg entry
+    (active, cfg_relocation_model, "CURRENT_RUSTC_VERSION", Some(114929), None),
     /// Allows the use of `#[cfg(sanitize = "option")]`; set when -Zsanitizer is used.
     (active, cfg_sanitize, "1.41.0", Some(39699), None),
     /// Allows `cfg(target_abi = "...")`.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index a183cfd8776..2f7cff3ce5c 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -35,6 +35,7 @@ const GATED_CFGS: &[GatedCfg] = &[
     (sym::target_has_atomic_load_store, sym::cfg_target_has_atomic, cfg_fn!(cfg_target_has_atomic)),
     (sym::sanitize, sym::cfg_sanitize, cfg_fn!(cfg_sanitize)),
     (sym::version, sym::cfg_version, cfg_fn!(cfg_version)),
+    (sym::relocation_model, sym::cfg_relocation_model, cfg_fn!(cfg_relocation_model)),
 ];
 
 /// Find a gated cfg determined by the `pred`icate which is given the cfg's name.
diff --git a/compiler/rustc_hir_analysis/src/astconv/errors.rs b/compiler/rustc_hir_analysis/src/astconv/errors.rs
index bd311c98fac..6082d446979 100644
--- a/compiler/rustc_hir_analysis/src/astconv/errors.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/errors.rs
@@ -597,7 +597,21 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                 }
             }
         }
-        if !suggestions.is_empty() {
+        suggestions.sort_by_key(|&(span, _)| span);
+        // There are cases where one bound points to a span within another bound's span, like when
+        // you have code like the following (#115019), so we skip providing a suggestion in those
+        // cases to avoid having a malformed suggestion.
+        //
+        // pub struct Flatten<I> {
+        //     inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::core,
+        //             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+        //             |                  ^^^^^^^^^^^^^^^^^^^^^
+        //             |                  |
+        //             |                  associated types `Item`, `IntoIter` must be specified
+        //             associated types `Item`, `IntoIter` must be specified
+        // }
+        let overlaps = suggestions.windows(2).any(|pair| pair[0].0.overlaps(pair[1].0));
+        if !suggestions.is_empty() && !overlaps {
             err.multipart_suggestion(
                 format!("specify the associated type{}", pluralize!(types_count)),
                 suggestions,
diff --git a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
index ad02ca252c4..bd0ab6463f0 100644
--- a/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
+++ b/compiler/rustc_hir_analysis/src/check/compare_impl_item.rs
@@ -342,9 +342,16 @@ fn compare_method_predicate_entailment<'tcx>(
                 continue;
             };
             for obligation in obligations {
+                debug!(?obligation);
                 match obligation.predicate.kind().skip_binder() {
+                    // We need to register Projection oblgiations too, because we may end up with
+                    // an implied `X::Item: 'a`, which gets desugared into `X::Item = ?0`, `?0: 'a`.
+                    // If we only register the region outlives obligation, this leads to an unconstrained var.
+                    // See `implied_bounds_entailment_alias_var` test.
                     ty::PredicateKind::Clause(
-                        ty::ClauseKind::RegionOutlives(..) | ty::ClauseKind::TypeOutlives(..),
+                        ty::ClauseKind::RegionOutlives(..)
+                        | ty::ClauseKind::TypeOutlives(..)
+                        | ty::ClauseKind::Projection(..),
                     ) => ocx.register_obligation(obligation),
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(arg)) => {
                         if wf_args_seen.insert(arg) {
diff --git a/compiler/rustc_hir_analysis/src/check/mod.rs b/compiler/rustc_hir_analysis/src/check/mod.rs
index 4cf3587327d..d8331661366 100644
--- a/compiler/rustc_hir_analysis/src/check/mod.rs
+++ b/compiler/rustc_hir_analysis/src/check/mod.rs
@@ -289,6 +289,7 @@ fn default_body_is_unstable(
         &tcx.sess.parse_sess,
         feature,
         rustc_feature::GateIssue::Library(issue),
+        false,
     );
 
     err.emit();
diff --git a/compiler/rustc_hir_typeck/src/cast.rs b/compiler/rustc_hir_typeck/src/cast.rs
index 5bc0e2ee86c..31a03fabe4f 100644
--- a/compiler/rustc_hir_typeck/src/cast.rs
+++ b/compiler/rustc_hir_typeck/src/cast.rs
@@ -389,34 +389,26 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                 if let ty::Ref(reg, cast_ty, mutbl) = *self.cast_ty.kind() {
                     if let ty::RawPtr(TypeAndMut { ty: expr_ty, .. }) = *self.expr_ty.kind()
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     fcx.tcx.lifetimes.re_erased,
                                     TypeAndMut { ty: expr_ty, mutbl },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}*", mutbl.prefix_str()), cast_ty == expr_ty));
                     } else if let ty::Ref(expr_reg, expr_ty, expr_mutbl) = *self.expr_ty.kind()
                         && expr_mutbl == Mutability::Not
                         && mutbl == Mutability::Mut
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,
                                     expr_reg,
                                     TypeAndMut { ty: expr_ty, mutbl: Mutability::Mut },
                                 ),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg_mutref = true;
                     }
@@ -424,30 +416,22 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     if !sugg_mutref
                         && sugg == None
                         && fcx
-                            .try_coerce(
-                                self.expr,
+                            .can_coerce(
                                 Ty::new_ref(fcx.tcx,reg, TypeAndMut { ty: self.expr_ty, mutbl }),
                                 self.cast_ty,
-                                AllowTwoPhase::No,
-                                None,
                             )
-                            .is_ok()
                     {
                         sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                     }
                 } else if let ty::RawPtr(TypeAndMut { mutbl, .. }) = *self.cast_ty.kind()
                     && fcx
-                        .try_coerce(
-                            self.expr,
+                        .can_coerce(
                             Ty::new_ref(fcx.tcx,
                                 fcx.tcx.lifetimes.re_erased,
                                 TypeAndMut { ty: self.expr_ty, mutbl },
                             ),
                             self.cast_ty,
-                            AllowTwoPhase::No,
-                            None,
                         )
-                        .is_ok()
                 {
                     sugg = Some((format!("&{}", mutbl.prefix_str()), false));
                 }
@@ -760,7 +744,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
                     ty::FnDef(..) => {
                         // Attempt a coercion to a fn pointer type.
                         let f = fcx.normalize(self.expr_span, self.expr_ty.fn_sig(fcx.tcx));
-                        let res = fcx.try_coerce(
+                        let res = fcx.coerce(
                             self.expr,
                             self.expr_ty,
                             Ty::new_fn_ptr(fcx.tcx, f),
@@ -860,7 +844,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
             (_, DynStar) => {
                 if fcx.tcx.features().dyn_star {
-                    bug!("should be handled by `try_coerce`")
+                    bug!("should be handled by `coerce`")
                 } else {
                     Err(CastError::IllegalCast)
                 }
@@ -956,7 +940,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
                 // Coerce to a raw pointer so that we generate AddressOf in MIR.
                 let array_ptr_type = Ty::new_ptr(fcx.tcx, m_expr);
-                fcx.try_coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
+                fcx.coerce(self.expr, self.expr_ty, array_ptr_type, AllowTwoPhase::No, None)
                     .unwrap_or_else(|_| {
                         bug!(
                         "could not cast from reference to array to pointer to array ({:?} to {:?})",
@@ -992,7 +976,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> Result<(), ty::error::TypeError<'tcx>> {
-        match fcx.try_coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
+        match fcx.coerce(self.expr, self.expr_ty, self.cast_ty, AllowTwoPhase::No, None) {
             Ok(_) => Ok(()),
             Err(err) => Err(err),
         }
diff --git a/compiler/rustc_hir_typeck/src/closure.rs b/compiler/rustc_hir_typeck/src/closure.rs
index 3e67afb1c3d..b19fb6da6de 100644
--- a/compiler/rustc_hir_typeck/src/closure.rs
+++ b/compiler/rustc_hir_typeck/src/closure.rs
@@ -711,6 +711,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         };
 
+        let span = self.tcx.def_span(expr_def_id);
+
         let output_ty = match *ret_ty.kind() {
             ty::Infer(ty::TyVar(ret_vid)) => {
                 self.obligations_for_self_ty(ret_vid).find_map(|obligation| {
@@ -724,20 +726,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .find_map(|(p, s)| get_future_output(p.as_predicate(), s))?,
             ty::Error(_) => return None,
             _ => span_bug!(
-                self.tcx.def_span(expr_def_id),
+                span,
                 "async fn generator return type not an inference variable: {ret_ty}"
             ),
         };
 
+        let output_ty = self.normalize(span, output_ty);
+
         // async fn that have opaque types in their return type need to redo the conversion to inference variables
         // as they fetch the still opaque version from the signature.
         let InferOk { value: output_ty, obligations } = self
-            .replace_opaque_types_with_inference_vars(
-                output_ty,
-                body_def_id,
-                self.tcx.def_span(expr_def_id),
-                self.param_env,
-            );
+            .replace_opaque_types_with_inference_vars(output_ty, body_def_id, span, self.param_env);
         self.register_predicates(obligations);
 
         Some(output_ty)
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 726914a995b..fca675ea9d8 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -1005,7 +1005,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// adjusted type of the expression, if successful.
     /// Adjustments are only recorded if the coercion succeeded.
     /// The expressions *must not* have any preexisting adjustments.
-    pub fn try_coerce(
+    pub fn coerce(
         &self,
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
@@ -1036,7 +1036,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         })
     }
 
-    /// Same as `try_coerce()`, but without side-effects.
+    /// Same as `coerce()`, but without side-effects.
     ///
     /// Returns false if the coercion creates any obligations that result in
     /// errors.
@@ -1494,7 +1494,7 @@ impl<'tcx, 'exprs, E: AsCoercionSite> CoerceMany<'tcx, 'exprs, E> {
                 // Special-case the first expression we are coercing.
                 // To be honest, I'm not entirely sure why we do this.
                 // We don't allow two-phase borrows, see comment in try_find_coercion_lub for why
-                fcx.try_coerce(
+                fcx.coerce(
                     expression,
                     expression_ty,
                     self.expected_ty,
diff --git a/compiler/rustc_hir_typeck/src/demand.rs b/compiler/rustc_hir_typeck/src/demand.rs
index 5b06088c348..2c16f21b491 100644
--- a/compiler/rustc_hir_typeck/src/demand.rs
+++ b/compiler/rustc_hir_typeck/src/demand.rs
@@ -53,7 +53,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             || self.suggest_no_capture_closure(err, expected, expr_ty)
             || self.suggest_boxing_when_appropriate(err, expr.span, expr.hir_id, expected, expr_ty)
             || self.suggest_block_to_brackets_peeling_refs(err, expr, expr_ty, expected)
-            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected, expected_ty_expr)
+            || self.suggest_copied_cloned_or_as_ref(err, expr, expr_ty, expected)
             || self.suggest_clone_for_ref(err, expr, expr_ty, expected)
             || self.suggest_into(err, expr, expr_ty, expected)
             || self.suggest_floating_point_literal(err, expr, expected)
@@ -254,7 +254,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) -> (Ty<'tcx>, Option<DiagnosticBuilder<'tcx, ErrorGuaranteed>>) {
         let expected = self.resolve_vars_with_obligations(expected);
 
-        let e = match self.try_coerce(expr, checked_ty, expected, allow_two_phase, None) {
+        let e = match self.coerce(expr, checked_ty, expected, allow_two_phase, None) {
             Ok(ty) => return (ty, None),
             Err(e) => e,
         };
@@ -475,7 +475,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 {
                     let Some(arg_ty) = self.node_ty_opt(arg_expr.hir_id) else { continue; };
                     let arg_ty = arg_ty.fold_with(&mut fudger);
-                    let _ = self.try_coerce(
+                    let _ = self.coerce(
                         arg_expr,
                         arg_ty,
                         *expected_arg_ty,
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index 36096aa35d4..054d23c71d4 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -253,7 +253,7 @@ impl HelpUseLatestEdition {
 }
 
 #[derive(Subdiagnostic)]
-pub enum OptionResultRefMismatch<'tcx> {
+pub enum OptionResultRefMismatch {
     #[suggestion(
         hir_typeck_option_result_copied,
         code = ".copied()",
@@ -276,19 +276,20 @@ pub enum OptionResultRefMismatch<'tcx> {
         span: Span,
         def_path: String,
     },
-    #[suggestion(
-        hir_typeck_option_result_asref,
-        code = ".as_ref()",
-        style = "verbose",
-        applicability = "machine-applicable"
-    )]
-    AsRef {
-        #[primary_span]
-        span: Span,
-        def_path: String,
-        expected_ty: Ty<'tcx>,
-        expr_ty: Ty<'tcx>,
-    },
+    // FIXME: #114050
+    // #[suggestion(
+    //     hir_typeck_option_result_asref,
+    //     code = ".as_ref()",
+    //     style = "verbose",
+    //     applicability = "machine-applicable"
+    // )]
+    // AsRef {
+    //     #[primary_span]
+    //     span: Span,
+    //     def_path: String,
+    //     expected_ty: Ty<'tcx>,
+    //     expr_ty: Ty<'tcx>,
+    // },
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index 004c8affcf0..4def7867384 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -260,9 +260,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // fulfillment error to be more accurate.
             let coerced_ty = self.resolve_vars_with_obligations(coerced_ty);
 
-            let coerce_error = self
-                .try_coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None)
-                .err();
+            let coerce_error =
+                self.coerce(provided_arg, checked_ty, coerced_ty, AllowTwoPhase::Yes, None).err();
 
             if coerce_error.is_some() {
                 return Compatibility::Incompatible(coerce_error);
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
index 48358e338da..d2a53ee8b5e 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/suggestions.rs
@@ -1097,7 +1097,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expr: &hir::Expr<'_>,
         expr_ty: Ty<'tcx>,
         expected_ty: Ty<'tcx>,
-        expected_ty_expr: Option<&'tcx hir::Expr<'tcx>>,
     ) -> bool {
         let ty::Adt(adt_def, args) = expr_ty.kind() else {
             return false;
@@ -1115,7 +1114,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         {
             let expr_inner_ty = args.type_at(0);
             let expected_inner_ty = expected_args.type_at(0);
-            if let &ty::Ref(_, ty, mutability) = expr_inner_ty.kind()
+            if let &ty::Ref(_, ty, _mutability) = expr_inner_ty.kind()
                     && self.can_eq(self.param_env, ty, expected_inner_ty)
                 {
                     let def_path = self.tcx.def_path_str(adt_def.did());
@@ -1124,14 +1123,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         errors::OptionResultRefMismatch::Copied {
                             span, def_path
                         }
-                    } else if let Some(expected_ty_expr) = expected_ty_expr
-                            // FIXME: suggest changes to both expressions to convert both to
-                            // Option/Result<&T>
-                            && mutability.is_not()
-                        {
-                        errors::OptionResultRefMismatch::AsRef {
-                            span: expected_ty_expr.span.shrink_to_hi(), expected_ty, expr_ty, def_path
-                        }
                     } else if let Some(clone_did) = self.tcx.lang_items().clone_trait()
                         && rustc_trait_selection::traits::type_known_to_meet_bound_modulo_regions(
                             self,
diff --git a/compiler/rustc_hir_typeck/src/method/prelude2021.rs b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
index 5b19a4c525f..3f1dca5b1de 100644
--- a/compiler/rustc_hir_typeck/src/method/prelude2021.rs
+++ b/compiler/rustc_hir_typeck/src/method/prelude2021.rs
@@ -14,6 +14,7 @@ use rustc_span::symbol::kw::{Empty, Underscore};
 use rustc_span::symbol::{sym, Ident};
 use rustc_span::Span;
 use rustc_trait_selection::infer::InferCtxtExt;
+use std::fmt::Write;
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     pub(super) fn lint_dot_call_from_2018(
@@ -143,16 +144,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                     let (self_adjusted, precise) = self.adjust_expr(pick, self_expr, sp);
                     if precise {
-                        let args = args
-                            .iter()
-                            .map(|arg| {
-                                let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
-                                format!(
-                                    ", {}",
-                                    self.sess().source_map().span_to_snippet(span).unwrap()
-                                )
-                            })
-                            .collect::<String>();
+                        let args = args.iter().fold(String::new(), |mut string, arg| {
+                            let span = arg.span.find_ancestor_inside(sp).unwrap_or_default();
+                            write!(
+                                string,
+                                ", {}",
+                                self.sess().source_map().span_to_snippet(span).unwrap()
+                            )
+                            .unwrap();
+                            string
+                        });
 
                         lint.span_suggestion(
                             sp,
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 1111a1a17e2..db8ea2bfe48 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -538,9 +538,13 @@ where
             continue;
         }
 
-        let timestamp = extract_timestamp_from_session_dir(&directory_name).unwrap_or_else(|_| {
-            bug!("unexpected incr-comp session dir: {}", session_dir.display())
-        });
+        let timestamp = match extract_timestamp_from_session_dir(&directory_name) {
+            Ok(timestamp) => timestamp,
+            Err(e) => {
+                debug!("unexpected incr-comp session dir: {}: {}", session_dir.display(), e);
+                continue;
+            }
+        };
 
         if timestamp > best_candidate.0 {
             best_candidate = (timestamp, Some(session_dir.clone()));
@@ -562,14 +566,14 @@ fn is_session_directory_lock_file(file_name: &str) -> bool {
     file_name.starts_with("s-") && file_name.ends_with(LOCK_FILE_EXT)
 }
 
-fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, ()> {
+fn extract_timestamp_from_session_dir(directory_name: &str) -> Result<SystemTime, &'static str> {
     if !is_session_directory(directory_name) {
-        return Err(());
+        return Err("not a directory");
     }
 
     let dash_indices: Vec<_> = directory_name.match_indices('-').map(|(idx, _)| idx).collect();
     if dash_indices.len() != 3 {
-        return Err(());
+        return Err("not three dashes in name");
     }
 
     string_to_timestamp(&directory_name[dash_indices[0] + 1..dash_indices[1]])
@@ -581,11 +585,11 @@ fn timestamp_to_string(timestamp: SystemTime) -> String {
     base_n::encode(micros as u128, INT_ENCODE_BASE)
 }
 
-fn string_to_timestamp(s: &str) -> Result<SystemTime, ()> {
+fn string_to_timestamp(s: &str) -> Result<SystemTime, &'static str> {
     let micros_since_unix_epoch = u64::from_str_radix(s, INT_ENCODE_BASE as u32);
 
     if micros_since_unix_epoch.is_err() {
-        return Err(());
+        return Err("timestamp not an int");
     }
 
     let micros_since_unix_epoch = micros_since_unix_epoch.unwrap();
diff --git a/compiler/rustc_index/src/lib.rs b/compiler/rustc_index/src/lib.rs
index 9942c70c4ae..76b493353cc 100644
--- a/compiler/rustc_index/src/lib.rs
+++ b/compiler/rustc_index/src/lib.rs
@@ -29,6 +29,18 @@ pub use {idx::Idx, slice::IndexSlice, vec::IndexVec};
 pub use rustc_macros::newtype_index;
 
 /// Type size assertion. The first argument is a type and the second argument is its expected size.
+///
+/// <div class="warning">
+///
+/// Emitting hard errors from size assertions like this is generally not
+/// recommended, especially in libraries, because they can cause build failures if the layout
+/// algorithm or dependencies change. Here in rustc we control the toolchain and layout algorithm,
+/// so the former is not a problem. For the latter we have a lockfile as rustc is an application and
+/// precompiled library.
+///
+/// Short version: Don't copy this macro into your own code. Use a `#[test]` instead.
+///
+/// </div>
 #[macro_export]
 macro_rules! static_assert_size {
     ($ty:ty, $size:expr) => {
diff --git a/compiler/rustc_infer/src/traits/mod.rs b/compiler/rustc_infer/src/traits/mod.rs
index dc41630196b..a5b2ccce85e 100644
--- a/compiler/rustc_infer/src/traits/mod.rs
+++ b/compiler/rustc_infer/src/traits/mod.rs
@@ -9,6 +9,7 @@ mod structural_impls;
 pub mod util;
 
 use std::cmp;
+use std::hash::{Hash, Hasher};
 
 use hir::def_id::LocalDefId;
 use rustc_hir as hir;
@@ -36,7 +37,7 @@ pub use rustc_middle::traits::*;
 /// either identifying an `impl` (e.g., `impl Eq for i32`) that
 /// satisfies the obligation, or else finding a bound that is in
 /// scope. The eventual result is usually a `Selection` (defined below).
-#[derive(Clone, PartialEq, Eq, Hash)]
+#[derive(Clone)]
 pub struct Obligation<'tcx, T> {
     /// The reason we have to prove this thing.
     pub cause: ObligationCause<'tcx>,
@@ -55,6 +56,27 @@ pub struct Obligation<'tcx, T> {
     pub recursion_depth: usize,
 }
 
+impl<'tcx, T: PartialEq> PartialEq<Obligation<'tcx, T>> for Obligation<'tcx, T> {
+    #[inline]
+    fn eq(&self, other: &Obligation<'tcx, T>) -> bool {
+        // Ignore `cause` and `recursion_depth`. This is a small performance
+        // win for a few crates, and a huge performance win for the crate in
+        // https://github.com/rust-lang/rustc-perf/pull/1680, which greatly
+        // stresses the trait system.
+        self.param_env == other.param_env && self.predicate == other.predicate
+    }
+}
+
+impl<T: Eq> Eq for Obligation<'_, T> {}
+
+impl<T: Hash> Hash for Obligation<'_, T> {
+    fn hash<H: Hasher>(&self, state: &mut H) -> () {
+        // See the comment on `Obligation::eq`.
+        self.param_env.hash(state);
+        self.predicate.hash(state);
+    }
+}
+
 impl<'tcx, P> From<Obligation<'tcx, P>> for solve::Goal<'tcx, P> {
     fn from(value: Obligation<'tcx, P>) -> Self {
         solve::Goal { param_env: value.param_env, predicate: value.predicate }
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index f73797415bc..aabefb729f3 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -966,6 +966,14 @@ pub trait LintContext: Sized {
                         Applicability::MachineApplicable
                     );
                 }
+                BuiltinLintDiagnostics::AssociatedConstElidedLifetime { elided, span } => {
+                    db.span_suggestion_verbose(
+                        if elided { span.shrink_to_hi() } else { span },
+                        "use the `'static` lifetime",
+                        if elided { "'static " } else { "'static" },
+                        Applicability::MachineApplicable
+                    );
+                }
             }
             // Rewrap `db`, and pass control to the user.
             decorate(db)
diff --git a/compiler/rustc_lint/src/levels.rs b/compiler/rustc_lint/src/levels.rs
index 1f4e5fa4d3b..0a40d17f98e 100644
--- a/compiler/rustc_lint/src/levels.rs
+++ b/compiler/rustc_lint/src/levels.rs
@@ -12,7 +12,7 @@ use rustc_ast as ast;
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::FxHashMap;
 use rustc_errors::{DecorateLint, DiagnosticBuilder, DiagnosticMessage, MultiSpan};
-use rustc_feature::Features;
+use rustc_feature::{Features, GateIssue};
 use rustc_hir as hir;
 use rustc_hir::intravisit::{self, Visitor};
 use rustc_hir::HirId;
@@ -24,12 +24,14 @@ use rustc_middle::lint::{
 };
 use rustc_middle::query::Providers;
 use rustc_middle::ty::{RegisteredTools, TyCtxt};
-use rustc_session::lint::builtin::{RENAMED_AND_REMOVED_LINTS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES};
 use rustc_session::lint::{
-    builtin::{self, FORBIDDEN_LINT_GROUPS, SINGLE_USE_LIFETIMES, UNFULFILLED_LINT_EXPECTATIONS},
+    builtin::{
+        self, FORBIDDEN_LINT_GROUPS, RENAMED_AND_REMOVED_LINTS, SINGLE_USE_LIFETIMES,
+        UNFULFILLED_LINT_EXPECTATIONS, UNKNOWN_LINTS, UNUSED_ATTRIBUTES,
+    },
     Level, Lint, LintExpectationId, LintId,
 };
-use rustc_session::parse::{add_feature_diagnostics, feature_err};
+use rustc_session::parse::feature_err;
 use rustc_session::Session;
 use rustc_span::symbol::{sym, Symbol};
 use rustc_span::{Span, DUMMY_SP};
@@ -566,7 +568,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     continue;
                 }
 
-                if self.check_gated_lint(id, DUMMY_SP) {
+                if self.check_gated_lint(id, DUMMY_SP, true) {
                     let src = LintLevelSource::CommandLine(lint_flag_val, orig_level);
                     self.insert(id, (level, src));
                 }
@@ -837,7 +839,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             reason,
                         };
                         for &id in *ids {
-                            if self.check_gated_lint(id, attr.span) {
+                            if self.check_gated_lint(id, attr.span, false) {
                                 self.insert_spec(id, (level, src));
                             }
                         }
@@ -854,7 +856,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                                     reason,
                                 };
                                 for &id in ids {
-                                    if self.check_gated_lint(id, attr.span) {
+                                    if self.check_gated_lint(id, attr.span, false) {
                                         self.insert_spec(id, (level, src));
                                     }
                                 }
@@ -955,7 +957,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                             reason,
                         };
                         for &id in ids {
-                            if self.check_gated_lint(id, attr.span) {
+                            if self.check_gated_lint(id, attr.span, false) {
                                 self.insert_spec(id, (level, src));
                             }
                         }
@@ -1000,7 +1002,7 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
     // FIXME only emit this once for each attribute, instead of repeating it 4 times for
     // pre-expansion lints, post-expansion lints, `shallow_lint_levels_on` and `lint_expectations`.
     #[track_caller]
-    fn check_gated_lint(&self, lint_id: LintId, span: Span) -> bool {
+    fn check_gated_lint(&self, lint_id: LintId, span: Span, lint_from_cli: bool) -> bool {
         if let Some(feature) = lint_id.lint.feature_gate {
             if !self.features.enabled(feature) {
                 let lint = builtin::UNKNOWN_LINTS;
@@ -1015,7 +1017,13 @@ impl<'s, P: LintLevelsProvider> LintLevelsBuilder<'s, P> {
                     |lint| {
                         lint.set_arg("name", lint_id.lint.name_lower());
                         lint.note(fluent::lint_note);
-                        add_feature_diagnostics(lint, &self.sess.parse_sess, feature);
+                        rustc_session::parse::add_feature_diagnostics_for_issue(
+                            lint,
+                            &self.sess.parse_sess,
+                            feature,
+                            GateIssue::Language,
+                            lint_from_cli,
+                        );
                         lint
                     },
                 );
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 96c31a90da8..0aa37642b74 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3376,6 +3376,7 @@ declare_lint_pass! {
         DEPRECATED_IN_FUTURE,
         DEPRECATED_WHERE_CLAUSE_LOCATION,
         DUPLICATE_MACRO_ATTRIBUTES,
+        ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
         ELIDED_LIFETIMES_IN_PATHS,
         EXPORTED_PRIVATE_DEPENDENCIES,
         FFI_UNWIND_CALLS,
@@ -4527,3 +4528,44 @@ declare_lint! {
         reference: "issue #114095 <https://github.com/rust-lang/rust/issues/114095>",
     };
 }
+
+declare_lint! {
+    /// The `elided_lifetimes_in_associated_constant` lint detects elided lifetimes
+    /// that were erroneously allowed in associated constants.
+    ///
+    /// ### Example
+    ///
+    /// ```rust,compile_fail
+    /// #![deny(elided_lifetimes_in_associated_constant)]
+    ///
+    /// struct Foo;
+    ///
+    /// impl Foo {
+    ///     const STR: &str = "hello, world";
+    /// }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Previous version of Rust
+    ///
+    /// Implicit static-in-const behavior was decided [against] for associated
+    /// constants because of ambiguity. This, however, regressed and the compiler
+    /// erroneously treats elided lifetimes in associated constants as lifetime
+    /// parameters on the impl.
+    ///
+    /// This is a [future-incompatible] lint to transition this to a
+    /// hard error in the future.
+    ///
+    /// [against]: https://github.com/rust-lang/rust/issues/38831
+    /// [future-incompatible]: ../index.md#future-incompatible-lints
+    pub ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
+    Warn,
+    "elided lifetimes cannot be used in associated constants in impls",
+    @future_incompatible = FutureIncompatibleInfo {
+        reason: FutureIncompatibilityReason::FutureReleaseError,
+        reference: "issue #115010 <https://github.com/rust-lang/rust/issues/115010>",
+    };
+}
diff --git a/compiler/rustc_lint_defs/src/lib.rs b/compiler/rustc_lint_defs/src/lib.rs
index f350957f72f..76e736859d3 100644
--- a/compiler/rustc_lint_defs/src/lib.rs
+++ b/compiler/rustc_lint_defs/src/lib.rs
@@ -23,8 +23,9 @@ pub mod builtin;
 
 #[macro_export]
 macro_rules! pluralize {
+    // Pluralize based on count (e.g., apples)
     ($x:expr) => {
-        if $x != 1 { "s" } else { "" }
+        if $x == 1 { "" } else { "s" }
     };
     ("has", $x:expr) => {
         if $x == 1 { "has" } else { "have" }
@@ -572,6 +573,10 @@ pub enum BuiltinLintDiagnostics {
         /// The span of the unnecessarily-qualified path to remove.
         removal_span: Span,
     },
+    AssociatedConstElidedLifetime {
+        elided: bool,
+        span: Span,
+    },
 }
 
 /// Lints that are buffered up early on in the `Session` before the
diff --git a/compiler/rustc_macros/src/serialize.rs b/compiler/rustc_macros/src/serialize.rs
index f1e7b8eb6c7..ba75517d7a6 100644
--- a/compiler/rustc_macros/src/serialize.rs
+++ b/compiler/rustc_macros/src/serialize.rs
@@ -59,14 +59,14 @@ fn decodable_body(
                 })
                 .collect();
             let message = format!(
-                "invalid enum variant tag while decoding `{}`, expected 0..{}",
+                "invalid enum variant tag while decoding `{}`, expected 0..{}, actual {{}}",
                 ty_name,
                 variants.len()
             );
             quote! {
                 match ::rustc_serialize::Decoder::read_usize(__decoder) {
                     #match_inner
-                    _ => panic!(#message),
+                    n => panic!(#message, n),
                 }
             }
         }
diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs
index e8fd469e1fb..0da8fe9cca7 100644
--- a/compiler/rustc_middle/src/hir/mod.rs
+++ b/compiler/rustc_middle/src/hir/mod.rs
@@ -164,18 +164,15 @@ pub fn provide(providers: &mut Providers) {
         tcx.hir_crate(()).owners[id.def_id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs)
     };
     providers.def_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_span(hir_id).unwrap_or(DUMMY_SP)
     };
     providers.def_ident_span = |tcx, def_id| {
-        let def_id = def_id;
         let hir_id = tcx.hir().local_def_id_to_hir_id(def_id);
         tcx.hir().opt_ident_span(hir_id)
     };
-    providers.fn_arg_names = |tcx, id| {
+    providers.fn_arg_names = |tcx, def_id| {
         let hir = tcx.hir();
-        let def_id = id;
         let hir_id = hir.local_def_id_to_hir_id(def_id);
         if let Some(body_id) = hir.maybe_body_owned_by(def_id) {
             tcx.arena.alloc_from_iter(hir.body_param_names(body_id))
@@ -190,7 +187,7 @@ pub fn provide(providers: &mut Providers) {
         {
             idents
         } else {
-            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", id);
+            span_bug!(hir.span(hir_id), "fn_arg_names: unexpected item {:?}", def_id);
         }
     };
     providers.opt_def_kind = |tcx, def_id| tcx.hir().opt_def_kind(def_id);
diff --git a/compiler/rustc_middle/src/mir/coverage.rs b/compiler/rustc_middle/src/mir/coverage.rs
index d7d6e3a0086..1efb54bdb08 100644
--- a/compiler/rustc_middle/src/mir/coverage.rs
+++ b/compiler/rustc_middle/src/mir/coverage.rs
@@ -96,21 +96,6 @@ pub enum CoverageKind {
     Unreachable,
 }
 
-impl CoverageKind {
-    pub fn as_operand(&self) -> Operand {
-        use CoverageKind::*;
-        match *self {
-            Counter { id, .. } => Operand::Counter(id),
-            Expression { id, .. } => Operand::Expression(id),
-            Unreachable => bug!("Unreachable coverage cannot be part of an expression"),
-        }
-    }
-
-    pub fn is_expression(&self) -> bool {
-        matches!(self, Self::Expression { .. })
-    }
-}
-
 impl Debug for CoverageKind {
     fn fmt(&self, fmt: &mut Formatter<'_>) -> fmt::Result {
         use CoverageKind::*;
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index ddb5e248cdc..9ef3a1b30e4 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -1109,10 +1109,6 @@ pub struct VarDebugInfo<'tcx> {
     /// originated from (starting from 1). Note, if MIR inlining is enabled, then this is the
     /// argument number in the original function before it was inlined.
     pub argument_index: Option<u16>,
-
-    /// The data represents `name` dereferenced `references` times,
-    /// and not the direct value.
-    pub references: u8,
 }
 
 ///////////////////////////////////////////////////////////////////////////
diff --git a/compiler/rustc_middle/src/mir/patch.rs b/compiler/rustc_middle/src/mir/patch.rs
index c4c3341f873..cd74a403ff6 100644
--- a/compiler/rustc_middle/src/mir/patch.rs
+++ b/compiler/rustc_middle/src/mir/patch.rs
@@ -35,7 +35,7 @@ impl<'tcx> MirPatch<'tcx> {
 
         for (bb, block) in body.basic_blocks.iter_enumerated() {
             // Check if we already have a resume block
-            if let TerminatorKind::Resume = block.terminator().kind && block.statements.is_empty() {
+            if let TerminatorKind::UnwindResume = block.terminator().kind && block.statements.is_empty() {
                 result.resume_block = Some(bb);
                 continue;
             }
@@ -50,7 +50,7 @@ impl<'tcx> MirPatch<'tcx> {
             }
 
             // Check if we already have a terminate block
-            if let TerminatorKind::Terminate = block.terminator().kind && block.statements.is_empty() {
+            if let TerminatorKind::UnwindTerminate = block.terminator().kind && block.statements.is_empty() {
                 result.terminate_block = Some(bb);
                 continue;
             }
@@ -68,7 +68,7 @@ impl<'tcx> MirPatch<'tcx> {
             statements: vec![],
             terminator: Some(Terminator {
                 source_info: SourceInfo::outermost(self.body_span),
-                kind: TerminatorKind::Resume,
+                kind: TerminatorKind::UnwindResume,
             }),
             is_cleanup: true,
         });
@@ -102,7 +102,7 @@ impl<'tcx> MirPatch<'tcx> {
             statements: vec![],
             terminator: Some(Terminator {
                 source_info: SourceInfo::outermost(self.body_span),
-                kind: TerminatorKind::Terminate,
+                kind: TerminatorKind::UnwindTerminate,
             }),
             is_cleanup: true,
         });
diff --git a/compiler/rustc_middle/src/mir/pretty.rs b/compiler/rustc_middle/src/mir/pretty.rs
index 27e39137092..773056e8a17 100644
--- a/compiler/rustc_middle/src/mir/pretty.rs
+++ b/compiler/rustc_middle/src/mir/pretty.rs
@@ -555,13 +555,8 @@ fn write_scope_tree(
         }
 
         let indented_debug_info = format!(
-            "{0:1$}debug {2} => {3:&<4$}{5:?};",
-            INDENT,
-            indent,
-            var_debug_info.name,
-            "",
-            var_debug_info.references as usize,
-            var_debug_info.value,
+            "{0:1$}debug {2} => {3:?};",
+            INDENT, indent, var_debug_info.name, var_debug_info.value,
         );
 
         if tcx.sess.opts.unstable_opts.mir_include_spans {
diff --git a/compiler/rustc_middle/src/mir/spanview.rs b/compiler/rustc_middle/src/mir/spanview.rs
index 20a9e6889e4..a5358687c14 100644
--- a/compiler/rustc_middle/src/mir/spanview.rs
+++ b/compiler/rustc_middle/src/mir/spanview.rs
@@ -238,45 +238,6 @@ pub fn source_range_no_file(tcx: TyCtxt<'_>, span: Span) -> String {
     format!("{}:{}-{}:{}", start.line, start.col.to_usize() + 1, end.line, end.col.to_usize() + 1)
 }
 
-pub fn statement_kind_name(statement: &Statement<'_>) -> &'static str {
-    use StatementKind::*;
-    match statement.kind {
-        Assign(..) => "Assign",
-        FakeRead(..) => "FakeRead",
-        SetDiscriminant { .. } => "SetDiscriminant",
-        Deinit(..) => "Deinit",
-        StorageLive(..) => "StorageLive",
-        StorageDead(..) => "StorageDead",
-        Retag(..) => "Retag",
-        PlaceMention(..) => "PlaceMention",
-        AscribeUserType(..) => "AscribeUserType",
-        Coverage(..) => "Coverage",
-        Intrinsic(..) => "Intrinsic",
-        ConstEvalCounter => "ConstEvalCounter",
-        Nop => "Nop",
-    }
-}
-
-pub fn terminator_kind_name(term: &Terminator<'_>) -> &'static str {
-    use TerminatorKind::*;
-    match term.kind {
-        Goto { .. } => "Goto",
-        SwitchInt { .. } => "SwitchInt",
-        Resume => "Resume",
-        Terminate => "Terminate",
-        Return => "Return",
-        Unreachable => "Unreachable",
-        Drop { .. } => "Drop",
-        Call { .. } => "Call",
-        Assert { .. } => "Assert",
-        Yield { .. } => "Yield",
-        GeneratorDrop => "GeneratorDrop",
-        FalseEdge { .. } => "FalseEdge",
-        FalseUnwind { .. } => "FalseUnwind",
-        InlineAsm { .. } => "InlineAsm",
-    }
-}
-
 fn statement_span_viewable<'tcx>(
     tcx: TyCtxt<'tcx>,
     body_span: Span,
@@ -304,7 +265,7 @@ fn terminator_span_viewable<'tcx>(
     if !body_span.contains(span) {
         return None;
     }
-    let id = format!("{}:{}", bb.index(), terminator_kind_name(term));
+    let id = format!("{}:{}", bb.index(), term.kind.name());
     let tooltip = tooltip(tcx, &id, span, vec![], &data.terminator);
     Some(SpanViewable { bb, span, id, tooltip })
 }
@@ -631,7 +592,7 @@ fn tooltip<'tcx>(
             "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
-            statement_kind_name(&statement),
+            statement.kind.name(),
             statement
         ));
     }
@@ -641,7 +602,7 @@ fn tooltip<'tcx>(
             "\n{}{}: {}: {:?}",
             TOOLTIP_INDENT,
             source_range,
-            terminator_kind_name(term),
+            term.kind.name(),
             term.kind
         ));
     }
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index be27bf75dbd..e91e822f915 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -380,6 +380,28 @@ pub enum StatementKind<'tcx> {
     Nop,
 }
 
+impl StatementKind<'_> {
+    /// Returns a simple string representation of a `StatementKind` variant, independent of any
+    /// values it might hold (e.g. `StatementKind::Assign` always returns `"Assign"`).
+    pub const fn name(&self) -> &'static str {
+        match self {
+            StatementKind::Assign(..) => "Assign",
+            StatementKind::FakeRead(..) => "FakeRead",
+            StatementKind::SetDiscriminant { .. } => "SetDiscriminant",
+            StatementKind::Deinit(..) => "Deinit",
+            StatementKind::StorageLive(..) => "StorageLive",
+            StatementKind::StorageDead(..) => "StorageDead",
+            StatementKind::Retag(..) => "Retag",
+            StatementKind::PlaceMention(..) => "PlaceMention",
+            StatementKind::AscribeUserType(..) => "AscribeUserType",
+            StatementKind::Coverage(..) => "Coverage",
+            StatementKind::Intrinsic(..) => "Intrinsic",
+            StatementKind::ConstEvalCounter => "ConstEvalCounter",
+            StatementKind::Nop => "Nop",
+        }
+    }
+}
+
 #[derive(
     Clone,
     TyEncodable,
@@ -593,13 +615,13 @@ pub enum TerminatorKind<'tcx> {
     ///
     /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
     /// deaggregation runs.
-    Resume,
+    UnwindResume,
 
     /// Indicates that the landing pad is finished and that the process should terminate.
     ///
     /// Used to prevent unwinding for foreign items or with `-C unwind=abort`. Only permitted in
     /// cleanup blocks.
-    Terminate,
+    UnwindTerminate,
 
     /// Returns from the function.
     ///
@@ -790,8 +812,8 @@ impl TerminatorKind<'_> {
         match self {
             TerminatorKind::Goto { .. } => "Goto",
             TerminatorKind::SwitchInt { .. } => "SwitchInt",
-            TerminatorKind::Resume => "Resume",
-            TerminatorKind::Terminate => "Terminate",
+            TerminatorKind::UnwindResume => "UnwindResume",
+            TerminatorKind::UnwindTerminate => "UnwindTerminate",
             TerminatorKind::Return => "Return",
             TerminatorKind::Unreachable => "Unreachable",
             TerminatorKind::Drop { .. } => "Drop",
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index 1f878d23b44..bd87563e2bb 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -155,8 +155,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | InlineAsm { destination: Some(t), unwind: _, .. } => {
                 Some(t).into_iter().chain((&[]).into_iter().copied())
             }
-            Resume
-            | Terminate
+            UnwindResume
+            | UnwindTerminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -197,8 +197,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             | InlineAsm { destination: Some(ref mut t), unwind: _, .. } => {
                 Some(t).into_iter().chain(&mut [])
             }
-            Resume
-            | Terminate
+            UnwindResume
+            | UnwindTerminate
             | GeneratorDrop
             | Return
             | Unreachable
@@ -214,8 +214,8 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn unwind(&self) -> Option<&UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -233,8 +233,8 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn unwind_mut(&mut self) -> Option<&mut UnwindAction> {
         match *self {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -311,8 +311,8 @@ impl<'tcx> TerminatorKind<'tcx> {
             SwitchInt { discr, .. } => write!(fmt, "switchInt({discr:?})"),
             Return => write!(fmt, "return"),
             GeneratorDrop => write!(fmt, "generator_drop"),
-            Resume => write!(fmt, "resume"),
-            Terminate => write!(fmt, "abort"),
+            UnwindResume => write!(fmt, "resume"),
+            UnwindTerminate => write!(fmt, "abort"),
             Yield { value, resume_arg, .. } => write!(fmt, "{resume_arg:?} = yield({value:?})"),
             Unreachable => write!(fmt, "unreachable"),
             Drop { place, .. } => write!(fmt, "drop({place:?})"),
@@ -391,7 +391,7 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn fmt_successor_labels(&self) -> Vec<Cow<'static, str>> {
         use self::TerminatorKind::*;
         match *self {
-            Return | Resume | Terminate | Unreachable | GeneratorDrop => vec![],
+            Return | UnwindResume | UnwindTerminate | Unreachable | GeneratorDrop => vec![],
             Goto { .. } => vec!["".into()],
             SwitchInt { ref targets, .. } => targets
                 .values
@@ -486,7 +486,9 @@ impl<'tcx> TerminatorKind<'tcx> {
     pub fn edges(&self) -> TerminatorEdges<'_, 'tcx> {
         use TerminatorKind::*;
         match *self {
-            Return | Resume | Terminate | GeneratorDrop | Unreachable => TerminatorEdges::None,
+            Return | UnwindResume | UnwindTerminate | GeneratorDrop | Unreachable => {
+                TerminatorEdges::None
+            }
 
             Goto { target } => TerminatorEdges::Single(target),
 
diff --git a/compiler/rustc_middle/src/mir/visit.rs b/compiler/rustc_middle/src/mir/visit.rs
index 64bc4fa7926..b3d3366ae10 100644
--- a/compiler/rustc_middle/src/mir/visit.rs
+++ b/compiler/rustc_middle/src/mir/visit.rs
@@ -469,8 +469,8 @@ macro_rules! make_mir_visitor {
                 self.visit_source_info(source_info);
                 match kind {
                     TerminatorKind::Goto { .. } |
-                    TerminatorKind::Resume |
-                    TerminatorKind::Terminate |
+                    TerminatorKind::UnwindResume |
+                    TerminatorKind::UnwindTerminate |
                     TerminatorKind::GeneratorDrop |
                     TerminatorKind::Unreachable |
                     TerminatorKind::FalseEdge { .. } |
@@ -840,7 +840,6 @@ macro_rules! make_mir_visitor {
                     source_info,
                     value,
                     argument_index: _,
-                    references: _,
                 } = var_debug_info;
 
                 self.visit_source_info(source_info);
diff --git a/compiler/rustc_middle/src/ty/diagnostics.rs b/compiler/rustc_middle/src/ty/diagnostics.rs
index e71482326da..5db9b775a0f 100644
--- a/compiler/rustc_middle/src/ty/diagnostics.rs
+++ b/compiler/rustc_middle/src/ty/diagnostics.rs
@@ -1,6 +1,7 @@
 //! Diagnostics related methods for `Ty`.
 
 use std::borrow::Cow;
+use std::fmt::Write;
 use std::ops::ControlFlow;
 
 use crate::ty::{
@@ -335,10 +336,10 @@ pub fn suggest_constraining_type_params<'a>(
             //                                           - insert: `, X: Bar`
             suggestions.push((
                 generics.tail_span_for_predicate_suggestion(),
-                constraints
-                    .iter()
-                    .map(|&(constraint, _)| format!(", {param_name}: {constraint}"))
-                    .collect::<String>(),
+                constraints.iter().fold(String::new(), |mut string, &(constraint, _)| {
+                    write!(string, ", {param_name}: {constraint}").unwrap();
+                    string
+                }),
                 SuggestChangingConstraintsMessage::RestrictTypeFurther { ty: param_name },
             ));
             continue;
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 1347b35556d..f979ddd00fa 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -438,7 +438,6 @@ CloneLiftImpls! {
     (),
     bool,
     usize,
-    u8,
     u16,
     u32,
     u64,
diff --git a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
index fe5190900e9..26662f5de45 100644
--- a/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
+++ b/compiler/rustc_mir_build/src/build/custom/parse/instruction.rs
@@ -61,9 +61,7 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
                 })
             },
             @call("mir_call", args) => {
-                let destination = self.parse_place(args[0])?;
-                let target = self.parse_block(args[1])?;
-                self.parse_call(args[2], destination, target)
+                self.parse_call(args)
             },
             ExprKind::Match { scrutinee, arms, .. } => {
                 let discr = self.parse_operand(*scrutinee)?;
@@ -109,13 +107,14 @@ impl<'tcx, 'body> ParseCtxt<'tcx, 'body> {
         Ok(SwitchTargets::new(values.into_iter().zip(targets), otherwise))
     }
 
-    fn parse_call(
-        &self,
-        expr_id: ExprId,
-        destination: Place<'tcx>,
-        target: BasicBlock,
-    ) -> PResult<TerminatorKind<'tcx>> {
-        parse_by_kind!(self, expr_id, _, "function call",
+    fn parse_call(&self, args: &[ExprId]) -> PResult<TerminatorKind<'tcx>> {
+        let (destination, call) = parse_by_kind!(self, args[0], _, "function call",
+            ExprKind::Assign { lhs, rhs } => (*lhs, *rhs),
+        );
+        let destination = self.parse_place(destination)?;
+        let target = self.parse_block(args[1])?;
+
+        parse_by_kind!(self, call, _, "function call",
             ExprKind::Call { fun, args, from_hir_call, fn_span, .. } => {
                 let fun = self.parse_operand(*fun)?;
                 let args = args
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index ed3ac7cb3ec..3c450740712 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -2242,7 +2242,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         self.var_debug_info.push(VarDebugInfo {
             name,
             source_info: debug_source_info,
-            references: 0,
             value: VarDebugInfoContents::Place(for_arm_body.into()),
             argument_index: None,
         });
@@ -2262,7 +2261,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             self.var_debug_info.push(VarDebugInfo {
                 name,
                 source_info: debug_source_info,
-                references: 0,
                 value: VarDebugInfoContents::Place(ref_for_guard.into()),
                 argument_index: None,
             });
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index c66eba5520e..2a23a69b584 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -820,7 +820,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 };
                 self.var_debug_info.push(VarDebugInfo {
                     name,
-                    references: 0,
                     source_info: SourceInfo::outermost(captured_place.var_ident.span),
                     value: VarDebugInfoContents::Place(use_place),
                     argument_index: None,
@@ -851,7 +850,6 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 self.var_debug_info.push(VarDebugInfo {
                     name,
                     source_info,
-                    references: 0,
                     value: VarDebugInfoContents::Place(arg_local.into()),
                     argument_index: Some(argument_index as u16 + 1),
                 });
diff --git a/compiler/rustc_mir_build/src/build/scope.rs b/compiler/rustc_mir_build/src/build/scope.rs
index a96288a11e5..567e7bfb5bf 100644
--- a/compiler/rustc_mir_build/src/build/scope.rs
+++ b/compiler/rustc_mir_build/src/build/scope.rs
@@ -685,9 +685,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
-        // create a dummy terminator now. `TerminatorKind::Resume` is used
+        // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
-        self.cfg.terminate(block, source_info, TerminatorKind::Resume);
+        self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
 
         self.cfg.start_new_block().unit()
     }
@@ -717,9 +717,9 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         drops.add_entry(block, drop_idx);
 
         // `build_drop_trees` doesn't have access to our source_info, so we
-        // create a dummy terminator now. `TerminatorKind::Resume` is used
+        // create a dummy terminator now. `TerminatorKind::UnwindResume` is used
         // because MIR type checking will panic if it hasn't been overwritten.
-        self.cfg.terminate(block, source_info, TerminatorKind::Resume);
+        self.cfg.terminate(block, source_info, TerminatorKind::UnwindResume);
     }
 
     // Add a dummy `Assign` statement to the CFG, with the span for the source code's `continue`
@@ -1441,7 +1441,7 @@ impl<'a, 'tcx: 'a> Builder<'a, 'tcx> {
         blocks[ROOT_NODE] = *resume_block;
         drops.build_mir::<Unwind>(cfg, &mut blocks);
         if let (None, Some(resume)) = (*resume_block, blocks[ROOT_NODE]) {
-            cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::Resume);
+            cfg.terminate(resume, SourceInfo::outermost(fn_span), TerminatorKind::UnwindResume);
 
             *resume_block = blocks[ROOT_NODE];
         }
@@ -1506,8 +1506,8 @@ impl<'tcx> DropTreeBuilder<'tcx> for Unwind {
             }
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. }
diff --git a/compiler/rustc_mir_build/src/lints.rs b/compiler/rustc_mir_build/src/lints.rs
index 7fb73b5c7b2..84c80bf41a4 100644
--- a/compiler/rustc_mir_build/src/lints.rs
+++ b/compiler/rustc_mir_build/src/lints.rs
@@ -186,9 +186,9 @@ impl<'mir, 'tcx, C: TerminatorClassifier<'tcx>> TriColorVisitor<BasicBlocks<'tcx
 
         match self.body[bb].terminator().kind {
             // These terminators return control flow to the caller.
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Yield { .. } => ControlFlow::Break(NonRecursive),
diff --git a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
index 8d7b50796bb..5ed8f20b73f 100644
--- a/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/borrowed_locals.rs
@@ -131,7 +131,7 @@ where
                 }
             }
 
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Call { .. }
             | TerminatorKind::FalseEdge { .. }
@@ -139,7 +139,7 @@ where
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
             | TerminatorKind::InlineAsm { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable
diff --git a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
index bea23b7f7ae..531390c2f07 100644
--- a/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/storage_liveness.rs
@@ -291,14 +291,14 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
 
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
-            TerminatorKind::Terminate
+            TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
@@ -328,14 +328,14 @@ impl<'tcx> crate::GenKillAnalysis<'tcx> for MaybeRequiresStorage<'_, '_, 'tcx> {
             // Nothing to do for these. Match exhaustively so this fails to compile when new
             // variants are added.
             TerminatorKind::Yield { .. }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Assert { .. }
             | TerminatorKind::Drop { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. }
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Return
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::Unreachable => {}
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index 5052de99184..4adf3dec61b 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -370,8 +370,8 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             // this that could possibly access the return place, this doesn't
             // need recording.
             | TerminatorKind::Return
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::GeneratorDrop
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. } => {}
diff --git a/compiler/rustc_mir_dataflow/src/value_analysis.rs b/compiler/rustc_mir_dataflow/src/value_analysis.rs
index 766e0257efd..1eea8eef0ad 100644
--- a/compiler/rustc_mir_dataflow/src/value_analysis.rs
+++ b/compiler/rustc_mir_dataflow/src/value_analysis.rs
@@ -269,8 +269,8 @@ pub trait ValueAnalysis<'tcx> {
                 return self.handle_switch_int(discr, targets, state);
             }
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Assert { .. }
diff --git a/compiler/rustc_mir_transform/src/check_unsafety.rs b/compiler/rustc_mir_transform/src/check_unsafety.rs
index 58e9786ec1a..e72db1a59a0 100644
--- a/compiler/rustc_mir_transform/src/check_unsafety.rs
+++ b/compiler/rustc_mir_transform/src/check_unsafety.rs
@@ -57,8 +57,8 @@ impl<'tcx> Visitor<'tcx> for UnsafetyChecker<'_, 'tcx> {
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Assert { .. }
             | TerminatorKind::GeneratorDrop
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::FalseEdge { .. }
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 7529ed8186b..a793b384d81 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -180,6 +180,10 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         throw_machine_stop_str!("calling functions isn't supported in ConstProp")
     }
 
+    fn panic_nounwind(_ecx: &mut InterpCx<'mir, 'tcx, Self>, _msg: &str) -> InterpResult<'tcx> {
+        throw_machine_stop_str!("panicking isn't supported in ConstProp")
+    }
+
     fn find_mir_or_eval_fn(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/const_prop_lint.rs b/compiler/rustc_mir_transform/src/const_prop_lint.rs
index ac07c25763b..4f8ca916d5b 100644
--- a/compiler/rustc_mir_transform/src/const_prop_lint.rs
+++ b/compiler/rustc_mir_transform/src/const_prop_lint.rs
@@ -678,8 +678,8 @@ impl<'tcx> Visitor<'tcx> for ConstPropagator<'_, 'tcx> {
             }
             // None of these have Operands to const-propagate.
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/counters.rs b/compiler/rustc_mir_transform/src/coverage/counters.rs
index d1f2f0c76c8..3d442e5dca9 100644
--- a/compiler/rustc_mir_transform/src/coverage/counters.rs
+++ b/compiler/rustc_mir_transform/src/coverage/counters.rs
@@ -14,36 +14,76 @@ use rustc_index::bit_set::BitSet;
 use rustc_index::IndexVec;
 use rustc_middle::mir::coverage::*;
 
+use std::fmt::{self, Debug};
+
+/// The coverage counter or counter expression associated with a particular
+/// BCB node or BCB edge.
+#[derive(Clone)]
+pub(super) enum BcbCounter {
+    Counter { id: CounterId },
+    Expression { id: ExpressionId, lhs: Operand, op: Op, rhs: Operand },
+}
+
+impl BcbCounter {
+    fn is_expression(&self) -> bool {
+        matches!(self, Self::Expression { .. })
+    }
+
+    pub(super) fn as_operand(&self) -> Operand {
+        match *self {
+            BcbCounter::Counter { id, .. } => Operand::Counter(id),
+            BcbCounter::Expression { id, .. } => Operand::Expression(id),
+        }
+    }
+}
+
+impl Debug for BcbCounter {
+    fn fmt(&self, fmt: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self {
+            Self::Counter { id, .. } => write!(fmt, "Counter({:?})", id.index()),
+            Self::Expression { id, lhs, op, rhs } => write!(
+                fmt,
+                "Expression({:?}) = {:?} {} {:?}",
+                id.index(),
+                lhs,
+                match op {
+                    Op::Add => "+",
+                    Op::Subtract => "-",
+                },
+                rhs,
+            ),
+        }
+    }
+}
+
 /// Generates and stores coverage counter and coverage expression information
 /// associated with nodes/edges in the BCB graph.
 pub(super) struct CoverageCounters {
-    function_source_hash: u64,
     next_counter_id: CounterId,
     next_expression_id: ExpressionId,
 
     /// Coverage counters/expressions that are associated with individual BCBs.
-    bcb_counters: IndexVec<BasicCoverageBlock, Option<CoverageKind>>,
+    bcb_counters: IndexVec<BasicCoverageBlock, Option<BcbCounter>>,
     /// Coverage counters/expressions that are associated with the control-flow
     /// edge between two BCBs.
-    bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), CoverageKind>,
+    bcb_edge_counters: FxHashMap<(BasicCoverageBlock, BasicCoverageBlock), BcbCounter>,
     /// Tracks which BCBs have a counter associated with some incoming edge.
     /// Only used by debug assertions, to verify that BCBs with incoming edge
     /// counters do not have their own physical counters (expressions are allowed).
     bcb_has_incoming_edge_counters: BitSet<BasicCoverageBlock>,
     /// Expression nodes that are not directly associated with any particular
     /// BCB/edge, but are needed as operands to more complex expressions.
-    /// These are always `CoverageKind::Expression`.
-    pub(super) intermediate_expressions: Vec<CoverageKind>,
+    /// These are always [`BcbCounter::Expression`].
+    pub(super) intermediate_expressions: Vec<BcbCounter>,
 
     pub debug_counters: DebugCounters,
 }
 
 impl CoverageCounters {
-    pub(super) fn new(function_source_hash: u64, basic_coverage_blocks: &CoverageGraph) -> Self {
+    pub(super) fn new(basic_coverage_blocks: &CoverageGraph) -> Self {
         let num_bcbs = basic_coverage_blocks.num_nodes();
 
         Self {
-            function_source_hash,
             next_counter_id: CounterId::START,
             next_expression_id: ExpressionId::START,
 
@@ -57,12 +97,12 @@ impl CoverageCounters {
     }
 
     /// Activate the `DebugCounters` data structures, to provide additional debug formatting
-    /// features when formatting `CoverageKind` (counter) values.
+    /// features when formatting [`BcbCounter`] (counter) values.
     pub fn enable_debug(&mut self) {
         self.debug_counters.enable();
     }
 
-    /// Makes `CoverageKind` `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
+    /// Makes [`BcbCounter`] `Counter`s and `Expressions` for the `BasicCoverageBlock`s directly or
     /// indirectly associated with `CoverageSpans`, and accumulates additional `Expression`s
     /// representing intermediate values.
     pub fn make_bcb_counters(
@@ -73,14 +113,11 @@ impl CoverageCounters {
         MakeBcbCounters::new(self, basic_coverage_blocks).make_bcb_counters(coverage_spans)
     }
 
-    fn make_counter<F>(&mut self, debug_block_label_fn: F) -> CoverageKind
+    fn make_counter<F>(&mut self, debug_block_label_fn: F) -> BcbCounter
     where
         F: Fn() -> Option<String>,
     {
-        let counter = CoverageKind::Counter {
-            function_source_hash: self.function_source_hash,
-            id: self.next_counter(),
-        };
+        let counter = BcbCounter::Counter { id: self.next_counter() };
         if self.debug_counters.is_enabled() {
             self.debug_counters.add_counter(&counter, (debug_block_label_fn)());
         }
@@ -93,19 +130,19 @@ impl CoverageCounters {
         op: Op,
         rhs: Operand,
         debug_block_label_fn: F,
-    ) -> CoverageKind
+    ) -> BcbCounter
     where
         F: Fn() -> Option<String>,
     {
         let id = self.next_expression();
-        let expression = CoverageKind::Expression { id, lhs, op, rhs };
+        let expression = BcbCounter::Expression { id, lhs, op, rhs };
         if self.debug_counters.is_enabled() {
             self.debug_counters.add_counter(&expression, (debug_block_label_fn)());
         }
         expression
     }
 
-    pub fn make_identity_counter(&mut self, counter_operand: Operand) -> CoverageKind {
+    pub fn make_identity_counter(&mut self, counter_operand: Operand) -> BcbCounter {
         let some_debug_block_label = if self.debug_counters.is_enabled() {
             self.debug_counters.some_block_label(counter_operand).cloned()
         } else {
@@ -134,7 +171,7 @@ impl CoverageCounters {
     fn set_bcb_counter(
         &mut self,
         bcb: BasicCoverageBlock,
-        counter_kind: CoverageKind,
+        counter_kind: BcbCounter,
     ) -> Result<Operand, Error> {
         debug_assert!(
             // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -158,7 +195,7 @@ impl CoverageCounters {
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bcb: BasicCoverageBlock,
-        counter_kind: CoverageKind,
+        counter_kind: BcbCounter,
     ) -> Result<Operand, Error> {
         if level_enabled!(tracing::Level::DEBUG) {
             // If the BCB has an edge counter (to be injected into a new `BasicBlock`), it can also
@@ -183,17 +220,17 @@ impl CoverageCounters {
         }
     }
 
-    pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&CoverageKind> {
+    pub(super) fn bcb_counter(&self, bcb: BasicCoverageBlock) -> Option<&BcbCounter> {
         self.bcb_counters[bcb].as_ref()
     }
 
-    pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<CoverageKind> {
+    pub(super) fn take_bcb_counter(&mut self, bcb: BasicCoverageBlock) -> Option<BcbCounter> {
         self.bcb_counters[bcb].take()
     }
 
     pub(super) fn drain_bcb_counters(
         &mut self,
-    ) -> impl Iterator<Item = (BasicCoverageBlock, CoverageKind)> + '_ {
+    ) -> impl Iterator<Item = (BasicCoverageBlock, BcbCounter)> + '_ {
         self.bcb_counters
             .iter_enumerated_mut()
             .filter_map(|(bcb, counter)| Some((bcb, counter.take()?)))
@@ -201,7 +238,7 @@ impl CoverageCounters {
 
     pub(super) fn drain_bcb_edge_counters(
         &mut self,
-    ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), CoverageKind)> + '_ {
+    ) -> impl Iterator<Item = ((BasicCoverageBlock, BasicCoverageBlock), BcbCounter)> + '_ {
         self.bcb_edge_counters.drain()
     }
 }
@@ -653,7 +690,7 @@ impl<'a> MakeBcbCounters<'a> {
         self.branch_counter(branch).is_none()
     }
 
-    fn branch_counter(&self, branch: &BcbBranch) -> Option<&CoverageKind> {
+    fn branch_counter(&self, branch: &BcbBranch) -> Option<&BcbCounter> {
         let to_bcb = branch.target_bcb;
         if let Some(from_bcb) = branch.edge_from_bcb {
             self.coverage_counters.bcb_edge_counters.get(&(from_bcb, to_bcb))
@@ -675,7 +712,7 @@ impl<'a> MakeBcbCounters<'a> {
     }
 
     #[inline]
-    fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         self.coverage_counters.debug_counters.format_counter(counter_kind)
     }
 }
diff --git a/compiler/rustc_mir_transform/src/coverage/debug.rs b/compiler/rustc_mir_transform/src/coverage/debug.rs
index d2c0c4ba069..af616c498fd 100644
--- a/compiler/rustc_mir_transform/src/coverage/debug.rs
+++ b/compiler/rustc_mir_transform/src/coverage/debug.rs
@@ -108,7 +108,7 @@
 //!         recursively, generating labels with nested operations, enclosed in parentheses
 //!         (for example: `bcb2 + (bcb0 - bcb1)`).
 
-use super::counters::CoverageCounters;
+use super::counters::{BcbCounter, CoverageCounters};
 use super::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
 use super::spans::CoverageSpan;
 
@@ -199,9 +199,9 @@ impl DebugOptions {
 
 fn bool_option_val(option: &str, some_strval: Option<&str>) -> bool {
     if let Some(val) = some_strval {
-        if vec!["yes", "y", "on", "true"].contains(&val) {
+        if ["yes", "y", "on", "true"].contains(&val) {
             true
-        } else if vec!["no", "n", "off", "false"].contains(&val) {
+        } else if ["no", "n", "off", "false"].contains(&val) {
             false
         } else {
             bug!(
@@ -247,11 +247,11 @@ impl Default for ExpressionFormat {
     }
 }
 
-/// If enabled, this struct maintains a map from `CoverageKind` IDs (as `Operand`) to
-/// the `CoverageKind` data and optional label (normally, the counter's associated
+/// If enabled, this struct maintains a map from `BcbCounter` IDs (as `Operand`) to
+/// the `BcbCounter` data and optional label (normally, the counter's associated
 /// `BasicCoverageBlock` format string, if any).
 ///
-/// Use `format_counter` to convert one of these `CoverageKind` counters to a debug output string,
+/// Use `format_counter` to convert one of these `BcbCounter` counters to a debug output string,
 /// as directed by the `DebugOptions`. This allows the format of counter labels in logs and dump
 /// files (including the `CoverageGraph` graphviz file) to be changed at runtime, via environment
 /// variable.
@@ -276,7 +276,7 @@ impl DebugCounters {
         self.some_counters.is_some()
     }
 
-    pub fn add_counter(&mut self, counter_kind: &CoverageKind, some_block_label: Option<String>) {
+    pub fn add_counter(&mut self, counter_kind: &BcbCounter, some_block_label: Option<String>) {
         if let Some(counters) = &mut self.some_counters {
             let id = counter_kind.as_operand();
             counters
@@ -291,21 +291,20 @@ impl DebugCounters {
         })
     }
 
-    pub fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    pub fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         match *counter_kind {
-            CoverageKind::Counter { .. } => {
+            BcbCounter::Counter { .. } => {
                 format!("Counter({})", self.format_counter_kind(counter_kind))
             }
-            CoverageKind::Expression { .. } => {
+            BcbCounter::Expression { .. } => {
                 format!("Expression({})", self.format_counter_kind(counter_kind))
             }
-            CoverageKind::Unreachable { .. } => "Unreachable".to_owned(),
         }
     }
 
-    fn format_counter_kind(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter_kind(&self, counter_kind: &BcbCounter) -> String {
         let counter_format = &debug_options().counter_format;
-        if let CoverageKind::Expression { id, lhs, op, rhs } = *counter_kind {
+        if let BcbCounter::Expression { id, lhs, op, rhs } = *counter_kind {
             if counter_format.operation {
                 return format!(
                     "{}{} {} {}",
@@ -346,7 +345,7 @@ impl DebugCounters {
         }
         if let Some(counters) = &self.some_counters {
             if let Some(DebugCounter { counter_kind, some_block_label }) = counters.get(&operand) {
-                if let CoverageKind::Expression { .. } = counter_kind {
+                if let BcbCounter::Expression { .. } = counter_kind {
                     if let Some(label) = some_block_label && debug_options().counter_format.block {
                         return format!(
                             "{}:({})",
@@ -366,12 +365,12 @@ impl DebugCounters {
 /// A non-public support class to `DebugCounters`.
 #[derive(Debug)]
 struct DebugCounter {
-    counter_kind: CoverageKind,
+    counter_kind: BcbCounter,
     some_block_label: Option<String>,
 }
 
 impl DebugCounter {
-    fn new(counter_kind: CoverageKind, some_block_label: Option<String>) -> Self {
+    fn new(counter_kind: BcbCounter, some_block_label: Option<String>) -> Self {
         Self { counter_kind, some_block_label }
     }
 }
@@ -380,9 +379,9 @@ impl DebugCounter {
 /// a Graphviz (.dot file) representation of the `CoverageGraph`, for debugging purposes.
 pub(super) struct GraphvizData {
     some_bcb_to_coverage_spans_with_counters:
-        Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, CoverageKind)>>>,
-    some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<CoverageKind>>>,
-    some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), CoverageKind>>,
+        Option<FxHashMap<BasicCoverageBlock, Vec<(CoverageSpan, BcbCounter)>>>,
+    some_bcb_to_dependency_counters: Option<FxHashMap<BasicCoverageBlock, Vec<BcbCounter>>>,
+    some_edge_to_counter: Option<FxHashMap<(BasicCoverageBlock, BasicBlock), BcbCounter>>,
 }
 
 impl GraphvizData {
@@ -409,7 +408,7 @@ impl GraphvizData {
         &mut self,
         bcb: BasicCoverageBlock,
         coverage_span: &CoverageSpan,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(bcb_to_coverage_spans_with_counters) =
             self.some_bcb_to_coverage_spans_with_counters.as_mut()
@@ -424,7 +423,7 @@ impl GraphvizData {
     pub fn get_bcb_coverage_spans_with_counters(
         &self,
         bcb: BasicCoverageBlock,
-    ) -> Option<&[(CoverageSpan, CoverageKind)]> {
+    ) -> Option<&[(CoverageSpan, BcbCounter)]> {
         if let Some(bcb_to_coverage_spans_with_counters) =
             self.some_bcb_to_coverage_spans_with_counters.as_ref()
         {
@@ -437,7 +436,7 @@ impl GraphvizData {
     pub fn add_bcb_dependency_counter(
         &mut self,
         bcb: BasicCoverageBlock,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_mut() {
             bcb_to_dependency_counters
@@ -447,7 +446,7 @@ impl GraphvizData {
         }
     }
 
-    pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[CoverageKind]> {
+    pub fn get_bcb_dependency_counters(&self, bcb: BasicCoverageBlock) -> Option<&[BcbCounter]> {
         if let Some(bcb_to_dependency_counters) = self.some_bcb_to_dependency_counters.as_ref() {
             bcb_to_dependency_counters.get(&bcb).map(Deref::deref)
         } else {
@@ -459,7 +458,7 @@ impl GraphvizData {
         &mut self,
         from_bcb: BasicCoverageBlock,
         to_bb: BasicBlock,
-        counter_kind: &CoverageKind,
+        counter_kind: &BcbCounter,
     ) {
         if let Some(edge_to_counter) = self.some_edge_to_counter.as_mut() {
             edge_to_counter
@@ -472,7 +471,7 @@ impl GraphvizData {
         &self,
         from_bcb: BasicCoverageBlock,
         to_bb: BasicBlock,
-    ) -> Option<&CoverageKind> {
+    ) -> Option<&BcbCounter> {
         if let Some(edge_to_counter) = self.some_edge_to_counter.as_ref() {
             edge_to_counter.get(&(from_bcb, to_bb))
         } else {
@@ -488,7 +487,7 @@ impl GraphvizData {
 pub(super) struct UsedExpressions {
     some_used_expression_operands: Option<FxHashMap<Operand, Vec<ExpressionId>>>,
     some_unused_expressions:
-        Option<Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
+        Option<Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)>>,
 }
 
 impl UsedExpressions {
@@ -506,16 +505,16 @@ impl UsedExpressions {
         self.some_used_expression_operands.is_some()
     }
 
-    pub fn add_expression_operands(&mut self, expression: &CoverageKind) {
+    pub fn add_expression_operands(&mut self, expression: &BcbCounter) {
         if let Some(used_expression_operands) = self.some_used_expression_operands.as_mut() {
-            if let CoverageKind::Expression { id, lhs, rhs, .. } = *expression {
+            if let BcbCounter::Expression { id, lhs, rhs, .. } = *expression {
                 used_expression_operands.entry(lhs).or_insert_with(Vec::new).push(id);
                 used_expression_operands.entry(rhs).or_insert_with(Vec::new).push(id);
             }
         }
     }
 
-    pub fn expression_is_used(&self, expression: &CoverageKind) -> bool {
+    pub fn expression_is_used(&self, expression: &BcbCounter) -> bool {
         if let Some(used_expression_operands) = self.some_used_expression_operands.as_ref() {
             used_expression_operands.contains_key(&expression.as_operand())
         } else {
@@ -525,7 +524,7 @@ impl UsedExpressions {
 
     pub fn add_unused_expression_if_not_found(
         &mut self,
-        expression: &CoverageKind,
+        expression: &BcbCounter,
         edge_from_bcb: Option<BasicCoverageBlock>,
         target_bcb: BasicCoverageBlock,
     ) {
@@ -540,11 +539,11 @@ impl UsedExpressions {
         }
     }
 
-    /// Return the list of unused counters (if any) as a tuple with the counter (`CoverageKind`),
+    /// Return the list of unused counters (if any) as a tuple with the counter (`BcbCounter`),
     /// optional `from_bcb` (if it was an edge counter), and `target_bcb`.
     pub fn get_unused_expressions(
         &self,
-    ) -> Vec<(CoverageKind, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
+    ) -> Vec<(BcbCounter, Option<BasicCoverageBlock>, BasicCoverageBlock)> {
         if let Some(unused_expressions) = self.some_unused_expressions.as_ref() {
             unused_expressions.clone()
         } else {
@@ -560,7 +559,7 @@ impl UsedExpressions {
         bcb_counters_without_direct_coverage_spans: &[(
             Option<BasicCoverageBlock>,
             BasicCoverageBlock,
-            CoverageKind,
+            BcbCounter,
         )],
     ) {
         if self.is_enabled() {
@@ -662,7 +661,7 @@ pub(super) fn dump_coverage_graphviz<'tcx>(
     basic_coverage_blocks: &CoverageGraph,
     coverage_counters: &CoverageCounters,
     graphviz_data: &GraphvizData,
-    intermediate_expressions: &[CoverageKind],
+    intermediate_expressions: &[BcbCounter],
     debug_used_expressions: &UsedExpressions,
 ) {
     let debug_counters = &coverage_counters.debug_counters;
@@ -743,9 +742,9 @@ fn bcb_to_string_sections<'tcx>(
     coverage_counters: &CoverageCounters,
     bcb: BasicCoverageBlock,
     bcb_data: &BasicCoverageBlockData,
-    some_coverage_spans_with_counters: Option<&[(CoverageSpan, CoverageKind)]>,
-    some_dependency_counters: Option<&[CoverageKind]>,
-    some_intermediate_expressions: Option<&[CoverageKind]>,
+    some_coverage_spans_with_counters: Option<&[(CoverageSpan, BcbCounter)]>,
+    some_dependency_counters: Option<&[BcbCounter]>,
+    some_intermediate_expressions: Option<&[BcbCounter]>,
 ) -> Vec<String> {
     let debug_counters = &coverage_counters.debug_counters;
 
diff --git a/compiler/rustc_mir_transform/src/coverage/graph.rs b/compiler/rustc_mir_transform/src/coverage/graph.rs
index 59b01ffec0f..d3d4fcd3a52 100644
--- a/compiler/rustc_mir_transform/src/coverage/graph.rs
+++ b/compiler/rustc_mir_transform/src/coverage/graph.rs
@@ -116,7 +116,7 @@ impl CoverageGraph {
 
             match term.kind {
                 TerminatorKind::Return { .. }
-                | TerminatorKind::Terminate
+                | TerminatorKind::UnwindTerminate
                 | TerminatorKind::Yield { .. }
                 | TerminatorKind::SwitchInt { .. } => {
                     // The `bb` has more than one _outgoing_ edge, or exits the function. Save the
@@ -146,7 +146,7 @@ impl CoverageGraph {
                 // is as intended. (See Issue #78544 for a possible future option to support
                 // coverage in test programs that panic.)
                 TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
+                | TerminatorKind::UnwindResume
                 | TerminatorKind::Unreachable
                 | TerminatorKind::Drop { .. }
                 | TerminatorKind::Call { .. }
diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs
index e08b6d6f6e8..8c9eae508b4 100644
--- a/compiler/rustc_mir_transform/src/coverage/mod.rs
+++ b/compiler/rustc_mir_transform/src/coverage/mod.rs
@@ -8,9 +8,9 @@ mod spans;
 #[cfg(test)]
 mod tests;
 
-use counters::CoverageCounters;
-use graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
-use spans::{CoverageSpan, CoverageSpans};
+use self::counters::{BcbCounter, CoverageCounters};
+use self::graph::{BasicCoverageBlock, BasicCoverageBlockData, CoverageGraph};
+use self::spans::{CoverageSpan, CoverageSpans};
 
 use crate::MirPass;
 
@@ -106,6 +106,7 @@ struct Instrumentor<'a, 'tcx> {
     source_file: Lrc<SourceFile>,
     fn_sig_span: Span,
     body_span: Span,
+    function_source_hash: u64,
     basic_coverage_blocks: CoverageGraph,
     coverage_counters: CoverageCounters,
 }
@@ -137,7 +138,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
         let function_source_hash = hash_mir_source(tcx, hir_body);
         let basic_coverage_blocks = CoverageGraph::from_mir(mir_body);
-        let coverage_counters = CoverageCounters::new(function_source_hash, &basic_coverage_blocks);
+        let coverage_counters = CoverageCounters::new(&basic_coverage_blocks);
 
         Self {
             pass_name,
@@ -146,6 +147,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             source_file,
             fn_sig_span,
             body_span,
+            function_source_hash,
             basic_coverage_blocks,
             coverage_counters,
         }
@@ -270,8 +272,11 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
 
         ////////////////////////////////////////////////////
         // Finally, inject the intermediate expressions collected along the way.
-        for intermediate_expression in self.coverage_counters.intermediate_expressions.drain(..) {
-            inject_intermediate_expression(self.mir_body, intermediate_expression);
+        for intermediate_expression in &self.coverage_counters.intermediate_expressions {
+            inject_intermediate_expression(
+                self.mir_body,
+                self.make_mir_coverage_kind(intermediate_expression),
+            );
         }
     }
 
@@ -309,19 +314,14 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             };
             graphviz_data.add_bcb_coverage_span_with_counter(bcb, &covspan, &counter_kind);
 
-            debug!(
-                "Calling make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
-                file_name,
-                self.source_file,
-                source_map.span_to_diagnostic_string(span),
-                source_map.span_to_diagnostic_string(body_span)
-            );
+            let code_region =
+                make_code_region(source_map, file_name, &self.source_file, span, body_span);
 
             inject_statement(
                 self.mir_body,
-                counter_kind,
+                self.make_mir_coverage_kind(&counter_kind),
                 self.bcb_leader_bb(bcb),
-                Some(make_code_region(source_map, file_name, &self.source_file, span, body_span)),
+                Some(code_region),
             );
         }
     }
@@ -367,7 +367,7 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
             );
 
             match counter_kind {
-                CoverageKind::Counter { .. } => {
+                BcbCounter::Counter { .. } => {
                     let inject_to_bb = if let Some(from_bcb) = edge_from_bcb {
                         // The MIR edge starts `from_bb` (the outgoing / last BasicBlock in
                         // `from_bcb`) and ends at `to_bb` (the incoming / first BasicBlock in the
@@ -400,12 +400,17 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
                         target_bb
                     };
 
-                    inject_statement(self.mir_body, counter_kind, inject_to_bb, None);
+                    inject_statement(
+                        self.mir_body,
+                        self.make_mir_coverage_kind(&counter_kind),
+                        inject_to_bb,
+                        None,
+                    );
                 }
-                CoverageKind::Expression { .. } => {
-                    inject_intermediate_expression(self.mir_body, counter_kind)
-                }
-                _ => bug!("CoverageKind should be a counter"),
+                BcbCounter::Expression { .. } => inject_intermediate_expression(
+                    self.mir_body,
+                    self.make_mir_coverage_kind(&counter_kind),
+                ),
             }
         }
     }
@@ -426,9 +431,20 @@ impl<'a, 'tcx> Instrumentor<'a, 'tcx> {
     }
 
     #[inline]
-    fn format_counter(&self, counter_kind: &CoverageKind) -> String {
+    fn format_counter(&self, counter_kind: &BcbCounter) -> String {
         self.coverage_counters.debug_counters.format_counter(counter_kind)
     }
+
+    fn make_mir_coverage_kind(&self, counter_kind: &BcbCounter) -> CoverageKind {
+        match *counter_kind {
+            BcbCounter::Counter { id } => {
+                CoverageKind::Counter { function_source_hash: self.function_source_hash, id }
+            }
+            BcbCounter::Expression { id, lhs, op, rhs } => {
+                CoverageKind::Expression { id, lhs, op, rhs }
+            }
+        }
+    }
 }
 
 fn inject_edge_counter_basic_block(
@@ -498,6 +514,14 @@ fn make_code_region(
     span: Span,
     body_span: Span,
 ) -> CodeRegion {
+    debug!(
+        "Called make_code_region(file_name={}, source_file={:?}, span={}, body_span={})",
+        file_name,
+        source_file,
+        source_map.span_to_diagnostic_string(span),
+        source_map.span_to_diagnostic_string(body_span)
+    );
+
     let (start_line, mut start_col) = source_file.lookup_file_pos(span.lo());
     let (end_line, end_col) = if span.hi() == span.lo() {
         let (end_line, mut end_col) = (start_line, start_col);
diff --git a/compiler/rustc_mir_transform/src/coverage/spans.rs b/compiler/rustc_mir_transform/src/coverage/spans.rs
index deebf5345ba..6fabaca524a 100644
--- a/compiler/rustc_mir_transform/src/coverage/spans.rs
+++ b/compiler/rustc_mir_transform/src/coverage/spans.rs
@@ -867,8 +867,8 @@ pub(super) fn filtered_terminator_span(terminator: &Terminator<'_>) -> Option<Sp
         }
 
         // Retain spans from all other terminators
-        TerminatorKind::Resume
-        | TerminatorKind::Terminate
+        TerminatorKind::UnwindResume
+        | TerminatorKind::UnwindTerminate
         | TerminatorKind::Return
         | TerminatorKind::Yield { .. }
         | TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_mir_transform/src/coverage/tests.rs b/compiler/rustc_mir_transform/src/coverage/tests.rs
index d797a6057a7..4a066ed3abd 100644
--- a/compiler/rustc_mir_transform/src/coverage/tests.rs
+++ b/compiler/rustc_mir_transform/src/coverage/tests.rs
@@ -34,7 +34,6 @@ use itertools::Itertools;
 use rustc_data_structures::graph::WithNumNodes;
 use rustc_data_structures::graph::WithSuccessors;
 use rustc_index::{Idx, IndexVec};
-use rustc_middle::mir::coverage::CoverageKind;
 use rustc_middle::mir::*;
 use rustc_middle::ty;
 use rustc_span::{self, BytePos, Pos, Span, DUMMY_SP};
@@ -675,8 +674,8 @@ fn test_make_bcb_counters() {
                 ));
             }
         }
-        let mut coverage_counters = counters::CoverageCounters::new(0, &basic_coverage_blocks);
-        let () = coverage_counters
+        let mut coverage_counters = counters::CoverageCounters::new(&basic_coverage_blocks);
+        coverage_counters
             .make_bcb_counters(&mut basic_coverage_blocks, &coverage_spans)
             .expect("should be Ok");
         assert_eq!(coverage_counters.intermediate_expressions.len(), 0);
@@ -685,7 +684,7 @@ fn test_make_bcb_counters() {
         assert_eq!(
             0, // bcb1 has a `Counter` with id = 0
             match coverage_counters.bcb_counter(bcb1).expect("should have a counter") {
-                CoverageKind::Counter { id, .. } => id,
+                counters::BcbCounter::Counter { id, .. } => id,
                 _ => panic!("expected a Counter"),
             }
             .as_u32()
@@ -695,7 +694,7 @@ fn test_make_bcb_counters() {
         assert_eq!(
             1, // bcb2 has a `Counter` with id = 1
             match coverage_counters.bcb_counter(bcb2).expect("should have a counter") {
-                CoverageKind::Counter { id, .. } => id,
+                counters::BcbCounter::Counter { id, .. } => id,
                 _ => panic!("expected a Counter"),
             }
             .as_u32()
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 8f4dc9f69e9..3a1ef3e7d64 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -541,6 +541,13 @@ impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for Dumm
         unimplemented!()
     }
 
+    fn panic_nounwind(
+        _ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        _msg: &str,
+    ) -> interpret::InterpResult<'tcx> {
+        unimplemented!()
+    }
+
     fn call_intrinsic(
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
diff --git a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
index 60ca3dfb2da..79645310a39 100644
--- a/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
+++ b/compiler/rustc_mir_transform/src/deduce_param_attrs.rs
@@ -203,7 +203,12 @@ pub fn deduced_param_attrs<'tcx>(
         body.local_decls.iter().skip(1).take(body.arg_count).enumerate().map(
             |(arg_index, local_decl)| DeducedParamAttrs {
                 read_only: !deduce_read_only.mutable_args.contains(arg_index)
-                    && local_decl.ty.is_freeze(tcx, param_env),
+                    // We must normalize here to reveal opaques and normalize
+                    // their substs, otherwise we'll see exponential blow-up in
+                    // compile times: #113372
+                    && tcx
+                        .normalize_erasing_regions(param_env, local_decl.ty)
+                        .is_freeze(tcx, param_env),
             },
         ),
     );
diff --git a/compiler/rustc_mir_transform/src/dest_prop.rs b/compiler/rustc_mir_transform/src/dest_prop.rs
index b73b72c3192..041f7c7221e 100644
--- a/compiler/rustc_mir_transform/src/dest_prop.rs
+++ b/compiler/rustc_mir_transform/src/dest_prop.rs
@@ -647,8 +647,8 @@ impl WriteInfo {
                 }
             }
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable { .. } => (),
             TerminatorKind::Drop { .. } => {
diff --git a/compiler/rustc_mir_transform/src/elaborate_drops.rs b/compiler/rustc_mir_transform/src/elaborate_drops.rs
index b6b1ae6d3c3..a80ae480089 100644
--- a/compiler/rustc_mir_transform/src/elaborate_drops.rs
+++ b/compiler/rustc_mir_transform/src/elaborate_drops.rs
@@ -470,7 +470,7 @@ impl<'b, 'tcx> ElaborateDropsCtxt<'b, 'tcx> {
                             // drop elaboration should handle that by itself
                             continue;
                         }
-                        TerminatorKind::Resume => {
+                        TerminatorKind::UnwindResume => {
                             // It is possible for `Resume` to be patched
                             // (in particular it can be patched to be replaced with
                             // a Goto; see `MirPatch::new`).
diff --git a/compiler/rustc_mir_transform/src/generator.rs b/compiler/rustc_mir_transform/src/generator.rs
index 797a1a86846..96077322575 100644
--- a/compiler/rustc_mir_transform/src/generator.rs
+++ b/compiler/rustc_mir_transform/src/generator.rs
@@ -50,8 +50,10 @@
 //! For generators with state 1 (returned) and state 2 (poisoned) it does nothing.
 //! Otherwise it drops all the values in scope at the last suspension point.
 
+use crate::abort_unwinding_calls;
 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};
@@ -64,6 +66,7 @@ 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::InstanceDef;
 use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_middle::ty::{GeneratorArgs, GenericArgsRef};
 use rustc_mir_dataflow::impls::{
@@ -1147,7 +1150,25 @@ fn create_generator_drop_shim<'tcx>(
     // unrelated code from the resume part of the function
     simplify::remove_dead_blocks(tcx, &mut body);
 
+    // Update the body's def to become the drop glue.
+    // This needs to be updated before the AbortUnwindingCalls pass.
+    let gen_instance = body.source.instance;
+    let drop_in_place = tcx.require_lang_item(LangItem::DropInPlace, None);
+    let drop_instance = InstanceDef::DropGlue(drop_in_place, Some(gen_ty));
+    body.source.instance = drop_instance;
+
+    pm::run_passes_no_validate(
+        tcx,
+        &mut body,
+        &[&abort_unwinding_calls::AbortUnwindingCalls],
+        None,
+    );
+
+    // Temporary change MirSource to generator's instance so that dump_mir produces more sensible
+    // filename.
+    body.source.instance = gen_instance;
     dump_mir(tcx, false, "generator_drop", &0, &body, |_, _| Ok(()));
+    body.source.instance = drop_instance;
 
     body
 }
@@ -1218,7 +1239,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
             // These never unwind.
             TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
@@ -1227,7 +1248,7 @@ fn can_unwind<'tcx>(tcx: TyCtxt<'tcx>, body: &Body<'tcx>) -> bool {
 
             // Resume will *continue* unwinding, but if there's no other unwinding terminator it
             // will never be reached.
-            TerminatorKind::Resume => {}
+            TerminatorKind::UnwindResume => {}
 
             TerminatorKind::Yield { .. } => {
                 unreachable!("`can_unwind` called before generator transform")
@@ -1258,14 +1279,14 @@ fn create_generator_resume_function<'tcx>(
         let source_info = SourceInfo::outermost(body.span);
         let poison_block = body.basic_blocks_mut().push(BasicBlockData {
             statements: vec![transform.set_discr(VariantIdx::new(POISONED), source_info)],
-            terminator: Some(Terminator { source_info, kind: TerminatorKind::Resume }),
+            terminator: Some(Terminator { source_info, kind: TerminatorKind::UnwindResume }),
             is_cleanup: true,
         });
 
         for (idx, block) in body.basic_blocks_mut().iter_enumerated_mut() {
             let source_info = block.terminator().source_info;
 
-            if let TerminatorKind::Resume = block.terminator().kind {
+            if let TerminatorKind::UnwindResume = block.terminator().kind {
                 // An existing `Resume` terminator is redirected to jump to our dedicated
                 // "poisoning block" above.
                 if idx != poison_block {
@@ -1317,6 +1338,8 @@ fn create_generator_resume_function<'tcx>(
     // unrelated code from the drop part of the function
     simplify::remove_dead_blocks(tcx, body);
 
+    pm::run_passes_no_validate(tcx, body, &[&abort_unwinding_calls::AbortUnwindingCalls], None);
+
     dump_mir(tcx, false, "generator_resume", &0, body, |_, _| Ok(()));
 }
 
@@ -1735,8 +1758,8 @@ impl<'tcx> Visitor<'tcx> for EnsureGeneratorFieldAssignmentsNeverAlias<'_> {
             TerminatorKind::Call { .. }
             | TerminatorKind::Goto { .. }
             | TerminatorKind::SwitchInt { .. }
-            | TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::Drop { .. }
diff --git a/compiler/rustc_mir_transform/src/inline.rs b/compiler/rustc_mir_transform/src/inline.rs
index fc9e18378d5..734e93783d1 100644
--- a/compiler/rustc_mir_transform/src/inline.rs
+++ b/compiler/rustc_mir_transform/src/inline.rs
@@ -839,7 +839,7 @@ impl<'tcx> Visitor<'tcx> for CostChecker<'_, 'tcx> {
                     self.cost += LANDINGPAD_PENALTY;
                 }
             }
-            TerminatorKind::Resume => self.cost += RESUME_PENALTY,
+            TerminatorKind::UnwindResume => self.cost += RESUME_PENALTY,
             TerminatorKind::InlineAsm { unwind, .. } => {
                 self.cost += INSTR_COST;
                 if let UnwindAction::Cleanup(_) = unwind {
@@ -1017,15 +1017,15 @@ impl<'tcx> MutVisitor<'tcx> for Integrator<'_, 'tcx> {
                     TerminatorKind::Unreachable
                 }
             }
-            TerminatorKind::Resume => {
+            TerminatorKind::UnwindResume => {
                 terminator.kind = match self.cleanup_block {
                     UnwindAction::Cleanup(tgt) => TerminatorKind::Goto { target: tgt },
-                    UnwindAction::Continue => TerminatorKind::Resume,
+                    UnwindAction::Continue => TerminatorKind::UnwindResume,
                     UnwindAction::Unreachable => TerminatorKind::Unreachable,
-                    UnwindAction::Terminate => TerminatorKind::Terminate,
+                    UnwindAction::Terminate => TerminatorKind::UnwindTerminate,
                 };
             }
-            TerminatorKind::Terminate => {}
+            TerminatorKind::UnwindTerminate => {}
             TerminatorKind::Unreachable => {}
             TerminatorKind::FalseEdge { ref mut real_target, ref mut imaginary_target } => {
                 *real_target = self.map_block(*real_target);
diff --git a/compiler/rustc_mir_transform/src/ref_prop.rs b/compiler/rustc_mir_transform/src/ref_prop.rs
index c17c791f9c3..49a940b5779 100644
--- a/compiler/rustc_mir_transform/src/ref_prop.rs
+++ b/compiler/rustc_mir_transform/src/ref_prop.rs
@@ -265,7 +265,6 @@ fn compute_replacement<'tcx>(
         targets,
         storage_to_remove,
         allowed_replacements,
-        fully_replacable_locals,
         any_replacement: false,
     };
 
@@ -346,7 +345,6 @@ struct Replacer<'tcx> {
     storage_to_remove: BitSet<Local>,
     allowed_replacements: FxHashSet<(Local, Location)>,
     any_replacement: bool,
-    fully_replacable_locals: BitSet<Local>,
 }
 
 impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
@@ -366,12 +364,6 @@ impl<'tcx> MutVisitor<'tcx> for Replacer<'tcx> {
             if let Some((&PlaceElem::Deref, rest)) = target.projection.split_last() {
                 *place = Place::from(target.local).project_deeper(rest, self.tcx);
                 self.any_replacement = true;
-            } else if self.fully_replacable_locals.contains(place.local)
-                && let Some(references) = debuginfo.references.checked_add(1)
-            {
-                debuginfo.references = references;
-                *place = target;
-                self.any_replacement = true;
             } else {
                 break
             }
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 4941c9edce3..5782adbb3ff 100644
--- a/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
+++ b/compiler/rustc_mir_transform/src/remove_noop_landing_pads.rs
@@ -6,8 +6,8 @@ use rustc_middle::ty::TyCtxt;
 use rustc_target::spec::PanicStrategy;
 
 /// A pass that removes noop landing pads and replaces jumps to them with
-/// `None`. This is important because otherwise LLVM generates terrible
-/// code for these.
+/// `UnwindAction::Continue`. This is important because otherwise LLVM generates
+/// terrible code for these.
 pub struct RemoveNoopLandingPads;
 
 impl<'tcx> MirPass<'tcx> for RemoveNoopLandingPads {
@@ -63,7 +63,7 @@ impl RemoveNoopLandingPads {
         let terminator = body[bb].terminator();
         match terminator.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::SwitchInt { .. }
             | TerminatorKind::FalseEdge { .. }
             | TerminatorKind::FalseUnwind { .. } => {
@@ -72,7 +72,7 @@ impl RemoveNoopLandingPads {
             TerminatorKind::GeneratorDrop
             | TerminatorKind::Yield { .. }
             | TerminatorKind::Return
-            | TerminatorKind::Terminate
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Unreachable
             | TerminatorKind::Call { .. }
             | TerminatorKind::Assert { .. }
@@ -84,7 +84,17 @@ impl RemoveNoopLandingPads {
     fn remove_nop_landing_pads(&self, body: &mut Body<'_>) {
         debug!("body: {:#?}", body);
 
-        // make sure there's a resume block
+        // Skip the pass if there are no blocks with a resume terminator.
+        let has_resume = body
+            .basic_blocks
+            .iter_enumerated()
+            .any(|(_bb, block)| matches!(block.terminator().kind, TerminatorKind::UnwindResume));
+        if !has_resume {
+            debug!("remove_noop_landing_pads: no resume block in MIR");
+            return;
+        }
+
+        // make sure there's a resume block without any statements
         let resume_block = {
             let mut patch = MirPatch::new(body);
             let resume_block = patch.resume_block();
diff --git a/compiler/rustc_mir_transform/src/separate_const_switch.rs b/compiler/rustc_mir_transform/src/separate_const_switch.rs
index 1d8e54cdca0..de1b80585d1 100644
--- a/compiler/rustc_mir_transform/src/separate_const_switch.rs
+++ b/compiler/rustc_mir_transform/src/separate_const_switch.rs
@@ -108,13 +108,13 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                         }
 
                         // The following terminators are not allowed
-                        TerminatorKind::Resume
+                        TerminatorKind::UnwindResume
                         | TerminatorKind::Drop { .. }
                         | TerminatorKind::Call { .. }
                         | TerminatorKind::Assert { .. }
                         | TerminatorKind::FalseUnwind { .. }
                         | TerminatorKind::Yield { .. }
-                        | TerminatorKind::Terminate
+                        | TerminatorKind::UnwindTerminate
                         | TerminatorKind::Return
                         | TerminatorKind::Unreachable
                         | TerminatorKind::InlineAsm { .. }
@@ -165,8 +165,8 @@ pub fn separate_const_switch(body: &mut Body<'_>) -> usize {
                 });
             }
 
-            TerminatorKind::Resume
-            | TerminatorKind::Terminate
+            TerminatorKind::UnwindResume
+            | TerminatorKind::UnwindTerminate
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
             | TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_mir_transform/src/shim.rs b/compiler/rustc_mir_transform/src/shim.rs
index 5e8ba4f544c..079cf9eb4e9 100644
--- a/compiler/rustc_mir_transform/src/shim.rs
+++ b/compiler/rustc_mir_transform/src/shim.rs
@@ -71,8 +71,17 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
             // of this function. Is this intentional?
             if let Some(ty::Generator(gen_def_id, args, _)) = ty.map(Ty::kind) {
                 let body = tcx.optimized_mir(*gen_def_id).generator_drop().unwrap();
-                let body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
+                let mut body = EarlyBinder::bind(body.clone()).instantiate(tcx, args);
                 debug!("make_shim({:?}) = {:?}", instance, body);
+
+                // Run empty passes to mark phase change and perform validation.
+                pm::run_passes(
+                    tcx,
+                    &mut body,
+                    &[],
+                    Some(MirPhase::Runtime(RuntimePhase::Optimized)),
+                );
+
                 return body;
             }
 
@@ -90,7 +99,11 @@ fn make_shim<'tcx>(tcx: TyCtxt<'tcx>, instance: ty::InstanceDef<'tcx>) -> Body<'
     };
     debug!("make_shim({:?}) = untransformed {:?}", instance, result);
 
-    pm::run_passes(
+    // We don't validate MIR here because the shims may generate code that's
+    // only valid in a reveal-all param-env. However, since we do initial
+    // validation with the MirBuilt phase, which uses a user-facing param-env.
+    // This causes validation errors when TAITs are involved.
+    pm::run_passes_no_validate(
         tcx,
         &mut result,
         &[
@@ -574,7 +587,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         I: IntoIterator<Item = Ty<'tcx>>,
     {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
-        let unwind = self.block(vec![], TerminatorKind::Resume, true);
+        let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
         let target = self.block(vec![], TerminatorKind::Return, false);
 
         let _final_cleanup_block = self.clone_fields(dest, src, target, unwind, tys);
@@ -588,7 +601,7 @@ impl<'tcx> CloneShimBuilder<'tcx> {
         args: GeneratorArgs<'tcx>,
     ) {
         self.block(vec![], TerminatorKind::Goto { target: self.block_index_offset(3) }, false);
-        let unwind = self.block(vec![], TerminatorKind::Resume, true);
+        let unwind = self.block(vec![], TerminatorKind::UnwindResume, true);
         // This will get overwritten with a switch once we know the target blocks
         let switch = self.block(vec![], TerminatorKind::Unreachable, false);
         let unwind = self.clone_fields(dest, src, switch, unwind, args.upvar_tys());
@@ -845,7 +858,7 @@ fn build_call_shim<'tcx>(
         );
 
         // BB #4 - resume
-        block(&mut blocks, vec![], TerminatorKind::Resume, true);
+        block(&mut blocks, vec![], TerminatorKind::UnwindResume, true);
     }
 
     let mut body =
diff --git a/compiler/rustc_monomorphize/src/collector.rs b/compiler/rustc_monomorphize/src/collector.rs
index 55b14ce1c3e..cd7908e75e2 100644
--- a/compiler/rustc_monomorphize/src/collector.rs
+++ b/compiler/rustc_monomorphize/src/collector.rs
@@ -776,7 +776,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
                     self.output.push(create_fn_mono_item(tcx, instance, source));
                 }
             }
-            mir::TerminatorKind::Terminate { .. } => {
+            mir::TerminatorKind::UnwindTerminate { .. } => {
                 let instance = Instance::mono(
                     tcx,
                     tcx.require_lang_item(LangItem::PanicCannotUnwind, Some(source)),
@@ -787,7 +787,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirUsedCollector<'a, 'tcx> {
             }
             mir::TerminatorKind::Goto { .. }
             | mir::TerminatorKind::SwitchInt { .. }
-            | mir::TerminatorKind::Resume
+            | mir::TerminatorKind::UnwindResume
             | mir::TerminatorKind::Return
             | mir::TerminatorKind::Unreachable => {}
             mir::TerminatorKind::GeneratorDrop
diff --git a/compiler/rustc_parse/messages.ftl b/compiler/rustc_parse/messages.ftl
index 6888127f36c..34cc0998c9b 100644
--- a/compiler/rustc_parse/messages.ftl
+++ b/compiler/rustc_parse/messages.ftl
@@ -310,8 +310,8 @@ parse_inclusive_range_no_end = inclusive range with no end
     .suggestion_open_range = use `..` instead
     .note = inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-parse_incorrect_braces_trait_bounds = incorrect braces around trait bounds
-    .suggestion = remove the parentheses
+parse_incorrect_parens_trait_bounds = incorrect parentheses around trait bounds
+parse_incorrect_parens_trait_bounds_sugg = fix the parentheses
 
 parse_incorrect_semicolon =
     expected item, found `;`
diff --git a/compiler/rustc_parse/src/errors.rs b/compiler/rustc_parse/src/errors.rs
index 26f38c9156a..e0b1e3678e4 100644
--- a/compiler/rustc_parse/src/errors.rs
+++ b/compiler/rustc_parse/src/errors.rs
@@ -2636,21 +2636,24 @@ pub(crate) struct MissingPlusBounds {
 }
 
 #[derive(Diagnostic)]
-#[diag(parse_incorrect_braces_trait_bounds)]
-pub(crate) struct IncorrectBracesTraitBounds {
+#[diag(parse_incorrect_parens_trait_bounds)]
+pub(crate) struct IncorrectParensTraitBounds {
     #[primary_span]
     pub span: Vec<Span>,
     #[subdiagnostic]
-    pub sugg: IncorrectBracesTraitBoundsSugg,
+    pub sugg: IncorrectParensTraitBoundsSugg,
 }
 
 #[derive(Subdiagnostic)]
-#[multipart_suggestion(parse_suggestion, applicability = "machine-applicable")]
-pub(crate) struct IncorrectBracesTraitBoundsSugg {
+#[multipart_suggestion(
+    parse_incorrect_parens_trait_bounds_sugg,
+    applicability = "machine-applicable"
+)]
+pub(crate) struct IncorrectParensTraitBoundsSugg {
     #[suggestion_part(code = " ")]
-    pub l: Span,
-    #[suggestion_part(code = "")]
-    pub r: Span,
+    pub wrong_span: Span,
+    #[suggestion_part(code = "(")]
+    pub new_span: Span,
 }
 
 #[derive(Diagnostic)]
diff --git a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
index 446472d1294..b659c40b233 100644
--- a/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
+++ b/compiler/rustc_parse/src/lexer/unescape_error_reporting.rs
@@ -80,20 +80,14 @@ pub(crate) fn emit_unescape_error(
             let sugg = sugg.unwrap_or_else(|| {
                 let prefix = mode.prefix_noraw();
                 let mut escaped = String::with_capacity(lit.len());
-                let mut chrs = lit.chars().peekable();
-                while let Some(first) = chrs.next() {
-                    match (first, chrs.peek()) {
-                        ('\\', Some('"')) => {
-                            escaped.push('\\');
-                            escaped.push('"');
-                            chrs.next();
-                        }
-                        ('"', _) => {
-                            escaped.push('\\');
-                            escaped.push('"')
-                        }
-                        (c, _) => escaped.push(c),
-                    };
+                let mut in_escape = false;
+                for c in lit.chars() {
+                    match c {
+                        '\\' => in_escape = !in_escape,
+                        '"' if !in_escape => escaped.push('\\'),
+                        _ => in_escape = false,
+                    }
+                    escaped.push(c);
                 }
                 let sugg = format!("{prefix}\"{escaped}\"");
                 MoreThanOneCharSugg::Quotes {
diff --git a/compiler/rustc_parse/src/parser/expr.rs b/compiler/rustc_parse/src/parser/expr.rs
index e409c7c6781..9ae3ef6172c 100644
--- a/compiler/rustc_parse/src/parser/expr.rs
+++ b/compiler/rustc_parse/src/parser/expr.rs
@@ -22,6 +22,7 @@ use rustc_ast::{AnonConst, BinOp, BinOpKind, FnDecl, FnRetTy, MacCall, Param, Ty
 use rustc_ast::{Arm, Async, BlockCheckMode, Expr, ExprKind, Label, Movability, RangeLimits};
 use rustc_ast::{ClosureBinder, MetaItemLit, StmtKind};
 use rustc_ast_pretty::pprust;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
     AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, IntoDiagnostic,
     PResult, StashKey,
@@ -193,13 +194,7 @@ impl<'a> Parser<'a> {
 
         self.expected_tokens.push(TokenType::Operator);
         while let Some(op) = self.check_assoc_op() {
-            // Adjust the span for interpolated LHS to point to the `$lhs` token
-            // and not to what it refers to.
-            let lhs_span = match self.prev_token.kind {
-                TokenKind::Interpolated(..) => self.prev_token.span,
-                _ => lhs.span,
-            };
-
+            let lhs_span = self.interpolated_or_expr_span(&lhs);
             let cur_op_span = self.token.span;
             let restrictions = if op.node.is_assign_like() {
                 self.restrictions & Restrictions::NO_STRUCT_LITERAL
@@ -626,8 +621,8 @@ impl<'a> Parser<'a> {
 
     fn parse_expr_prefix_common(&mut self, lo: Span) -> PResult<'a, (Span, P<Expr>)> {
         self.bump();
-        let expr = self.parse_expr_prefix(None);
-        let (span, expr) = self.interpolated_or_expr_span(expr)?;
+        let expr = self.parse_expr_prefix(None)?;
+        let span = self.interpolated_or_expr_span(&expr);
         Ok((lo.to(span), expr))
     }
 
@@ -702,20 +697,12 @@ impl<'a> Parser<'a> {
         self.parse_expr_unary(lo, UnOp::Not)
     }
 
-    /// Returns the span of expr, if it was not interpolated or the span of the interpolated token.
-    fn interpolated_or_expr_span(
-        &self,
-        expr: PResult<'a, P<Expr>>,
-    ) -> PResult<'a, (Span, P<Expr>)> {
-        expr.map(|e| {
-            (
-                match self.prev_token.kind {
-                    TokenKind::Interpolated(..) => self.prev_token.span,
-                    _ => e.span,
-                },
-                e,
-            )
-        })
+    /// Returns the span of expr if it was not interpolated, or the span of the interpolated token.
+    fn interpolated_or_expr_span(&self, expr: &Expr) -> Span {
+        match self.prev_token.kind {
+            TokenKind::Interpolated(..) => self.prev_token.span,
+            _ => expr.span,
+        }
     }
 
     fn parse_assoc_op_cast(
@@ -898,8 +885,8 @@ impl<'a> Parser<'a> {
             self.parse_expr_prefix_range(None)
         } else {
             self.parse_expr_prefix(None)
-        };
-        let (hi, expr) = self.interpolated_or_expr_span(expr)?;
+        }?;
+        let hi = self.interpolated_or_expr_span(&expr);
         let span = lo.to(hi);
         if let Some(lt) = lifetime {
             self.error_remove_borrow_lifetime(span, lt.ident.span);
@@ -930,8 +917,8 @@ impl<'a> Parser<'a> {
     fn parse_expr_dot_or_call(&mut self, attrs: Option<AttrWrapper>) -> PResult<'a, P<Expr>> {
         let attrs = self.parse_or_use_outer_attributes(attrs)?;
         self.collect_tokens_for_expr(attrs, |this, attrs| {
-            let base = this.parse_expr_bottom();
-            let (span, base) = this.interpolated_or_expr_span(base)?;
+            let base = this.parse_expr_bottom()?;
+            let span = this.interpolated_or_expr_span(&base);
             this.parse_expr_dot_or_call_with(base, span, attrs)
         })
     }
@@ -2503,7 +2490,7 @@ impl<'a> Parser<'a> {
         let else_span = self.prev_token.span; // `else`
         let attrs = self.parse_outer_attributes()?; // For recovery.
         let expr = if self.eat_keyword(kw::If) {
-            self.parse_expr_if()?
+            ensure_sufficient_stack(|| self.parse_expr_if())?
         } else if self.check(&TokenKind::OpenDelim(Delimiter::Brace)) {
             self.parse_simple_block()?
         } else {
diff --git a/compiler/rustc_parse/src/parser/mod.rs b/compiler/rustc_parse/src/parser/mod.rs
index ce4d4a60551..77c59bb3881 100644
--- a/compiler/rustc_parse/src/parser/mod.rs
+++ b/compiler/rustc_parse/src/parser/mod.rs
@@ -1052,33 +1052,48 @@ impl<'a> Parser<'a> {
     }
 
     /// Look-ahead `dist` tokens of `self.token` and get access to that token there.
-    /// When `dist == 0` then the current token is looked at.
+    /// When `dist == 0` then the current token is looked at. `Eof` will be
+    /// returned if the look-ahead is any distance past the end of the tokens.
     pub fn look_ahead<R>(&self, dist: usize, looker: impl FnOnce(&Token) -> R) -> R {
         if dist == 0 {
             return looker(&self.token);
         }
 
-        let tree_cursor = &self.token_cursor.tree_cursor;
         if let Some(&(_, delim, span)) = self.token_cursor.stack.last()
             && delim != Delimiter::Invisible
         {
+            // We are not in the outermost token stream, and the token stream
+            // we are in has non-skipped delimiters. Look for skipped
+            // delimiters in the lookahead range.
+            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, _)))
             });
             if all_normal {
+                // There were no skipped delimiters. Do lookahead by plain indexing.
                 return match tree_cursor.look_ahead(dist - 1) {
-                    Some(tree) => match tree {
-                        TokenTree::Token(token, _) => looker(token),
-                        TokenTree::Delimited(dspan, delim, _) => {
-                            looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                    Some(tree) => {
+                        // Indexing stayed within the current token stream.
+                        match tree {
+                            TokenTree::Token(token, _) => looker(token),
+                            TokenTree::Delimited(dspan, delim, _) => {
+                                looker(&Token::new(token::OpenDelim(*delim), dspan.open))
+                            }
                         }
-                    },
-                    None => looker(&Token::new(token::CloseDelim(delim), span.close)),
+                    }
+                    None => {
+                        // Indexing went past the end of the current token
+                        // stream. Use the close delimiter, no matter how far
+                        // ahead `dist` went.
+                        looker(&Token::new(token::CloseDelim(delim), span.close))
+                    }
                 };
             }
         }
 
+        // We are in a more complex case. Just clone the token cursor and use
+        // `next`, skipping delimiters as necessary. Slow but simple.
         let mut cursor = self.token_cursor.clone();
         let mut i = 0;
         let mut token = Token::dummy();
@@ -1476,7 +1491,7 @@ pub enum FlatToken {
 }
 
 #[derive(Debug)]
-pub enum NtOrTt {
+pub enum ParseNtResult {
     Nt(Nonterminal),
     Tt(TokenTree),
 }
diff --git a/compiler/rustc_parse/src/parser/nonterminal.rs b/compiler/rustc_parse/src/parser/nonterminal.rs
index f5681532b3a..ff059a7e865 100644
--- a/compiler/rustc_parse/src/parser/nonterminal.rs
+++ b/compiler/rustc_parse/src/parser/nonterminal.rs
@@ -1,5 +1,5 @@
 use rustc_ast::ptr::P;
-use rustc_ast::token::{self, Delimiter, NonterminalKind, Token};
+use rustc_ast::token::{self, Delimiter, Nonterminal::*, NonterminalKind, Token};
 use rustc_ast::HasTokens;
 use rustc_ast_pretty::pprust;
 use rustc_errors::IntoDiagnostic;
@@ -8,7 +8,7 @@ use rustc_span::symbol::{kw, Ident};
 
 use crate::errors::UnexpectedNonterminal;
 use crate::parser::pat::{CommaRecoveryMode, RecoverColon, RecoverComma};
-use crate::parser::{FollowedByType, ForceCollect, NtOrTt, Parser, PathStyle};
+use crate::parser::{FollowedByType, ForceCollect, ParseNtResult, Parser, PathStyle};
 
 impl<'a> Parser<'a> {
     /// Checks whether a non-terminal may begin with a particular token.
@@ -20,10 +20,21 @@ impl<'a> Parser<'a> {
     pub fn nonterminal_may_begin_with(kind: NonterminalKind, token: &Token) -> bool {
         /// Checks whether the non-terminal may contain a single (non-keyword) identifier.
         fn may_be_ident(nt: &token::Nonterminal) -> bool {
-            !matches!(
-                *nt,
-                token::NtItem(_) | token::NtBlock(_) | token::NtVis(_) | token::NtLifetime(_)
-            )
+            match nt {
+                NtStmt(_)
+                | NtPat(_)
+                | NtExpr(_)
+                | NtTy(_)
+                | NtIdent(..)
+                | NtLiteral(_) // `true`, `false`
+                | NtMeta(_)
+                | NtPath(_) => true,
+
+                NtItem(_)
+                | NtBlock(_)
+                | NtVis(_)
+                | NtLifetime(_) => false,
+            }
         }
 
         match kind {
@@ -44,27 +55,19 @@ impl<'a> Parser<'a> {
             },
             NonterminalKind::Block => match &token.kind {
                 token::OpenDelim(Delimiter::Brace) => true,
-                token::Interpolated(nt) => !matches!(
-                    **nt,
-                    token::NtItem(_)
-                        | token::NtPat(_)
-                        | token::NtTy(_)
-                        | token::NtIdent(..)
-                        | token::NtMeta(_)
-                        | token::NtPath(_)
-                        | token::NtVis(_)
-                ),
+                token::Interpolated(nt) => match **nt {
+                    NtBlock(_) | NtLifetime(_) | NtStmt(_) | NtExpr(_) | NtLiteral(_) => true,
+                    NtItem(_) | NtPat(_) | NtTy(_) | NtIdent(..) | NtMeta(_) | NtPath(_)
+                    | NtVis(_) => false,
+                },
                 _ => false,
             },
             NonterminalKind::Path | NonterminalKind::Meta => match &token.kind {
                 token::ModSep | token::Ident(..) => true,
-                token::Interpolated(nt) => match **nt {
-                    token::NtPath(_) | token::NtMeta(_) => true,
-                    _ => may_be_ident(&nt),
-                },
+                token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
                 match &token.kind {
                 token::Ident(..) |                          // box, ref, mut, and other identifiers (can stricten)
                 token::OpenDelim(Delimiter::Parenthesis) |  // tuple pattern
@@ -79,7 +82,7 @@ impl<'a> Parser<'a> {
                 token::Lt |                                 // path (UFCS constant)
                 token::BinOp(token::Shl) => true,           // path (double UFCS)
                 // leading vert `|` or-pattern
-                token::BinOp(token::Or) =>  matches!(kind, NonterminalKind::PatWithOr {..}),
+                token::BinOp(token::Or) => matches!(kind, NonterminalKind::PatWithOr),
                 token::Interpolated(nt) => may_be_ident(nt),
                 _ => false,
             }
@@ -87,7 +90,7 @@ impl<'a> Parser<'a> {
             NonterminalKind::Lifetime => match &token.kind {
                 token::Lifetime(_) => true,
                 token::Interpolated(nt) => {
-                    matches!(**nt, token::NtLifetime(_))
+                    matches!(**nt, NtLifetime(_))
                 }
                 _ => false,
             },
@@ -100,18 +103,16 @@ impl<'a> Parser<'a> {
     /// Parse a non-terminal (e.g. MBE `:pat` or `:ident`). Inlined because there is only one call
     /// site.
     #[inline]
-    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, NtOrTt> {
-        // Any `Nonterminal` which stores its tokens (currently `NtItem` and `NtExpr`)
-        // needs to have them force-captured here.
+    pub fn parse_nonterminal(&mut self, kind: NonterminalKind) -> PResult<'a, ParseNtResult> {
         // A `macro_rules!` invocation may pass a captured item/expr to a proc-macro,
         // which requires having captured tokens available. Since we cannot determine
         // in advance whether or not a proc-macro will be (transitively) invoked,
         // we always capture tokens for any `Nonterminal` which needs them.
         let mut nt = match kind {
             // Note that TT is treated differently to all the others.
-            NonterminalKind::TT => return Ok(NtOrTt::Tt(self.parse_token_tree())),
+            NonterminalKind::TT => return Ok(ParseNtResult::Tt(self.parse_token_tree())),
             NonterminalKind::Item => match self.parse_item(ForceCollect::Yes)? {
-                Some(item) => token::NtItem(item),
+                Some(item) => NtItem(item),
                 None => {
                     return Err(UnexpectedNonterminal::Item(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
@@ -120,19 +121,19 @@ impl<'a> Parser<'a> {
             NonterminalKind::Block => {
                 // While a block *expression* may have attributes (e.g. `#[my_attr] { ... }`),
                 // the ':block' matcher does not support them
-                token::NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
+                NtBlock(self.collect_tokens_no_attrs(|this| this.parse_block())?)
             }
             NonterminalKind::Stmt => match self.parse_stmt(ForceCollect::Yes)? {
-                Some(s) => token::NtStmt(P(s)),
+                Some(s) => NtStmt(P(s)),
                 None => {
                     return Err(UnexpectedNonterminal::Statement(self.token.span)
                                .into_diagnostic(&self.sess.span_diagnostic));
                 }
             },
-            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr { .. } => {
-                token::NtPat(self.collect_tokens_no_attrs(|this| match kind {
+            NonterminalKind::PatParam { .. } | NonterminalKind::PatWithOr => {
+                NtPat(self.collect_tokens_no_attrs(|this| match kind {
                     NonterminalKind::PatParam { .. } => this.parse_pat_no_top_alt(None, None),
-                    NonterminalKind::PatWithOr { .. } => this.parse_pat_allow_top_alt(
+                    NonterminalKind::PatWithOr => this.parse_pat_allow_top_alt(
                         None,
                         RecoverComma::No,
                         RecoverColon::No,
@@ -142,16 +143,16 @@ impl<'a> Parser<'a> {
                 })?)
             }
 
-            NonterminalKind::Expr => token::NtExpr(self.parse_expr_force_collect()?),
+            NonterminalKind::Expr => NtExpr(self.parse_expr_force_collect()?),
             NonterminalKind::Literal => {
                 // The `:literal` matcher does not support attributes
-                token::NtLiteral(
+                NtLiteral(
                     self.collect_tokens_no_attrs(|this| this.parse_literal_maybe_minus())?,
                 )
             }
 
-            NonterminalKind::Ty => token::NtTy(
-                self.collect_tokens_no_attrs(|this| this.parse_no_question_mark_recover())?,
+            NonterminalKind::Ty => NtTy(
+                self.collect_tokens_no_attrs(|this| this.parse_ty_no_question_mark_recover())?,
             ),
 
             // this could be handled like a token, since it is one
@@ -159,7 +160,7 @@ impl<'a> Parser<'a> {
                 if let Some((ident, is_raw)) = get_macro_ident(&self.token) =>
             {
                 self.bump();
-                token::NtIdent(ident, is_raw)
+                NtIdent(ident, is_raw)
             }
             NonterminalKind::Ident => {
                 return Err(UnexpectedNonterminal::Ident {
@@ -167,16 +168,16 @@ impl<'a> Parser<'a> {
                     token: self.token.clone(),
                 }.into_diagnostic(&self.sess.span_diagnostic));
             }
-            NonterminalKind::Path => token::NtPath(
+            NonterminalKind::Path => NtPath(
                 P(self.collect_tokens_no_attrs(|this| this.parse_path(PathStyle::Type))?),
             ),
-            NonterminalKind::Meta => token::NtMeta(P(self.parse_attr_item(true)?)),
-            NonterminalKind::Vis => token::NtVis(
+            NonterminalKind::Meta => NtMeta(P(self.parse_attr_item(true)?)),
+            NonterminalKind::Vis => NtVis(
                 P(self.collect_tokens_no_attrs(|this| this.parse_visibility(FollowedByType::Yes))?),
             ),
             NonterminalKind::Lifetime => {
                 if self.check_lifetime() {
-                    token::NtLifetime(self.expect_lifetime().ident)
+                    NtLifetime(self.expect_lifetime().ident)
                 } else {
                     return Err(UnexpectedNonterminal::Lifetime {
                         span: self.token.span,
@@ -196,7 +197,7 @@ impl<'a> Parser<'a> {
             );
         }
 
-        Ok(NtOrTt::Nt(nt))
+        Ok(ParseNtResult::Nt(nt))
     }
 }
 
diff --git a/compiler/rustc_parse/src/parser/ty.rs b/compiler/rustc_parse/src/parser/ty.rs
index 3bb50b05aa3..2d888efb1f3 100644
--- a/compiler/rustc_parse/src/parser/ty.rs
+++ b/compiler/rustc_parse/src/parser/ty.rs
@@ -180,7 +180,7 @@ impl<'a> Parser<'a> {
         )
     }
 
-    pub(super) fn parse_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
+    pub(super) fn parse_ty_no_question_mark_recover(&mut self) -> PResult<'a, P<Ty>> {
         self.parse_ty_common(
             AllowPlus::Yes,
             AllowCVariadic::No,
@@ -714,6 +714,7 @@ impl<'a> Parser<'a> {
     /// ```
     fn parse_generic_bound(&mut self) -> PResult<'a, GenericBound> {
         let lo = self.token.span;
+        let leading_token = self.prev_token.clone();
         let has_parens = self.eat(&token::OpenDelim(Delimiter::Parenthesis));
         let inner_lo = self.token.span;
 
@@ -722,7 +723,7 @@ impl<'a> Parser<'a> {
             self.error_lt_bound_with_modifiers(modifiers);
             self.parse_generic_lt_bound(lo, inner_lo, has_parens)?
         } else {
-            self.parse_generic_ty_bound(lo, has_parens, modifiers)?
+            self.parse_generic_ty_bound(lo, has_parens, modifiers, &leading_token)?
         };
 
         Ok(bound)
@@ -827,6 +828,7 @@ impl<'a> Parser<'a> {
         lo: Span,
         has_parens: bool,
         modifiers: BoundModifiers,
+        leading_token: &Token,
     ) -> PResult<'a, GenericBound> {
         let mut lifetime_defs = self.parse_late_bound_lifetime_defs()?;
         let mut path = if self.token.is_keyword(kw::Fn)
@@ -873,18 +875,18 @@ impl<'a> Parser<'a> {
         }
 
         if has_parens {
-            if self.token.is_like_plus() {
-                // Someone has written something like `&dyn (Trait + Other)`. The correct code
-                // would be `&(dyn Trait + Other)`, but we don't have access to the appropriate
-                // span to suggest that. When written as `&dyn Trait + Other`, an appropriate
-                // suggestion is given.
+            // Someone has written something like `&dyn (Trait + Other)`. The correct code
+            // would be `&(dyn Trait + Other)`
+            if self.token.is_like_plus() && leading_token.is_keyword(kw::Dyn) {
                 let bounds = vec![];
                 self.parse_remaining_bounds(bounds, true)?;
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
-                let sp = vec![lo, self.prev_token.span];
-                self.sess.emit_err(errors::IncorrectBracesTraitBounds {
-                    span: sp,
-                    sugg: errors::IncorrectBracesTraitBoundsSugg { l: lo, r: self.prev_token.span },
+                self.sess.emit_err(errors::IncorrectParensTraitBounds {
+                    span: vec![lo, self.prev_token.span],
+                    sugg: errors::IncorrectParensTraitBoundsSugg {
+                        wrong_span: leading_token.span.shrink_to_hi().to(lo),
+                        new_span: leading_token.span.shrink_to_lo(),
+                    },
                 });
             } else {
                 self.expect(&token::CloseDelim(Delimiter::Parenthesis))?;
diff --git a/compiler/rustc_passes/src/layout_test.rs b/compiler/rustc_passes/src/layout_test.rs
index 0463ee2914b..a7a8af864ac 100644
--- a/compiler/rustc_passes/src/layout_test.rs
+++ b/compiler/rustc_passes/src/layout_test.rs
@@ -27,7 +27,6 @@ pub fn test_layout(tcx: TyCtxt<'_>) {
 }
 
 fn dump_layout_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId, attr: &Attribute) {
-    let tcx = tcx;
     let param_env = tcx.param_env(item_def_id);
     let ty = tcx.type_of(item_def_id).instantiate_identity();
     match tcx.layout_of(param_env.and(ty)) {
diff --git a/compiler/rustc_passes/src/liveness.rs b/compiler/rustc_passes/src/liveness.rs
index 0c0b8b6d094..20e996eaec4 100644
--- a/compiler/rustc_passes/src/liveness.rs
+++ b/compiler/rustc_passes/src/liveness.rs
@@ -1105,7 +1105,6 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
                 }
 
                 // Then do a second pass for inputs
-                let mut succ = succ;
                 for (op, _op_sp) in asm.operands.iter().rev() {
                     match op {
                         hir::InlineAsmOperand::In { expr, .. } => {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index c87db96a5dd..22d084c8e0b 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -311,6 +311,10 @@ enum LifetimeRibKind {
     /// error on default object bounds (e.g., `Box<dyn Foo>`).
     AnonymousReportError,
 
+    /// Resolves elided lifetimes to `'static`, but gives a warning that this behavior
+    /// is a bug and will be reverted soon.
+    AnonymousWarnToStatic(NodeId),
+
     /// Signal we cannot find which should be the anonymous lifetime.
     ElisionFailure,
 
@@ -1148,6 +1152,7 @@ impl<'a: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'a, '_, 'ast,
                             }
                             LifetimeRibKind::AnonymousCreateParameter { .. }
                             | LifetimeRibKind::AnonymousReportError
+                            | LifetimeRibKind::AnonymousWarnToStatic(_)
                             | LifetimeRibKind::Elided(_)
                             | LifetimeRibKind::ElisionFailure
                             | LifetimeRibKind::ConcreteAnonConst(_)
@@ -1515,6 +1520,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                                     // lifetime would be illegal.
                                     LifetimeRibKind::Item
                                     | LifetimeRibKind::AnonymousReportError
+                                    | LifetimeRibKind::AnonymousWarnToStatic(_)
                                     | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
                                     // An anonymous lifetime is legal here, and bound to the right
                                     // place, go ahead.
@@ -1576,7 +1582,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                 | LifetimeRibKind::Elided(_)
                 | LifetimeRibKind::Generics { .. }
                 | LifetimeRibKind::ElisionFailure
-                | LifetimeRibKind::AnonymousReportError => {}
+                | LifetimeRibKind::AnonymousReportError
+                | LifetimeRibKind::AnonymousWarnToStatic(_) => {}
             }
         }
 
@@ -1616,6 +1623,25 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     self.record_lifetime_res(lifetime.id, res, elision_candidate);
                     return;
                 }
+                LifetimeRibKind::AnonymousWarnToStatic(node_id) => {
+                    self.record_lifetime_res(lifetime.id, LifetimeRes::Static, elision_candidate);
+                    let msg = if elided {
+                        "`&` without an explicit lifetime name cannot be used here"
+                    } else {
+                        "`'_` cannot be used here"
+                    };
+                    self.r.lint_buffer.buffer_lint_with_diagnostic(
+                        lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
+                        node_id,
+                        lifetime.ident.span,
+                        msg,
+                        lint::BuiltinLintDiagnostics::AssociatedConstElidedLifetime {
+                            elided,
+                            span: lifetime.ident.span,
+                        },
+                    );
+                    return;
+                }
                 LifetimeRibKind::AnonymousReportError => {
                     let (msg, note) = if elided {
                         (
@@ -1811,7 +1837,8 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                     //
                     //     impl Foo for std::cell::Ref<u32> // note lack of '_
                     //     async fn foo(_: std::cell::Ref<u32>) { ... }
-                    LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. } => {
+                    LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
+                    | LifetimeRibKind::AnonymousWarnToStatic(_) => {
                         let sess = self.r.tcx.sess;
                         let mut err = rustc_errors::struct_span_err!(
                             sess,
@@ -2898,7 +2925,6 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         match &item.kind {
             AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
                 debug!("resolve_implementation AssocItemKind::Const");
-
                 self.with_generic_param_rib(
                     &generics.params,
                     RibKind::AssocItem,
@@ -2908,28 +2934,33 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
                         kind: LifetimeBinderKind::ConstItem,
                     },
                     |this| {
-                        // If this is a trait impl, ensure the const
-                        // exists in trait
-                        this.check_trait_item(
-                            item.id,
-                            item.ident,
-                            &item.kind,
-                            ValueNS,
-                            item.span,
-                            seen_trait_items,
-                            |i, s, c| ConstNotMemberOfTrait(i, s, c),
-                        );
+                        this.with_lifetime_rib(
+                            LifetimeRibKind::AnonymousWarnToStatic(item.id),
+                            |this| {
+                                // If this is a trait impl, ensure the const
+                                // exists in trait
+                                this.check_trait_item(
+                                    item.id,
+                                    item.ident,
+                                    &item.kind,
+                                    ValueNS,
+                                    item.span,
+                                    seen_trait_items,
+                                    |i, s, c| ConstNotMemberOfTrait(i, s, c),
+                                );
 
-                        this.visit_generics(generics);
-                        this.visit_ty(ty);
-                        if let Some(expr) = expr {
-                            // We allow arbitrary const expressions inside of associated consts,
-                            // even if they are potentially not const evaluatable.
-                            //
-                            // Type parameters can already be used and as associated consts are
-                            // not used as part of the type system, this is far less surprising.
-                            this.resolve_const_body(expr, None);
-                        }
+                                this.visit_generics(generics);
+                                this.visit_ty(ty);
+                                if let Some(expr) = expr {
+                                    // We allow arbitrary const expressions inside of associated consts,
+                                    // even if they are potentially not const evaluatable.
+                                    //
+                                    // Type parameters can already be used and as associated consts are
+                                    // not used as part of the type system, this is far less surprising.
+                                    this.resolve_const_body(expr, None);
+                                }
+                            },
+                        );
                     },
                 );
             }
diff --git a/compiler/rustc_resolve/src/rustdoc.rs b/compiler/rustc_resolve/src/rustdoc.rs
index d433391f272..ba7417b6dda 100644
--- a/compiler/rustc_resolve/src/rustdoc.rs
+++ b/compiler/rustc_resolve/src/rustdoc.rs
@@ -1,4 +1,4 @@
-use pulldown_cmark::{BrokenLink, Event, LinkType, Options, Parser, Tag};
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, Options, Parser, Tag};
 use rustc_ast as ast;
 use rustc_ast::util::comments::beautify_doc_string;
 use rustc_data_structures::fx::FxHashMap;
@@ -392,16 +392,73 @@ pub(crate) fn attrs_to_preprocessed_links(attrs: &[ast::Attribute]) -> Vec<Box<s
     let (doc_fragments, _) = attrs_to_doc_fragments(attrs.iter().map(|attr| (attr, None)), true);
     let doc = prepare_to_doc_link_resolution(&doc_fragments).into_values().next().unwrap();
 
-    Parser::new_with_broken_link_callback(
+    parse_links(&doc)
+}
+
+/// Similiar version of `markdown_links` from rustdoc.
+/// This will collect destination links and display text if exists.
+fn parse_links<'md>(doc: &'md str) -> Vec<Box<str>> {
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         &doc,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .filter_map(|event| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            Some(preprocess_link(&dest))
+    .into_iter();
+    let mut links = Vec::new();
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    if let Some(display_text) = collect_link_data(&mut event_iter) {
+                        links.push(display_text);
+                    }
+                }
+
+                links.push(preprocess_link(&dest));
+            }
+            _ => {}
+        }
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut Parser<'input, 'callback>,
+) -> Option<Box<str>> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some(event) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    display_text.map(String::into_boxed_str)
 }
diff --git a/compiler/rustc_session/messages.ftl b/compiler/rustc_session/messages.ftl
index b07c6db599e..e06b6380944 100644
--- a/compiler/rustc_session/messages.ftl
+++ b/compiler/rustc_session/messages.ftl
@@ -8,6 +8,9 @@ session_cannot_mix_and_match_sanitizers = `-Zsanitizer={$first}` is incompatible
 session_cgu_not_recorded =
     CGU-reuse for `{$cgu_user_name}` is (mangled: `{$cgu_name}`) was not recorded
 
+session_cli_feature_diagnostic_help =
+    add `-Zcrate-attr="feature({$feature})"` to the command-line options to enable
+
 session_crate_name_does_not_match = `--crate-name` and `#[crate_name]` are required to match, but `{$s}` != `{$name}`
 
 session_crate_name_empty = crate name must not be empty
diff --git a/compiler/rustc_session/src/config.rs b/compiler/rustc_session/src/config.rs
index 28ae88424ab..f00472f181d 100644
--- a/compiler/rustc_session/src/config.rs
+++ b/compiler/rustc_session/src/config.rs
@@ -12,7 +12,7 @@ use crate::{EarlyErrorHandler, Session};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::stable_hasher::{StableOrd, ToStableHashKey};
 use rustc_target::abi::Align;
-use rustc_target::spec::{PanicStrategy, SanitizerSet, SplitDebuginfo};
+use rustc_target::spec::{PanicStrategy, RelocModel, SanitizerSet, SplitDebuginfo};
 use rustc_target::spec::{Target, TargetTriple, TargetWarnings, TARGETS};
 
 use crate::parse::{CrateCheckConfig, CrateConfig};
@@ -1193,6 +1193,7 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     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();
@@ -1218,6 +1219,9 @@ fn default_configuration(sess: &Session) -> CrateConfig {
     ret.insert((sym::target_pointer_width, Some(Symbol::intern(&wordsz))));
     ret.insert((sym::target_env, Some(Symbol::intern(env))));
     ret.insert((sym::target_abi, Some(Symbol::intern(abi))));
+    if sess.is_nightly_build() {
+        ret.insert((sym::relocation_model, Some(relocation_model)));
+    }
     ret.insert((sym::target_vendor, Some(Symbol::intern(vendor))));
     if sess.target.has_thread_local {
         ret.insert((sym::target_thread_local, None));
@@ -1415,6 +1419,8 @@ impl CrateCheckConfig {
             .into_iter()
             .map(|sanitizer| Symbol::intern(sanitizer.as_str().unwrap()));
 
+        let relocation_model_values = RelocModel::all();
+
         // Unknown possible values:
         //  - `feature`
         //  - `target_feature`
@@ -1453,6 +1459,10 @@ impl CrateCheckConfig {
             .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
         {
diff --git a/compiler/rustc_session/src/errors.rs b/compiler/rustc_session/src/errors.rs
index 78940462b2c..5f8bbfca890 100644
--- a/compiler/rustc_session/src/errors.rs
+++ b/compiler/rustc_session/src/errors.rs
@@ -57,6 +57,12 @@ pub struct FeatureDiagnosticHelp {
     pub feature: Symbol,
 }
 
+#[derive(Subdiagnostic)]
+#[help(session_cli_feature_diagnostic_help)]
+pub struct CliFeatureDiagnosticHelp {
+    pub feature: Symbol,
+}
+
 #[derive(Diagnostic)]
 #[diag(session_not_circumvent_feature)]
 pub struct NotCircumventFeature;
diff --git a/compiler/rustc_session/src/parse.rs b/compiler/rustc_session/src/parse.rs
index 1cf63e9b7ba..671204c0d8e 100644
--- a/compiler/rustc_session/src/parse.rs
+++ b/compiler/rustc_session/src/parse.rs
@@ -2,7 +2,9 @@
 //! It also serves as an input to the parser itself.
 
 use crate::config::CheckCfg;
-use crate::errors::{FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError};
+use crate::errors::{
+    CliFeatureDiagnosticHelp, FeatureDiagnosticForIssue, FeatureDiagnosticHelp, FeatureGateError,
+};
 use crate::lint::{
     builtin::UNSTABLE_SYNTAX_PRE_EXPANSION, BufferedEarlyLint, BuiltinLintDiagnostics, Lint, LintId,
 };
@@ -110,7 +112,7 @@ pub fn feature_err_issue(
     }
 
     let mut err = sess.create_err(FeatureGateError { span, explain: explain.into() });
-    add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
+    add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
     err
 }
 
@@ -139,7 +141,7 @@ pub fn feature_warn_issue(
     explain: &'static str,
 ) {
     let mut err = sess.span_diagnostic.struct_span_warn(span, explain);
-    add_feature_diagnostics_for_issue(&mut err, sess, feature, issue);
+    add_feature_diagnostics_for_issue(&mut err, sess, feature, issue, false);
 
     // Decorate this as a future-incompatibility lint as in rustc_middle::lint::struct_lint_level
     let lint = UNSTABLE_SYNTAX_PRE_EXPANSION;
@@ -158,7 +160,7 @@ pub fn feature_warn_issue(
 
 /// Adds the diagnostics for a feature to an existing error.
 pub fn add_feature_diagnostics(err: &mut Diagnostic, sess: &ParseSess, feature: Symbol) {
-    add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language);
+    add_feature_diagnostics_for_issue(err, sess, feature, GateIssue::Language, false);
 }
 
 /// Adds the diagnostics for a feature to an existing error.
@@ -171,6 +173,7 @@ pub fn add_feature_diagnostics_for_issue(
     sess: &ParseSess,
     feature: Symbol,
     issue: GateIssue,
+    feature_from_cli: bool,
 ) {
     if let Some(n) = find_feature_issue(feature, issue) {
         err.subdiagnostic(FeatureDiagnosticForIssue { n });
@@ -178,7 +181,11 @@ pub fn add_feature_diagnostics_for_issue(
 
     // #23973: do not suggest `#![feature(...)]` if we are in beta/stable
     if sess.unstable_features.is_nightly_build() {
-        err.subdiagnostic(FeatureDiagnosticHelp { feature });
+        if feature_from_cli {
+            err.subdiagnostic(CliFeatureDiagnosticHelp { feature });
+        } else {
+            err.subdiagnostic(FeatureDiagnosticHelp { feature });
+        }
     }
 }
 
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 06b37008ebe..7e8ac9a141a 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -780,8 +780,8 @@ impl<'tcx> Stable<'tcx> for mir::Terminator<'tcx> {
                     .collect(),
                 otherwise: targets.otherwise().as_usize(),
             },
-            Resume => Terminator::Resume,
-            Terminate => Terminator::Abort,
+            UnwindResume => Terminator::Resume,
+            UnwindTerminate => Terminator::Abort,
             Return => Terminator::Return,
             Unreachable => Terminator::Unreachable,
             Drop { place, target, unwind, replace: _ } => Terminator::Drop {
diff --git a/compiler/rustc_smir/src/stable_mir/mod.rs b/compiler/rustc_smir/src/stable_mir/mod.rs
index 19061742b64..2ae334c6a95 100644
--- a/compiler/rustc_smir/src/stable_mir/mod.rs
+++ b/compiler/rustc_smir/src/stable_mir/mod.rs
@@ -1,6 +1,6 @@
 //! Module that implements the public interface to the Stable MIR.
 //!
-//! This module shall contain all type definitions and APIs that we expect 3P tools to invoke to
+//! This module shall contain all type definitions and APIs that we expect third-party tools to invoke to
 //! interact with the compiler.
 //!
 //! The goal is to eventually move this module to its own crate which shall be published on
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index edbf51e9b33..28a2dfebcfe 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -445,6 +445,7 @@ symbols! {
         bridge,
         bswap,
         builtin_syntax,
+        c,
         c_str,
         c_str_literals,
         c_unwind,
@@ -468,6 +469,7 @@ symbols! {
         cfg_hide,
         cfg_overflow_checks,
         cfg_panic,
+        cfg_relocation_model,
         cfg_sanitize,
         cfg_target_abi,
         cfg_target_compact,
@@ -661,6 +663,7 @@ symbols! {
         dyn_metadata,
         dyn_star,
         dyn_trait,
+        dynamic_no_pic: "dynamic-no-pic",
         e,
         edition_panic,
         effects,
@@ -1115,6 +1118,8 @@ symbols! {
         path,
         pattern_parentheses,
         phantom_data,
+        pic,
+        pie,
         pin,
         platform_intrinsics,
         plugin,
@@ -1223,6 +1228,7 @@ symbols! {
         register_tool,
         relaxed_adts,
         relaxed_struct_unsize,
+        relocation_model,
         rem,
         rem_assign,
         repr,
@@ -1243,6 +1249,8 @@ symbols! {
         rintf64,
         riscv_target_feature,
         rlib,
+        ropi,
+        ropi_rwpi: "ropi-rwpi",
         rotate_left,
         rotate_right,
         roundevenf32,
@@ -1354,6 +1362,7 @@ symbols! {
         rustdoc_missing_doc_code_examples,
         rustfmt,
         rvalue_static_promotion,
+        rwpi,
         s,
         safety,
         sanitize,
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
index c0f1827ad3f..400030ca0c6 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabi.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
index 79b8958c22a..6228fb15a83 100644
--- a/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
+++ b/compiler/rustc_target/src/spec/arm_unknown_linux_gnueabihf.rs
@@ -11,6 +11,7 @@ pub fn target() -> Target {
             features: "+strict-align,+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
index 4836f3cf720..1d66515a72e 100644
--- a/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armeb_unknown_linux_gnueabi.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             endian: Endian::Big,
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
index 1de63a920c8..cffebcc9581 100644
--- a/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv4t_unknown_linux_gnueabi.rs
@@ -12,6 +12,7 @@ pub fn target() -> Target {
             // Atomic operations provided by compiler-builtins
             max_atomic_width: Some(32),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             has_thumb_interworking: true,
             ..super::linux_gnu_base::opts()
         },
diff --git a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
index b7cfccc8b3d..4a8aa31576f 100644
--- a/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
+++ b/compiler/rustc_target/src/spec/armv6_unknown_freebsd.rs
@@ -13,6 +13,7 @@ pub fn target() -> Target {
             features: "+v6,+vfp2,-d32".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::freebsd_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
index 903042d7e7a..73ae212a7a6 100644
--- a/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
+++ b/compiler/rustc_target/src/spec/armv7_unknown_linux_gnueabi.rs
@@ -14,6 +14,7 @@ pub fn target() -> Target {
             features: "+v7,+thumb2,+soft-float,-neon".into(),
             max_atomic_width: Some(64),
             mcount: "\u{1}__gnu_mcount_nc".into(),
+            llvm_mcount_intrinsic: Some("llvm.arm.gnu.eabi.mcount".into()),
             ..super::linux_gnu_base::opts()
         },
     }
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index af2b96ccb51..31b6961bb62 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -42,7 +42,7 @@ use crate::spec::crt_objects::{CrtObjects, LinkSelfContainedDefault};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_fs_util::try_canonicalize;
 use rustc_serialize::{Decodable, Decoder, Encodable, Encoder};
-use rustc_span::symbol::{sym, Symbol};
+use rustc_span::symbol::{kw, sym, Symbol};
 use serde_json::Value;
 use std::borrow::Cow;
 use std::collections::BTreeMap;
@@ -655,6 +655,43 @@ pub enum RelocModel {
     RopiRwpi,
 }
 
+impl RelocModel {
+    pub fn desc(&self) -> &str {
+        match *self {
+            RelocModel::Static => "static",
+            RelocModel::Pic => "pic",
+            RelocModel::Pie => "pie",
+            RelocModel::DynamicNoPic => "dynamic-no-pic",
+            RelocModel::Ropi => "ropi",
+            RelocModel::Rwpi => "rwpi",
+            RelocModel::RopiRwpi => "ropi-rwpi",
+        }
+    }
+    pub const fn desc_symbol(&self) -> Symbol {
+        match *self {
+            RelocModel::Static => kw::Static,
+            RelocModel::Pic => sym::pic,
+            RelocModel::Pie => sym::pie,
+            RelocModel::DynamicNoPic => sym::dynamic_no_pic,
+            RelocModel::Ropi => sym::ropi,
+            RelocModel::Rwpi => sym::rwpi,
+            RelocModel::RopiRwpi => sym::ropi_rwpi,
+        }
+    }
+
+    pub const fn all() -> [Symbol; 7] {
+        [
+            RelocModel::Static.desc_symbol(),
+            RelocModel::Pic.desc_symbol(),
+            RelocModel::Pie.desc_symbol(),
+            RelocModel::DynamicNoPic.desc_symbol(),
+            RelocModel::Ropi.desc_symbol(),
+            RelocModel::Rwpi.desc_symbol(),
+            RelocModel::RopiRwpi.desc_symbol(),
+        ]
+    }
+}
+
 impl FromStr for RelocModel {
     type Err = ();
 
@@ -674,16 +711,7 @@ impl FromStr for RelocModel {
 
 impl ToJson for RelocModel {
     fn to_json(&self) -> Json {
-        match *self {
-            RelocModel::Static => "static",
-            RelocModel::Pic => "pic",
-            RelocModel::Pie => "pie",
-            RelocModel::DynamicNoPic => "dynamic-no-pic",
-            RelocModel::Ropi => "ropi",
-            RelocModel::Rwpi => "rwpi",
-            RelocModel::RopiRwpi => "ropi-rwpi",
-        }
-        .to_json()
+        self.desc().to_json()
     }
 }
 
@@ -1922,6 +1950,9 @@ pub struct TargetOptions {
     /// Use platform dependent mcount function
     pub mcount: StaticCow<str>,
 
+    /// Use LLVM intrinsic for mcount function name
+    pub llvm_mcount_intrinsic: Option<StaticCow<str>>,
+
     /// LLVM ABI name, corresponds to the '-mabi' parameter available in multilib C compilers
     pub llvm_abiname: StaticCow<str>,
 
@@ -2183,6 +2214,7 @@ impl Default for TargetOptions {
             override_export_symbols: None,
             merge_functions: MergeFunctions::Aliases,
             mcount: "mcount".into(),
+            llvm_mcount_intrinsic: None,
             llvm_abiname: "".into(),
             relax_elf_relocations: false,
             llvm_args: cvs![],
@@ -2840,6 +2872,7 @@ impl Target {
         key!(override_export_symbols, opt_list);
         key!(merge_functions, MergeFunctions)?;
         key!(mcount = "target-mcount");
+        key!(llvm_mcount_intrinsic, optional);
         key!(llvm_abiname);
         key!(relax_elf_relocations, bool);
         key!(llvm_args, list);
@@ -3096,6 +3129,7 @@ impl ToJson for Target {
         target_option_val!(override_export_symbols);
         target_option_val!(merge_functions);
         target_option_val!(mcount, "target-mcount");
+        target_option_val!(llvm_mcount_intrinsic);
         target_option_val!(llvm_abiname);
         target_option_val!(relax_elf_relocations);
         target_option_val!(llvm_args);
diff --git a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
index 0990b9bee90..523841951b0 100644
--- a/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_trait_selection/src/solve/eval_ctxt/canonical.rs
@@ -215,7 +215,7 @@ impl<'tcx> EvalCtxt<'_, 'tcx> {
         // created inside of the query directly instead of returning them to the
         // caller.
         let prev_universe = self.infcx.universe();
-        let universes_created_in_query = response.max_universe.index() + 1;
+        let universes_created_in_query = response.max_universe.index();
         for _ in 0..universes_created_in_query {
             self.infcx.create_next_universe();
         }
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index 3d800421b76..06a1027e5df 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -1214,7 +1214,7 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
 
             let projected_term = selcx.infcx.resolve_vars_if_possible(projected_term);
 
-            let mut result = if projected_term.has_projections() {
+            let result = if projected_term.has_projections() {
                 let mut normalizer = AssocTypeNormalizer::new(
                     selcx,
                     param_env,
@@ -1224,19 +1224,14 @@ fn opt_normalize_projection_type<'a, 'b, 'tcx>(
                 );
                 let normalized_ty = normalizer.fold(projected_term);
 
+                let mut deduped = SsoHashSet::with_capacity(projected_obligations.len());
+                projected_obligations.retain(|obligation| deduped.insert(obligation.clone()));
+
                 Normalized { value: normalized_ty, obligations: projected_obligations }
             } else {
                 Normalized { value: projected_term, obligations: projected_obligations }
             };
 
-            let mut deduped: SsoHashSet<_> = Default::default();
-            result.obligations.retain(|projected_obligation| {
-                if !deduped.insert(projected_obligation.clone()) {
-                    return false;
-                }
-                true
-            });
-
             if use_cache {
                 infcx.inner.borrow_mut().projection_cache().insert_term(cache_key, result.clone());
             }
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 1a2d6d64eb0..f36f4ec8697 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -23,7 +23,6 @@ TrivialTypeTraversalImpls! {
     (),
     bool,
     usize,
-    u8,
     u16,
     u32,
     u64,
diff --git a/library/alloc/src/boxed.rs b/library/alloc/src/boxed.rs
index 8697a77db3b..96b93830f96 100644
--- a/library/alloc/src/boxed.rs
+++ b/library/alloc/src/boxed.rs
@@ -2183,7 +2183,7 @@ impl dyn Error + Send {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
             // Reapply the `Send` marker.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send>>(s)
+            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send))
         })
     }
 }
@@ -2197,7 +2197,7 @@ impl dyn Error + Send + Sync {
         let err: Box<dyn Error> = self;
         <dyn Error>::downcast(err).map_err(|s| unsafe {
             // Reapply the `Send + Sync` marker.
-            mem::transmute::<Box<dyn Error>, Box<dyn Error + Send + Sync>>(s)
+            Box::from_raw(Box::into_raw(s) as *mut (dyn Error + Send + Sync))
         })
     }
 }
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 41aac02eaa9..efe8f5a8bcf 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -89,6 +89,7 @@
 #![allow(explicit_outlives_requirements)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
@@ -119,6 +120,7 @@
 #![feature(const_waker)]
 #![feature(core_intrinsics)]
 #![feature(core_panic)]
+#![feature(deprecated_suggestion)]
 #![feature(dispatch_from_dyn)]
 #![feature(error_generic_member_access)]
 #![feature(error_in_core)]
diff --git a/library/alloc/src/slice.rs b/library/alloc/src/slice.rs
index 093dcbbe8bf..aa3b7b7e191 100644
--- a/library/alloc/src/slice.rs
+++ b/library/alloc/src/slice.rs
@@ -592,7 +592,7 @@ impl<T> [T] {
     /// ```
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[deprecated(since = "1.3.0", note = "renamed to join")]
+    #[deprecated(since = "1.3.0", note = "renamed to join", suggestion = "join")]
     pub fn connect<Separator>(&self, sep: Separator) -> <Self as Join<Separator>>::Output
     where
         Self: Join<Separator>,
diff --git a/library/alloc/src/sync.rs b/library/alloc/src/sync.rs
index e2a2fe932ab..476a4fea54f 100644
--- a/library/alloc/src/sync.rs
+++ b/library/alloc/src/sync.rs
@@ -153,7 +153,7 @@ macro_rules! acquire {
 ///
 /// ## `Deref` behavior
 ///
-/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`][deref] trait),
+/// `Arc<T>` automatically dereferences to `T` (via the [`Deref`] trait),
 /// so you can call `T`'s methods on a value of type `Arc<T>`. To avoid name
 /// clashes with `T`'s methods, the methods of `Arc<T>` itself are associated
 /// functions, called using [fully qualified syntax]:
@@ -187,7 +187,6 @@ macro_rules! acquire {
 /// [mutex]: ../../std/sync/struct.Mutex.html
 /// [rwlock]: ../../std/sync/struct.RwLock.html
 /// [atomic]: core::sync::atomic
-/// [deref]: core::ops::Deref
 /// [downgrade]: Arc::downgrade
 /// [upgrade]: Weak::upgrade
 /// [RefCell\<T>]: core::cell::RefCell
@@ -1495,7 +1494,7 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// alignment as `T`. This is trivially true if `U` is `T`.
     /// Note that if `U` is not `T` but has the same size and alignment, this is
     /// basically like transmuting references of different types. See
-    /// [`mem::transmute`][transmute] for more information on what
+    /// [`mem::transmute`] for more information on what
     /// restrictions apply in this case.
     ///
     /// The raw pointer must point to a block of memory allocated by `alloc`
@@ -1507,7 +1506,6 @@ impl<T: ?Sized, A: Allocator> Arc<T, A> {
     /// even if the returned `Arc<T>` is never accessed.
     ///
     /// [into_raw]: Arc::into_raw
-    /// [transmute]: core::mem::transmute
     ///
     /// # Examples
     ///
diff --git a/library/core/src/ffi/c_str.rs b/library/core/src/ffi/c_str.rs
index 92e38df4049..163a65c909e 100644
--- a/library/core/src/ffi/c_str.rs
+++ b/library/core/src/ffi/c_str.rs
@@ -253,7 +253,7 @@ impl CStr {
     /// ```
     ///
     /// [valid]: core::ptr#safety
-    #[inline]
+    #[inline] // inline is necessary for codegen to see strlen.
     #[must_use]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_cstr_from_ptr", issue = "113219")]
@@ -280,6 +280,8 @@ impl CStr {
                 len
             }
 
+            // `inline` is necessary for codegen to see strlen.
+            #[inline]
             fn strlen_rt(s: *const c_char) -> usize {
                 extern "C" {
                     /// Provided by libc or compiler_builtins.
diff --git a/library/core/src/intrinsics/mir.rs b/library/core/src/intrinsics/mir.rs
index 036edbebbf3..ef0a2fd4ec4 100644
--- a/library/core/src/intrinsics/mir.rs
+++ b/library/core/src/intrinsics/mir.rs
@@ -104,17 +104,18 @@
 //! }
 //!
 //! #[custom_mir(dialect = "runtime", phase = "optimized")]
+#![cfg_attr(bootstrap, doc = "#[cfg(any())]")] // disable the following function in doctests when `bootstrap` is set
 //! fn push_and_pop<T>(v: &mut Vec<T>, value: T) {
 //!     mir!(
-//!         let unused;
+//!         let _unused;
 //!         let popped;
 //!
 //!         {
-//!             Call(unused, pop, Vec::push(v, value))
+//!             Call(_unused = Vec::push(v, value), pop)
 //!         }
 //!
 //!         pop = {
-//!             Call(popped, drop, Vec::pop(v))
+//!             Call(popped = Vec::pop(v), drop)
 //!         }
 //!
 //!         drop = {
@@ -275,7 +276,7 @@ define!("mir_return", fn Return() -> BasicBlock);
 define!("mir_goto", fn Goto(destination: BasicBlock) -> BasicBlock);
 define!("mir_unreachable", fn Unreachable() -> BasicBlock);
 define!("mir_drop", fn Drop<T>(place: T, goto: BasicBlock));
-define!("mir_call", fn Call<T>(place: T, goto: BasicBlock, call: T));
+define!("mir_call", fn Call(call: (), goto: BasicBlock));
 define!("mir_storage_live", fn StorageLive<T>(local: T));
 define!("mir_storage_dead", fn StorageDead<T>(local: T));
 define!("mir_deinit", fn Deinit<T>(place: T));
diff --git a/library/core/src/lib.rs b/library/core/src/lib.rs
index 48c3c1f2123..a2729b3743c 100644
--- a/library/core/src/lib.rs
+++ b/library/core/src/lib.rs
@@ -97,6 +97,8 @@
 #![allow(incomplete_features)]
 #![warn(multiple_supertrait_upcastable)]
 #![cfg_attr(not(bootstrap), allow(internal_features))]
+// Do not check link redundancy on bootstraping phase
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 //
 // Library features:
 // tidy-alphabetical-start
diff --git a/library/core/src/mem/mod.rs b/library/core/src/mem/mod.rs
index 2fff3f0efd7..732fcce0f29 100644
--- a/library/core/src/mem/mod.rs
+++ b/library/core/src/mem/mod.rs
@@ -413,7 +413,7 @@ pub const unsafe fn size_of_val_raw<T: ?Sized>(val: *const T) -> usize {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(note = "use `align_of` instead", since = "1.2.0")]
+#[deprecated(note = "use `align_of` instead", since = "1.2.0", suggestion = "align_of")]
 pub fn min_align_of<T>() -> usize {
     intrinsics::min_align_of::<T>()
 }
@@ -436,7 +436,7 @@ pub fn min_align_of<T>() -> usize {
 #[inline]
 #[must_use]
 #[stable(feature = "rust1", since = "1.0.0")]
-#[deprecated(note = "use `align_of_val` instead", since = "1.2.0")]
+#[deprecated(note = "use `align_of_val` instead", since = "1.2.0", suggestion = "align_of_val")]
 pub fn min_align_of_val<T: ?Sized>(val: &T) -> usize {
     // SAFETY: val is a reference, so it's a valid raw pointer
     unsafe { intrinsics::min_align_of_val(val) }
diff --git a/library/core/src/num/int_macros.rs b/library/core/src/num/int_macros.rs
index 1199d09b563..1f43520e1b3 100644
--- a/library/core/src/num/int_macros.rs
+++ b/library/core/src/num/int_macros.rs
@@ -2126,6 +2126,7 @@ macro_rules! int_impl {
         /// assert_eq!(a.rem_euclid(-b), 3);
         /// assert_eq!((-a).rem_euclid(-b), 1);
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/num/uint_macros.rs b/library/core/src/num/uint_macros.rs
index 2136d29255f..81148c7cc51 100644
--- a/library/core/src/num/uint_macros.rs
+++ b/library/core/src/num/uint_macros.rs
@@ -2024,6 +2024,7 @@ macro_rules! uint_impl {
         /// ```
         #[doc = concat!("assert_eq!(7", stringify!($SelfT), ".rem_euclid(4), 3); // or any other integer type")]
         /// ```
+        #[doc(alias = "modulo", alias = "mod")]
         #[stable(feature = "euclidean_division", since = "1.38.0")]
         #[rustc_const_stable(feature = "const_euclidean_int_methods", since = "1.52.0")]
         #[must_use = "this returns the result of the operation, \
diff --git a/library/core/src/str/mod.rs b/library/core/src/str/mod.rs
index e5f34952c7d..23cebdb6c3b 100644
--- a/library/core/src/str/mod.rs
+++ b/library/core/src/str/mod.rs
@@ -997,7 +997,7 @@ impl str {
 
     /// An iterator over the lines of a string.
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[deprecated(since = "1.4.0", note = "use lines() instead now")]
+    #[deprecated(since = "1.4.0", note = "use lines() instead now", suggestion = "lines")]
     #[inline]
     #[allow(deprecated)]
     pub fn lines_any(&self) -> LinesAny<'_> {
diff --git a/library/std/src/collections/hash/map.rs b/library/std/src/collections/hash/map.rs
index a083b65604d..be173a7ace6 100644
--- a/library/std/src/collections/hash/map.rs
+++ b/library/std/src/collections/hash/map.rs
@@ -49,12 +49,14 @@ use crate::sys;
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashMap` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/collections/hash/set.rs b/library/std/src/collections/hash/set.rs
index 959403e1644..6d85b26af5f 100644
--- a/library/std/src/collections/hash/set.rs
+++ b/library/std/src/collections/hash/set.rs
@@ -24,13 +24,14 @@ use super::map::{map_try_reserve_error, RandomState};
 /// ```
 ///
 /// In other words, if two keys are equal, their hashes must be equal.
+/// Violating this property is a logic error.
 ///
-///
-/// It is a logic error for a key to be modified in such a way that the key's
+/// It is also a logic error for a key to be modified in such a way that the key's
 /// hash, as determined by the [`Hash`] trait, or its equality, as determined by
 /// the [`Eq`] trait, changes while it is in the map. This is normally only
 /// possible through [`Cell`], [`RefCell`], global state, I/O, or unsafe code.
-/// The behavior resulting from such a logic error is not specified, but will
+///
+/// The behavior resulting from either logic error is not specified, but will
 /// be encapsulated to the `HashSet` that observed the logic error and not
 /// result in undefined behavior. This could include panics, incorrect results,
 /// aborts, memory leaks, and non-termination.
diff --git a/library/std/src/error.rs b/library/std/src/error.rs
index 7bc3af1793e..375ff2d2450 100644
--- a/library/std/src/error.rs
+++ b/library/std/src/error.rs
@@ -10,7 +10,7 @@ use crate::fmt::{self, Write};
 #[stable(feature = "rust1", since = "1.0.0")]
 pub use core::error::Error;
 #[unstable(feature = "error_generic_member_access", issue = "99301")]
-pub use core::error::{request_ref, Request};
+pub use core::error::{request_ref, request_value, Request};
 
 mod private {
     // This is a hack to prevent `type_id` from being overridden by `Error`
diff --git a/library/std/src/f32.rs b/library/std/src/f32.rs
index a53b8535213..776899dbcfd 100644
--- a/library/std/src/f32.rs
+++ b/library/std/src/f32.rs
@@ -61,6 +61,7 @@ impl f32 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f32 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f32 {
     /// // limitation due to round-off error
     /// assert!((-f32::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f32 {
     /// assert!(abs_difference_0 <= f32::EPSILON);
     /// assert!(abs_difference_1 <= f32::EPSILON);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -815,6 +822,7 @@ impl f32 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "log1p")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -904,6 +912,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +935,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= f32::EPSILON);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +960,7 @@ impl f32 {
     ///
     /// assert!(abs_difference <= 1e-5);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/f64.rs b/library/std/src/f64.rs
index a1cec22c97a..4f4f5f02471 100644
--- a/library/std/src/f64.rs
+++ b/library/std/src/f64.rs
@@ -61,6 +61,7 @@ impl f64 {
     /// assert_eq!(f.ceil(), 4.0);
     /// assert_eq!(g.ceil(), 4.0);
     /// ```
+    #[doc(alias = "ceiling")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -135,6 +136,7 @@ impl f64 {
     /// assert_eq!(g.trunc(), 3.0);
     /// assert_eq!(h.trunc(), -3.0);
     /// ```
+    #[doc(alias = "truncate")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -321,6 +323,7 @@ impl f64 {
     /// // limitation due to round-off error
     /// assert!((-f64::EPSILON).rem_euclid(3.0) != 0.0);
     /// ```
+    #[doc(alias = "modulo", alias = "mod")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[inline]
@@ -672,6 +675,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arcsin")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -694,6 +698,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arccos")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -715,6 +720,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-10);
     /// ```
+    #[doc(alias = "arctan")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -772,6 +778,7 @@ impl f64 {
     /// assert!(abs_difference_0 < 1e-10);
     /// assert!(abs_difference_1 < 1e-10);
     /// ```
+    #[doc(alias = "sincos")]
     #[rustc_allow_incoherent_impl]
     #[stable(feature = "rust1", since = "1.0.0")]
     #[inline]
@@ -815,6 +822,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1e-20);
     /// ```
+    #[doc(alias = "log1p")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -904,6 +912,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arcsinh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -926,6 +935,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arccosh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
@@ -950,6 +960,7 @@ impl f64 {
     ///
     /// assert!(abs_difference < 1.0e-10);
     /// ```
+    #[doc(alias = "arctanh")]
     #[rustc_allow_incoherent_impl]
     #[must_use = "method returns a new number and does not mutate the original value"]
     #[stable(feature = "rust1", since = "1.0.0")]
diff --git a/library/std/src/io/mod.rs b/library/std/src/io/mod.rs
index 5c1d2d8f46c..71d91f21362 100644
--- a/library/std/src/io/mod.rs
+++ b/library/std/src/io/mod.rs
@@ -1425,9 +1425,9 @@ pub trait Write {
     ///
     /// If this method consumed `n > 0` bytes of `buf` it must return [`Ok(n)`].
     /// If the return value is `Ok(n)` then `n` must satisfy `n <= buf.len()`.
-    /// Unless `buf` is empty, this function shouldn’t return `Ok(0)` since the
-    /// caller may interpret that as an error.  To indicate lack of space,
-    /// implementors should return [`ErrorKind::StorageFull`] error instead.
+    /// A return value of `Ok(0)` typically means that the underlying object is
+    /// no longer able to accept bytes and will likely not be able to in the
+    /// future as well, or that the buffer provided is empty.
     ///
     /// # Errors
     ///
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index ac4ce222fba..58684ffe500 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -223,6 +223,7 @@
 #![cfg_attr(not(bootstrap), allow(internal_features))]
 #![deny(rustc::existing_doc_keyword)]
 #![deny(fuzzy_provenance_casts)]
+#![cfg_attr(not(bootstrap), allow(rustdoc::redundant_explicit_links))]
 // Ensure that std can be linked against panic_abort despite compiled with `-C panic=unwind`
 #![deny(ffi_unwind_calls)]
 // std may use features in a platform-specific way
diff --git a/library/std/src/sys/solid/os.rs b/library/std/src/sys/solid/os.rs
index 717c08434a8..9f4e66d628b 100644
--- a/library/std/src/sys/solid/os.rs
+++ b/library/std/src/sys/solid/os.rs
@@ -81,6 +81,10 @@ pub fn current_exe() -> io::Result<PathBuf> {
 
 static ENV_LOCK: RwLock<()> = RwLock::new(());
 
+pub fn env_read_lock() -> impl Drop {
+    ENV_LOCK.read().unwrap_or_else(PoisonError::into_inner)
+}
+
 pub struct Env {
     iter: vec::IntoIter<(OsString, OsString)>,
 }
@@ -134,7 +138,7 @@ pub fn env() -> Env {
     }
 
     unsafe {
-        let _guard = ENV_LOCK.read();
+        let _guard = env_read_lock();
         let mut result = Vec::new();
         if !environ.is_null() {
             while !(*environ).is_null() {
@@ -168,17 +172,21 @@ pub fn env() -> Env {
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
-    let s = run_with_cstr(k.as_bytes(), |k| {
-        let _guard = ENV_LOCK.read();
-        Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
-    })
-    .ok()?;
+    run_with_cstr(k.as_bytes(), |k| {
+        let _guard = env_read_lock();
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
 
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
+    })
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/unix/os.rs b/library/std/src/sys/unix/os.rs
index 215f63d04f7..57e1a36dace 100644
--- a/library/std/src/sys/unix/os.rs
+++ b/library/std/src/sys/unix/os.rs
@@ -594,16 +594,21 @@ pub fn env() -> Env {
 pub fn getenv(k: &OsStr) -> Option<OsString> {
     // environment variables with a nul byte can't be set, so their value is
     // always None as well
-    let s = run_with_cstr(k.as_bytes(), |k| {
+    run_with_cstr(k.as_bytes(), |k| {
         let _guard = env_read_lock();
-        Ok(unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char)
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
     })
-    .ok()?;
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/wasi/os.rs b/library/std/src/sys/wasi/os.rs
index e0de284c5e2..d53bddd8e9d 100644
--- a/library/std/src/sys/wasi/os.rs
+++ b/library/std/src/sys/wasi/os.rs
@@ -225,16 +225,23 @@ pub fn env() -> Env {
 }
 
 pub fn getenv(k: &OsStr) -> Option<OsString> {
-    let s = run_with_cstr(k.as_bytes(), |k| unsafe {
+    // environment variables with a nul byte can't be set, so their value is
+    // always None as well
+    run_with_cstr(k.as_bytes(), |k| {
         let _guard = env_read_lock();
-        Ok(libc::getenv(k.as_ptr()) as *const libc::c_char)
+        let v = unsafe { libc::getenv(k.as_ptr()) } as *const libc::c_char;
+
+        if v.is_null() {
+            Ok(None)
+        } else {
+            // SAFETY: `v` cannot be mutated while executing this line since we've a read lock
+            let bytes = unsafe { CStr::from_ptr(v) }.to_bytes().to_vec();
+
+            Ok(Some(OsStringExt::from_vec(bytes)))
+        }
     })
-    .ok()?;
-    if s.is_null() {
-        None
-    } else {
-        Some(OsStringExt::from_vec(unsafe { CStr::from_ptr(s) }.to_bytes().to_vec()))
-    }
+    .ok()
+    .flatten()
 }
 
 pub fn setenv(k: &OsStr, v: &OsStr) -> io::Result<()> {
diff --git a/library/std/src/sys/windows/os.rs b/library/std/src/sys/windows/os.rs
index 2329426ad1d..58afca088ef 100644
--- a/library/std/src/sys/windows/os.rs
+++ b/library/std/src/sys/windows/os.rs
@@ -25,10 +25,6 @@ pub fn errno() -> i32 {
 
 /// Gets a detailed string description for the given error number.
 pub fn error_string(mut errnum: i32) -> String {
-    // This value is calculated from the macro
-    // MAKELANGID(LANG_SYSTEM_DEFAULT, SUBLANG_SYS_DEFAULT)
-    let langId = 0x0800 as c::DWORD;
-
     let mut buf = [0 as c::WCHAR; 2048];
 
     unsafe {
@@ -56,13 +52,13 @@ pub fn error_string(mut errnum: i32) -> String {
             flags | c::FORMAT_MESSAGE_FROM_SYSTEM | c::FORMAT_MESSAGE_IGNORE_INSERTS,
             module,
             errnum as c::DWORD,
-            langId,
+            0,
             buf.as_mut_ptr(),
             buf.len() as c::DWORD,
             ptr::null(),
         ) as usize;
         if res == 0 {
-            // Sometimes FormatMessageW can fail e.g., system doesn't like langId,
+            // Sometimes FormatMessageW can fail e.g., system doesn't like 0 as langId,
             let fm_err = errno();
             return format!("OS Error {errnum} (FormatMessageW() returned error {fm_err})");
         }
diff --git a/library/std/src/sys_common/thread_parking/id.rs b/library/std/src/sys_common/thread_parking/id.rs
index 15042fc3bee..04667439660 100644
--- a/library/std/src/sys_common/thread_parking/id.rs
+++ b/library/std/src/sys_common/thread_parking/id.rs
@@ -56,18 +56,14 @@ impl Parker {
         self.init_tid();
 
         // Changes NOTIFIED to EMPTY and EMPTY to PARKED.
-        let mut state = self.state.fetch_sub(1, Acquire).wrapping_sub(1);
-        if state == PARKED {
+        let state = self.state.fetch_sub(1, Acquire);
+        if state == EMPTY {
             // Loop to guard against spurious wakeups.
-            while state == PARKED {
+            // The state must be reset with acquire ordering to ensure that all
+            // calls to `unpark` synchronize with this thread.
+            while self.state.compare_exchange(NOTIFIED, EMPTY, Acquire, Relaxed).is_err() {
                 park(self.state.as_ptr().addr());
-                state = self.state.load(Acquire);
             }
-
-            // Since the state change has already been observed with acquire
-            // ordering, the state can be reset with a relaxed store instead
-            // of a swap.
-            self.state.store(EMPTY, Relaxed);
         }
     }
 
@@ -78,8 +74,7 @@ impl Parker {
         if state == PARKED {
             park_timeout(dur, self.state.as_ptr().addr());
             // Swap to ensure that we observe all state changes with acquire
-            // ordering, even if the state has been changed after the timeout
-            // occurred.
+            // ordering.
             self.state.swap(EMPTY, Acquire);
         }
     }
diff --git a/library/std/tests/env.rs b/library/std/tests/env.rs
index 96b4f372b8b..a1ca85c2145 100644
--- a/library/std/tests/env.rs
+++ b/library/std/tests/env.rs
@@ -5,6 +5,7 @@ use rand::distributions::{Alphanumeric, DistString};
 
 mod common;
 use common::test_rng;
+use std::thread;
 
 #[track_caller]
 fn make_rand_name() -> OsString {
@@ -140,3 +141,22 @@ fn env_home_dir() {
         }
     }
 }
+
+#[test] // miri shouldn't detect any data race in this fn
+#[cfg_attr(any(not(miri), target_os = "emscripten"), ignore)]
+fn test_env_get_set_multithreaded() {
+    let getter = thread::spawn(|| {
+        for _ in 0..100 {
+            let _ = var_os("foo");
+        }
+    });
+
+    let setter = thread::spawn(|| {
+        for _ in 0..100 {
+            set_var("foo", "bar");
+        }
+    });
+
+    let _ = getter.join();
+    let _ = setter.join();
+}
diff --git a/src/bootstrap/bootstrap.py b/src/bootstrap/bootstrap.py
index f44a05a6b28..c5c70f2e18a 100644
--- a/src/bootstrap/bootstrap.py
+++ b/src/bootstrap/bootstrap.py
@@ -644,7 +644,7 @@ class RustBuild(object):
                 return False
 
             # If the user has asked binaries to be patched for Nix, then
-            # don't check for NixOS or `/lib`.
+            # don't check for NixOS.
             if self.get_toml("patch-binaries-for-nix", "build") == "true":
                 return True
 
@@ -652,14 +652,9 @@ class RustBuild(object):
             # The latter one does not exist on NixOS when using tmpfs as root.
             try:
                 with open("/etc/os-release", "r") as f:
-                    if not any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f):
-                        return False
+                    return any(ln.strip() in ("ID=nixos", "ID='nixos'", 'ID="nixos"') for ln in f)
             except FileNotFoundError:
                 return False
-            if os.path.exists("/lib"):
-                return False
-
-            return True
 
         answer = self._should_fix_bins_and_dylibs = get_answer()
         if answer:
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index a4135b06e9d..52162bf42ea 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -105,7 +105,7 @@ impl Config {
                     matches!(l.trim(), "ID=nixos" | "ID='nixos'" | "ID=\"nixos\"")
                 }),
             };
-            is_nixos && !Path::new("/lib").exists()
+            is_nixos
         });
         if val {
             eprintln!("info: You seem to be using Nix.");
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index d0d62db0807..db3b7ffbea4 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -630,6 +630,10 @@ impl Step for Miri {
         cargo.env("MIRI_SYSROOT", &miri_sysroot);
         cargo.env("MIRI_HOST_SYSROOT", sysroot);
         cargo.env("MIRI", &miri);
+        if builder.config.locked_deps {
+            // enforce lockfiles
+            cargo.env("CARGO_EXTRA_FLAGS", "--locked");
+        }
 
         // Set the target.
         cargo.env("MIRI_TEST_TARGET", target.rustc_target_arg());
@@ -675,6 +679,9 @@ impl Step for Miri {
         );
         cargo.add_rustc_lib_path(builder, compiler);
         cargo.arg("--").arg("miri").arg("test");
+        if builder.config.locked_deps {
+            cargo.arg("--locked");
+        }
         cargo
             .arg("--manifest-path")
             .arg(builder.src.join("src/tools/miri/test-cargo-miri/Cargo.toml"));
diff --git a/src/bootstrap/tool.rs b/src/bootstrap/tool.rs
index e6d27757ac6..07ff3da6b4a 100644
--- a/src/bootstrap/tool.rs
+++ b/src/bootstrap/tool.rs
@@ -601,7 +601,7 @@ pub struct RustAnalyzer {
 }
 
 impl RustAnalyzer {
-    pub const ALLOW_FEATURES: &str =
+    pub const ALLOW_FEATURES: &'static str =
         "proc_macro_internals,proc_macro_diagnostic,proc_macro_span,proc_macro_span_shrink";
 }
 
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index 2cc0bfd9db9..89b82d59d31 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -504,18 +504,6 @@ jobs:
               NO_OVERFLOW_CHECKS: 1
             <<: *job-macos-xl
 
-          - name: dist-x86_64-apple-alt
-            env:
-              SCRIPT: ./x.py dist bootstrap --include-default-paths
-              RUST_CONFIGURE_ARGS: --enable-extended --enable-profiler --set rust.jemalloc --set llvm.ninja=false
-              RUSTC_RETRY_LINKER_ON_SEGFAULT: 1
-              MACOSX_DEPLOYMENT_TARGET: 10.7
-              SELECT_XCODE: /Applications/Xcode_13.4.1.app
-              NO_LLVM_ASSERTIONS: 1
-              NO_DEBUG_ASSERTIONS: 1
-              NO_OVERFLOW_CHECKS: 1
-            <<: *job-macos-xl
-
           - name: x86_64-apple-1
             env: &env-x86_64-apple-tests
               SCRIPT: ./x.py --stage 2 test --skip tests/ui --skip tests/rustdoc --skip tests/run-make-fulldeps
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index 371ee378d1a..7cc17e11bdb 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -176,7 +176,6 @@ target | std | notes
 `thumbv8m.base-none-eabi` | * | Bare ARMv8-M Baseline
 `thumbv8m.main-none-eabi` | * | Bare ARMv8-M Mainline
 `thumbv8m.main-none-eabihf` | * | Bare ARMv8-M Mainline, hardfloat
-[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+
 `wasm32-unknown-emscripten` | ✓ | WebAssembly via Emscripten
 `wasm32-unknown-unknown` | ✓ | WebAssembly
 `wasm32-wasi` | ✓ | WebAssembly with WASI
@@ -271,8 +270,8 @@ target | std | host | notes
 `i686-uwp-windows-gnu` | ? |  |
 `i686-uwp-windows-msvc` | ? |  |
 `i686-wrs-vxworks` | ? |  |
-[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64D ABI)
-[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * | LoongArch64 Bare-metal (LP64S ABI)
+[`loongarch64-unknown-none`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64D ABI)
+[`loongarch64-unknown-none-softfloat`](platform-support/loongarch-none.md) | * |  | LoongArch64 Bare-metal (LP64S ABI)
 [`m68k-unknown-linux-gnu`](platform-support/m68k-unknown-linux-gnu.md) | ? |  | Motorola 680x0 Linux
 `mips-unknown-linux-uclibc` | ✓ |  | MIPS Linux with uClibc
 [`mips64-openwrt-linux-musl`](platform-support/mips64-openwrt-linux-musl.md) | ? |  | MIPS64 for OpenWrt Linux MUSL
@@ -314,6 +313,7 @@ target | std | host | notes
 [`riscv64-linux-android`](platform-support/android.md) |   |   | RISC-V 64-bit Android
 `s390x-unknown-linux-musl` |  |  | S390x Linux (kernel 3.2, MUSL)
 `sparc-unknown-linux-gnu` | ✓ |  | 32-bit SPARC Linux
+[`sparc-unknown-none-elf`](./platform-support/sparc-unknown-none-elf.md) | * | Bare 32-bit SPARC V7+
 [`sparc64-unknown-netbsd`](platform-support/netbsd.md) | ✓ | ✓ | NetBSD/sparc64
 [`sparc64-unknown-openbsd`](platform-support/openbsd.md) | ✓ | ✓ | OpenBSD/sparc64
 `thumbv4t-none-eabi` | * |  | Thumb-mode Bare ARMv4T
@@ -321,7 +321,7 @@ target | std | host | notes
 `thumbv7a-pc-windows-msvc` | ? |  |
 `thumbv7a-uwp-windows-msvc` | ✓ |  |
 `thumbv7neon-unknown-linux-musleabihf` | ? |  | Thumb2-mode ARMv7-A Linux with NEON, MUSL
-[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ | WebAssembly with WASI Preview 1 and threads
+[`wasm32-wasi-preview1-threads`](platform-support/wasm32-wasi-preview1-threads.md) | ✓ |  | WebAssembly with WASI Preview 1 and threads
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
 `x86_64-apple-ios-macabi` | ✓ |  | Apple Catalyst on x86_64
 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ? | | x86 64-bit tvOS
diff --git a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
index 8bc9381342d..f8cd92f9257 100644
--- a/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
+++ b/src/doc/rustc/src/platform-support/aarch64-unknown-teeos.md
@@ -8,6 +8,7 @@ TEEOS is a mini os run in TrustZone, for trusted/security apps. The kernel of TE
 It's very small that there is no RwLock, no network, no stdin, and no file system for apps in TEEOS.
 
 Some abbreviation:
+
 | Abbreviation | The full text | Description |
 |  ----  | ----  | ---- |
 | TEE | Trusted Execution Environment | ARM TrustZone divides the system into two worlds/modes -- the secure world/mode and the normal world/mode. TEE is in the secure world/mode. |
diff --git a/src/doc/rustdoc/src/how-to-write-documentation.md b/src/doc/rustdoc/src/how-to-write-documentation.md
index 1fa9f814476..acab1a93690 100644
--- a/src/doc/rustdoc/src/how-to-write-documentation.md
+++ b/src/doc/rustdoc/src/how-to-write-documentation.md
@@ -254,6 +254,19 @@ characters:
 
 So, no need to manually enter those Unicode characters!
 
+### Adding a warning block
+
+If you want to make a warning or similar note stand out in the documentation,
+you can wrap it like this:
+
+```md
+/// documentation
+///
+/// <div class="warning">A big warning!</div>
+///
+/// more documentation
+```
+
 [`backtrace`]: https://docs.rs/backtrace/0.3.50/backtrace/
 [commonmark markdown specification]: https://commonmark.org/
 [commonmark quick reference]: https://commonmark.org/help/
diff --git a/src/doc/rustdoc/src/lints.md b/src/doc/rustdoc/src/lints.md
index fd57b079644..f15e6e451e7 100644
--- a/src/doc/rustdoc/src/lints.md
+++ b/src/doc/rustdoc/src/lints.md
@@ -412,3 +412,37 @@ help: if you meant to use a literal backtick, escape it
 
 warning: 1 warning emitted
 ```
+
+## `redundant_explicit_links`
+
+This lint is **warned by default**. It detects explicit links that are same
+as computed automatic links.
+This usually means the explicit links is removeable. For example:
+
+```rust
+#![warn(rustdoc::redundant_explicit_links)] // note: unnecessary - warns by default.
+
+/// add takes 2 [`usize`](usize) and performs addition
+/// on them, then returns result.
+pub fn add(left: usize, right: usize) -> usize {
+    left + right
+}
+```
+
+Which will give:
+
+```text
+error: redundant explicit rustdoc link
+  --> src/lib.rs:3:27
+   |
+3  | /// add takes 2 [`usize`](usize) and performs addition
+   |                           ^^^^^
+   |
+   = note: Explicit link does not affect the original link
+note: the lint level is defined here
+  --> src/lib.rs:1:9
+   |
+1  | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = help: Remove explicit link instead
+```
diff --git a/src/doc/unstable-book/src/language-features/lang-items.md b/src/doc/unstable-book/src/language-features/lang-items.md
index 1f3d472c3aa..9e20662fff3 100644
--- a/src/doc/unstable-book/src/language-features/lang-items.md
+++ b/src/doc/unstable-book/src/language-features/lang-items.md
@@ -9,26 +9,60 @@ functionality that isn't hard-coded into the language, but is
 implemented in libraries, with a special marker to tell the compiler
 it exists. The marker is the attribute `#[lang = "..."]` and there are
 various different values of `...`, i.e. various different 'lang
-items'.
+items'. Most of them can only be defined once.
 
-For example, `Box` pointers require a lang item for allocation.
-A freestanding program that uses the `Box`
-sugar for dynamic allocations via `malloc` and `free`:
+Lang items are loaded lazily by the compiler; e.g. if one never uses `Box`
+then there is no need to define a function for `exchange_malloc`.
+`rustc` will emit an error when an item is needed but not found in the current
+crate or any that it depends on.
+
+Some features provided by lang items:
+
+- overloadable operators via traits: the traits corresponding to the
+  `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
+  marked with lang items; those specific four are `eq`, `partial_ord`,
+  `deref`/`deref_mut`, and `add` respectively.
+- panicking: the `panic` and `panic_impl` lang items, among others.
+- stack unwinding: the lang item `eh_personality` is a function used by the
+  failure mechanisms of the compiler. This is often mapped to GCC's personality
+  function (see the [`std` implementation][personality] for more information),
+  but programs which don't trigger a panic can be assured that this function is
+  never called. Additionally, a `eh_catch_typeinfo` static is needed for certain
+  targets which implement Rust panics on top of C++ exceptions.
+- the traits in `core::marker` used to indicate types of
+  various kinds; e.g. lang items `sized`, `sync` and `copy`.
+- memory allocation, see below.
+
+Most lang items are defined by `core`, but if you're trying to build
+an executable without the `std` crate, you might run into the need
+for lang item definitions.
+
+[personality]: https://github.com/rust-lang/rust/blob/master/library/std/src/personality/gcc.rs
+
+## Example: Implementing a `Box`
+
+`Box` pointers require two lang items: one for the type itself and one for
+allocation. A freestanding program that uses the `Box` sugar for dynamic
+allocations via `malloc` and `free`:
 
 ```rust,ignore (libc-is-finicky)
-#![feature(lang_items, start, libc, core_intrinsics, rustc_private, rustc_attrs)]
+#![feature(lang_items, start, core_intrinsics, rustc_private, panic_unwind, rustc_attrs)]
 #![allow(internal_features)]
 #![no_std]
+
+extern crate libc;
+extern crate unwind;
+
+use core::ffi::c_void;
 use core::intrinsics;
 use core::panic::PanicInfo;
 use core::ptr::NonNull;
 
-extern crate libc;
-
+pub struct Global; // the global allocator
 struct Unique<T>(NonNull<T>);
 
 #[lang = "owned_box"]
-pub struct Box<T>(Unique<T>);
+pub struct Box<T, A = Global>(Unique<T>, A);
 
 impl<T> Box<T> {
     pub fn new(x: T) -> Self {
@@ -37,24 +71,26 @@ impl<T> Box<T> {
     }
 }
 
+impl<T, A> Drop for Box<T, A> {
+    fn drop(&mut self) {
+        unsafe {
+            libc::free(self.0.0.as_ptr() as *mut c_void);
+        }
+    }
+}
+
 #[lang = "exchange_malloc"]
 unsafe fn allocate(size: usize, _align: usize) -> *mut u8 {
-    let p = libc::malloc(size as libc::size_t) as *mut u8;
+    let p = libc::malloc(size) as *mut u8;
 
     // Check if `malloc` failed:
-    if p as usize == 0 {
+    if p.is_null() {
         intrinsics::abort();
     }
 
     p
 }
 
-impl<T> Drop for Box<T> {
-    fn drop(&mut self) {
-      libc::free(self.0.0.0 as *mut libc::c_void)
-    }
-}
-
 #[start]
 fn main(_argc: isize, _argv: *const *const u8) -> isize {
     let _x = Box::new(1);
@@ -62,247 +98,18 @@ fn main(_argc: isize, _argv: *const *const u8) -> isize {
     0
 }
 
-#[lang = "eh_personality"] extern fn rust_eh_personality() {}
-#[lang = "panic_impl"] extern fn rust_begin_panic(_info: &PanicInfo) -> ! { intrinsics::abort() }
-#[no_mangle] pub extern fn rust_eh_register_frames () {}
-#[no_mangle] pub extern fn rust_eh_unregister_frames () {}
-```
-
-Note the use of `abort`: the `exchange_malloc` lang item is assumed to
-return a valid pointer, and so needs to do the check internally.
-
-Other features provided by lang items include:
-
-- overloadable operators via traits: the traits corresponding to the
-  `==`, `<`, dereferencing (`*`) and `+` (etc.) operators are all
-  marked with lang items; those specific four are `eq`, `ord`,
-  `deref`, and `add` respectively.
-- stack unwinding and general failure; the `eh_personality`,
-  `panic` and `panic_bounds_check` lang items.
-- the traits in `std::marker` used to indicate types of
-  various kinds; lang items `send`, `sync` and `copy`.
-- the marker types and variance indicators found in
-  `std::marker`; lang items `covariant_type`,
-  `contravariant_lifetime`, etc.
-
-Lang items are loaded lazily by the compiler; e.g. if one never uses
-`Box` then there is no need to define a function for `exchange_malloc`.
-`rustc` will emit an error when an item is needed
-but not found in the current crate or any that it depends on.
-
-Most lang items are defined by `libcore`, but if you're trying to build
-an executable without the standard library, you'll run into the need
-for lang items. The rest of this page focuses on this use-case, even though
-lang items are a bit broader than that.
-
-### Using libc
-
-In order to build a `#[no_std]` executable we will need libc as a dependency.
-We can specify this using our `Cargo.toml` file:
-
-```toml
-[dependencies]
-libc = { version = "0.2.14", default-features = false }
-```
-
-Note that the default features have been disabled. This is a critical step -
-**the default features of libc include the standard library and so must be
-disabled.**
-
-### Writing an executable without stdlib
-
-Controlling the entry point is possible in two ways: the `#[start]` attribute,
-or overriding the default shim for the C `main` function with your own.
-
-The function marked `#[start]` is passed the command line parameters
-in the same format as C:
-
-```rust,ignore (libc-is-finicky)
-#![feature(lang_items, core_intrinsics, rustc_private)]
-#![feature(start)]
-#![allow(internal_features)]
-#![no_std]
-use core::intrinsics;
-use core::panic::PanicInfo;
-
-// Pull in the system libc library for what crt0.o likely requires.
-extern crate libc;
-
-// Entry point for this program.
-#[start]
-fn start(_argc: isize, _argv: *const *const u8) -> isize {
-    0
-}
-
-// These functions are used by the compiler, but not
-// for a bare-bones hello world. These are normally
-// provided by libstd.
-#[lang = "eh_personality"]
-#[no_mangle]
-pub extern fn rust_eh_personality() {
-}
-
-#[lang = "panic_impl"]
-#[no_mangle]
-pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
-    unsafe { intrinsics::abort() }
-}
-```
-
-To override the compiler-inserted `main` shim, one has to disable it
-with `#![no_main]` and then create the appropriate symbol with the
-correct ABI and the correct name, which requires overriding the
-compiler's name mangling too:
-
-```rust,ignore (libc-is-finicky)
-#![feature(lang_items, core_intrinsics, rustc_private)]
-#![feature(start)]
-#![allow(internal_features)]
-#![no_std]
-#![no_main]
-use core::intrinsics;
-use core::panic::PanicInfo;
-
-// Pull in the system libc library for what crt0.o likely requires.
-extern crate libc;
-
-// Entry point for this program.
-#[no_mangle] // ensure that this symbol is called `main` in the output
-pub extern fn main(_argc: i32, _argv: *const *const u8) -> i32 {
-    0
-}
-
-// These functions are used by the compiler, but not
-// for a bare-bones hello world. These are normally
-// provided by libstd.
 #[lang = "eh_personality"]
-#[no_mangle]
-pub extern fn rust_eh_personality() {
-}
+fn rust_eh_personality() {}
 
-#[lang = "panic_impl"]
-#[no_mangle]
-pub extern fn rust_begin_panic(info: &PanicInfo) -> ! {
-    unsafe { intrinsics::abort() }
-}
+#[panic_handler]
+fn panic_handler(_info: &PanicInfo) -> ! { intrinsics::abort() }
 ```
 
-In many cases, you may need to manually link to the `compiler_builtins` crate
-when building a `no_std` binary. You may observe this via linker error messages
-such as "```undefined reference to `__rust_probestack'```".
-
-## More about the language items
-
-The compiler currently makes a few assumptions about symbols which are
-available in the executable to call. Normally these functions are provided by
-the standard library, but without it you must define your own. These symbols
-are called "language items", and they each have an internal name, and then a
-signature that an implementation must conform to.
-
-The first of these functions, `rust_eh_personality`, is used by the failure
-mechanisms of the compiler. This is often mapped to GCC's personality function
-(see the [libstd implementation][unwind] for more information), but crates
-which do not trigger a panic can be assured that this function is never
-called. The language item's name is `eh_personality`.
-
-[unwind]: https://github.com/rust-lang/rust/blob/master/library/panic_unwind/src/gcc.rs
-
-The second function, `rust_begin_panic`, is also used by the failure mechanisms of the
-compiler. When a panic happens, this controls the message that's displayed on
-the screen. While the language item's name is `panic_impl`, the symbol name is
-`rust_begin_panic`.
-
-Finally, a `eh_catch_typeinfo` static is needed for certain targets which
-implement Rust panics on top of C++ exceptions.
+Note the use of `abort`: the `exchange_malloc` lang item is assumed to
+return a valid pointer, and so needs to do the check internally.
 
 ## List of all language items
 
-This is a list of all language items in Rust along with where they are located in
-the source code.
+An up-to-date list of all language items can be found [here] in the compiler code.
 
-- Primitives
-  - `i8`: `libcore/num/mod.rs`
-  - `i16`: `libcore/num/mod.rs`
-  - `i32`: `libcore/num/mod.rs`
-  - `i64`: `libcore/num/mod.rs`
-  - `i128`: `libcore/num/mod.rs`
-  - `isize`: `libcore/num/mod.rs`
-  - `u8`: `libcore/num/mod.rs`
-  - `u16`: `libcore/num/mod.rs`
-  - `u32`: `libcore/num/mod.rs`
-  - `u64`: `libcore/num/mod.rs`
-  - `u128`: `libcore/num/mod.rs`
-  - `usize`: `libcore/num/mod.rs`
-  - `f32`: `libstd/f32.rs`
-  - `f64`: `libstd/f64.rs`
-  - `char`: `libcore/char.rs`
-  - `slice`: `liballoc/slice.rs`
-  - `str`: `liballoc/str.rs`
-  - `const_ptr`: `libcore/ptr.rs`
-  - `mut_ptr`: `libcore/ptr.rs`
-  - `unsafe_cell`: `libcore/cell.rs`
-- Runtime
-  - `start`: `libstd/rt.rs`
-  - `eh_personality`: `libpanic_unwind/emcc.rs` (EMCC)
-  - `eh_personality`: `libpanic_unwind/gcc.rs` (GNU)
-  - `eh_personality`: `libpanic_unwind/seh.rs` (SEH)
-  - `eh_catch_typeinfo`: `libpanic_unwind/emcc.rs` (EMCC)
-  - `panic`: `libcore/panicking.rs`
-  - `panic_bounds_check`: `libcore/panicking.rs`
-  - `panic_impl`: `libcore/panicking.rs`
-  - `panic_impl`: `libstd/panicking.rs`
-- Allocations
-  - `owned_box`: `liballoc/boxed.rs`
-  - `exchange_malloc`: `liballoc/heap.rs`
-- Operands
-  - `not`: `libcore/ops/bit.rs`
-  - `bitand`: `libcore/ops/bit.rs`
-  - `bitor`: `libcore/ops/bit.rs`
-  - `bitxor`: `libcore/ops/bit.rs`
-  - `shl`: `libcore/ops/bit.rs`
-  - `shr`: `libcore/ops/bit.rs`
-  - `bitand_assign`: `libcore/ops/bit.rs`
-  - `bitor_assign`: `libcore/ops/bit.rs`
-  - `bitxor_assign`: `libcore/ops/bit.rs`
-  - `shl_assign`: `libcore/ops/bit.rs`
-  - `shr_assign`: `libcore/ops/bit.rs`
-  - `deref`: `libcore/ops/deref.rs`
-  - `deref_mut`: `libcore/ops/deref.rs`
-  - `index`: `libcore/ops/index.rs`
-  - `index_mut`: `libcore/ops/index.rs`
-  - `add`: `libcore/ops/arith.rs`
-  - `sub`: `libcore/ops/arith.rs`
-  - `mul`: `libcore/ops/arith.rs`
-  - `div`: `libcore/ops/arith.rs`
-  - `rem`: `libcore/ops/arith.rs`
-  - `neg`: `libcore/ops/arith.rs`
-  - `add_assign`: `libcore/ops/arith.rs`
-  - `sub_assign`: `libcore/ops/arith.rs`
-  - `mul_assign`: `libcore/ops/arith.rs`
-  - `div_assign`: `libcore/ops/arith.rs`
-  - `rem_assign`: `libcore/ops/arith.rs`
-  - `eq`: `libcore/cmp.rs`
-  - `ord`: `libcore/cmp.rs`
-- Functions
-  - `fn`: `libcore/ops/function.rs`
-  - `fn_mut`: `libcore/ops/function.rs`
-  - `fn_once`: `libcore/ops/function.rs`
-  - `generator_state`: `libcore/ops/generator.rs`
-  - `generator`: `libcore/ops/generator.rs`
-- Other
-  - `coerce_unsized`: `libcore/ops/unsize.rs`
-  - `drop`: `libcore/ops/drop.rs`
-  - `drop_in_place`: `libcore/ptr.rs`
-  - `clone`: `libcore/clone.rs`
-  - `copy`: `libcore/marker.rs`
-  - `send`: `libcore/marker.rs`
-  - `sized`: `libcore/marker.rs`
-  - `unsize`: `libcore/marker.rs`
-  - `sync`: `libcore/marker.rs`
-  - `phantom_data`: `libcore/marker.rs`
-  - `discriminant_kind`: `libcore/marker.rs`
-  - `freeze`: `libcore/marker.rs`
-  - `debug_trait`: `libcore/fmt/mod.rs`
-  - `non_zero`: `libcore/nonzero.rs`
-  - `arc`: `liballoc/sync.rs`
-  - `rc`: `liballoc/rc.rs`
+[here]: https://github.com/rust-lang/rust/blob/master/compiler/rustc_hir/src/lang_items.rs
diff --git a/src/doc/unstable-book/src/language-features/start.md b/src/doc/unstable-book/src/language-features/start.md
new file mode 100644
index 00000000000..09e4875a2e4
--- /dev/null
+++ b/src/doc/unstable-book/src/language-features/start.md
@@ -0,0 +1,59 @@
+# `start`
+
+The tracking issue for this feature is: [#29633]
+
+[#29633]: https://github.com/rust-lang/rust/issues/29633
+
+------------------------
+
+Allows you to mark a function as the entry point of the executable, which is
+necessary in `#![no_std]` environments.
+
+The function marked `#[start]` is passed the command line parameters in the same
+format as the C main function (aside from the integer types being used).
+It has to be non-generic and have the following signature:
+
+```rust,ignore (only-for-syntax-highlight)
+# let _:
+fn(isize, *const *const u8) -> isize
+# ;
+```
+
+This feature should not be confused with the `start` *lang item* which is
+defined by the `std` crate and is written `#[lang = "start"]`.
+
+## Usage together with the `std` crate
+
+`#[start]` can be used in combination with the `std` crate, in which case the
+normal `main` function (which would get called from the `std` crate) won't be
+used as an entry point.
+The initialization code in `std` will be skipped this way.
+
+Example:
+
+```rust
+#![feature(start)]
+
+#[start]
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+    0
+}
+```
+
+Unwinding the stack past the `#[start]` function is currently considered
+Undefined Behavior (for any unwinding implementation):
+
+```rust,ignore (UB)
+#![feature(start)]
+
+#[start]
+fn start(_argc: isize, _argv: *const *const u8) -> isize {
+    std::panic::catch_unwind(|| {
+        panic!(); // panic safely gets caught or safely aborts execution
+    });
+
+    panic!(); // UB!
+
+    0
+}
+```
diff --git a/src/librustdoc/html/markdown.rs b/src/librustdoc/html/markdown.rs
index 0ba2d992392..98cc38a10d4 100644
--- a/src/librustdoc/html/markdown.rs
+++ b/src/librustdoc/html/markdown.rs
@@ -50,7 +50,7 @@ use crate::html::render::small_url_encode;
 use crate::html::toc::TocBuilder;
 
 use pulldown_cmark::{
-    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, Options, Parser, Tag,
+    html, BrokenLink, CodeBlockKind, CowStr, Event, LinkType, OffsetIter, Options, Parser, Tag,
 };
 
 #[cfg(test)]
@@ -1240,6 +1240,7 @@ pub(crate) fn plain_text_summary(md: &str, link_names: &[RenderedLink]) -> Strin
 pub(crate) struct MarkdownLink {
     pub kind: LinkType,
     pub link: String,
+    pub display_text: Option<String>,
     pub range: MarkdownLinkRange,
 }
 
@@ -1263,8 +1264,8 @@ impl MarkdownLinkRange {
     }
 }
 
-pub(crate) fn markdown_links<R>(
-    md: &str,
+pub(crate) fn markdown_links<'md, R>(
+    md: &'md str,
     preprocess_link: impl Fn(MarkdownLink) -> Option<R>,
 ) -> Vec<R> {
     if md.is_empty() {
@@ -1375,32 +1376,90 @@ pub(crate) fn markdown_links<R>(
         MarkdownLinkRange::Destination(range.clone())
     };
 
-    Parser::new_with_broken_link_callback(
+    let mut broken_link_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut event_iter = Parser::new_with_broken_link_callback(
         md,
         main_body_opts(),
-        Some(&mut |link: BrokenLink<'_>| Some((link.reference, "".into()))),
+        Some(&mut broken_link_callback),
     )
-    .into_offset_iter()
-    .filter_map(|(event, span)| match event {
-        Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
-            let range = match link_type {
-                // Link is pulled from the link itself.
-                LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
-                    span_for_offset_backward(span, b'[', b']')
-                }
-                LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
-                LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
-                // Link is pulled from elsewhere in the document.
-                LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
-                    span_for_link(&dest, span)
+    .into_offset_iter();
+    let mut links = Vec::new();
+
+    while let Some((event, span)) = event_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) if may_be_doc_link(link_type) => {
+                let range = match link_type {
+                    // Link is pulled from the link itself.
+                    LinkType::ReferenceUnknown | LinkType::ShortcutUnknown => {
+                        span_for_offset_backward(span, b'[', b']')
+                    }
+                    LinkType::CollapsedUnknown => span_for_offset_forward(span, b'[', b']'),
+                    LinkType::Inline => span_for_offset_backward(span, b'(', b')'),
+                    // Link is pulled from elsewhere in the document.
+                    LinkType::Reference | LinkType::Collapsed | LinkType::Shortcut => {
+                        span_for_link(&dest, span)
+                    }
+                    LinkType::Autolink | LinkType::Email => unreachable!(),
+                };
+
+                let display_text = if matches!(
+                    link_type,
+                    LinkType::Inline
+                        | LinkType::ReferenceUnknown
+                        | LinkType::Reference
+                        | LinkType::Shortcut
+                        | LinkType::ShortcutUnknown
+                ) {
+                    collect_link_data(&mut event_iter)
+                } else {
+                    None
+                };
+
+                if let Some(link) = preprocess_link(MarkdownLink {
+                    kind: link_type,
+                    link: dest.into_string(),
+                    display_text,
+                    range,
+                }) {
+                    links.push(link);
                 }
-                LinkType::Autolink | LinkType::Email => unreachable!(),
-            };
-            preprocess_link(MarkdownLink { kind: link_type, range, link: dest.into_string() })
+            }
+            _ => {}
         }
-        _ => None,
-    })
-    .collect()
+    }
+
+    links
+}
+
+/// Collects additional data of link.
+fn collect_link_data<'input, 'callback>(
+    event_iter: &mut OffsetIter<'input, 'callback>,
+) -> Option<String> {
+    let mut display_text: Option<String> = None;
+    let mut append_text = |text: CowStr<'_>| {
+        if let Some(display_text) = &mut display_text {
+            display_text.push_str(&text);
+        } else {
+            display_text = Some(text.to_string());
+        }
+    };
+
+    while let Some((event, _span)) = event_iter.next() {
+        match event {
+            Event::Text(text) => {
+                append_text(text);
+            }
+            Event::Code(code) => {
+                append_text(code);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    display_text
 }
 
 #[derive(Debug)]
diff --git a/src/librustdoc/html/static/css/rustdoc.css b/src/librustdoc/html/static/css/rustdoc.css
index b1de8c1529e..da4da50106a 100644
--- a/src/librustdoc/html/static/css/rustdoc.css
+++ b/src/librustdoc/html/static/css/rustdoc.css
@@ -270,7 +270,7 @@ ul ul, ol ul, ul ol, ol ol {
 	margin-bottom: .625em;
 }
 
-p {
+p, .docblock > .warning {
 	/* Paragraph spacing at least 1.5 times line spacing per Web Content Accessibility Guidelines.
 	   Line-height is 1.5rem, so line spacing is .5rem; .75em is 1.5 times that.
 	   https://www.w3.org/WAI/WCAG21/Understanding/visual-presentation.html */
@@ -278,7 +278,7 @@ p {
 }
 /* For the last child of a div, the margin will be taken care of
 	by the margin-top of the next item. */
-p:last-child {
+p:last-child, .docblock > .warning:last-child {
 	margin: 0;
 }
 
@@ -1096,7 +1096,7 @@ pre.rust .doccomment {
 }
 
 .example-wrap.ignore .tooltip {
-	color:  var(--codeblock-ignore-color);
+	color: var(--codeblock-ignore-color);
 }
 
 .example-wrap.compile_fail:hover .tooltip,
@@ -1124,6 +1124,26 @@ pre.rust .doccomment {
 	font-size: 1.25rem;
 }
 
+/* This class only exists for users who want to draw attention to a particular element in their
+documentation. */
+.content .docblock .warning {
+	border-left: 2px solid var(--warning-border-color);
+	padding: 14px;
+	position: relative;
+	/* The "!important" part is required because the rule is otherwise overruled in this CSS
+	selector: ".docblock > :not(.more-examples-toggle):not(.example-wrap)" */
+	overflow-x: visible !important;
+}
+.content .docblock .warning::before {
+	color: var(--warning-border-color);
+	content: "ⓘ";
+	position: absolute;
+	left: -25px;
+	top: 5px;
+	font-weight: bold;
+	font-size: 1.25rem;
+}
+
 a.test-arrow {
 	visibility: hidden;
 	position: absolute;
diff --git a/src/librustdoc/html/static/css/themes/ayu.css b/src/librustdoc/html/static/css/themes/ayu.css
index d8dae51eb1b..c81a80eeca0 100644
--- a/src/librustdoc/html/static/css/themes/ayu.css
+++ b/src/librustdoc/html/static/css/themes/ayu.css
@@ -31,6 +31,7 @@ Original by Dempfi (https://github.com/dempfi/ayu)
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--warning-border-color: rgb(255, 142, 0);
 	--type-link-color: #ffa0a5;
 	--trait-link-color: #39afd7;
 	--assoc-item-link-color: #39afd7;
diff --git a/src/librustdoc/html/static/css/themes/dark.css b/src/librustdoc/html/static/css/themes/dark.css
index 2b302988734..0f8b1dc24a6 100644
--- a/src/librustdoc/html/static/css/themes/dark.css
+++ b/src/librustdoc/html/static/css/themes/dark.css
@@ -26,6 +26,7 @@
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--warning-border-color: rgb(255, 142, 0);
 	--type-link-color: #2dbfb8;
 	--trait-link-color: #b78cf2;
 	--assoc-item-link-color: #d2991d;
diff --git a/src/librustdoc/html/static/css/themes/light.css b/src/librustdoc/html/static/css/themes/light.css
index 56fd8cbef12..39ea44a1165 100644
--- a/src/librustdoc/html/static/css/themes/light.css
+++ b/src/librustdoc/html/static/css/themes/light.css
@@ -26,6 +26,7 @@
 	--codeblock-error-color: rgba(255, 0, 0, .5);
 	--codeblock-ignore-hover-color: rgb(255, 142, 0);
 	--codeblock-ignore-color: rgba(255, 142, 0, .6);
+	--warning-border-color: rgb(255, 142, 0);
 	--type-link-color: #ad378a;
 	--trait-link-color: #6e4fc9;
 	--assoc-item-link-color: #3873ad;
diff --git a/src/librustdoc/lint.rs b/src/librustdoc/lint.rs
index 749c1ff51bf..d45040e348a 100644
--- a/src/librustdoc/lint.rs
+++ b/src/librustdoc/lint.rs
@@ -185,6 +185,17 @@ declare_rustdoc_lint! {
    "detects unescaped backticks in doc comments"
 }
 
+declare_rustdoc_lint! {
+    /// This lint is **warned by default**. It detects explicit links that are same
+    /// as computed automatic links. This usually means the explicit links is removeable.
+    /// This is a `rustdoc` only lint, see the documentation in the [rustdoc book].
+    ///
+    /// [rustdoc book]: ../../../rustdoc/lints.html#redundant_explicit_links
+    REDUNDANT_EXPLICIT_LINKS,
+    Warn,
+    "detects redundant explicit links in doc comments"
+}
+
 pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
     vec![
         BROKEN_INTRA_DOC_LINKS,
@@ -197,6 +208,7 @@ pub(crate) static RUSTDOC_LINTS: Lazy<Vec<&'static Lint>> = Lazy::new(|| {
         BARE_URLS,
         MISSING_CRATE_LEVEL_DOCS,
         UNESCAPED_BACKTICKS,
+        REDUNDANT_EXPLICIT_LINKS,
     ]
 });
 
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 26ff64f06a3..7b0a7a90d31 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -994,7 +994,7 @@ impl LinkCollector<'_, '_> {
                 _ => find_nearest_parent_module(self.cx.tcx, item_id).unwrap(),
             };
             for md_link in preprocessed_markdown_links(&doc) {
-                let link = self.resolve_link(item, item_id, module_id, &doc, &md_link);
+                let link = self.resolve_link(&doc, item, item_id, module_id, &md_link);
                 if let Some(link) = link {
                     self.cx.cache.intra_doc_links.entry(item.item_id).or_default().insert(link);
                 }
@@ -1007,13 +1007,12 @@ impl LinkCollector<'_, '_> {
     /// FIXME(jynelson): this is way too many arguments
     fn resolve_link(
         &mut self,
+        dox: &String,
         item: &Item,
         item_id: DefId,
         module_id: DefId,
-        dox: &str,
-        link: &PreprocessedMarkdownLink,
+        PreprocessedMarkdownLink(pp_link, ori_link): &PreprocessedMarkdownLink,
     ) -> Option<ItemLink> {
-        let PreprocessedMarkdownLink(pp_link, ori_link) = link;
         trace!("considering link '{}'", ori_link.link);
 
         let diag_info = DiagnosticInfo {
@@ -1022,7 +1021,6 @@ impl LinkCollector<'_, '_> {
             ori_link: &ori_link.link,
             link_range: ori_link.range.clone(),
         };
-
         let PreprocessingInfo { path_str, disambiguator, extra_fragment, link_text } =
             pp_link.as_ref().map_err(|err| err.report(self.cx, diag_info.clone())).ok()?;
         let disambiguator = *disambiguator;
@@ -1040,8 +1038,24 @@ impl LinkCollector<'_, '_> {
             // resolutions are cached, for other links we want to report an error every
             // time so they are not cached.
             matches!(ori_link.kind, LinkType::Reference | LinkType::Shortcut),
+            false,
         )?;
 
+        if ori_link.display_text.is_some() {
+            self.resolve_display_text(
+                path_str,
+                ResolutionInfo {
+                    item_id,
+                    module_id,
+                    dis: disambiguator,
+                    path_str: ori_link.display_text.clone()?.into_boxed_str(),
+                    extra_fragment: extra_fragment.clone(),
+                },
+                &ori_link,
+                &diag_info,
+            );
+        }
+
         // Check for a primitive which might conflict with a module
         // Report the ambiguity and require that the user specify which one they meant.
         // FIXME: could there ever be a primitive not in the type namespace?
@@ -1221,6 +1235,9 @@ impl LinkCollector<'_, '_> {
         // If errors are cached then they are only reported on first occurrence
         // which we want in some cases but not in others.
         cache_errors: bool,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Option<(Res, Option<UrlFragment>)> {
         if let Some(res) = self.visited_links.get(&key) {
             if res.is_some() || cache_errors {
@@ -1228,7 +1245,7 @@ impl LinkCollector<'_, '_> {
             }
         }
 
-        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone());
+        let mut candidates = self.resolve_with_disambiguator(&key, diag.clone(), recoverable);
 
         // FIXME: it would be nice to check that the feature gate was enabled in the original crate, not just ignore it altogether.
         // However I'm not sure how to check that across crates.
@@ -1279,6 +1296,9 @@ impl LinkCollector<'_, '_> {
         &mut self,
         key: &ResolutionInfo,
         diag: DiagnosticInfo<'_>,
+        // If this call is intended to be recoverable, then pass true to silence.
+        // This is only recoverable when path is failed to resolved.
+        recoverable: bool,
     ) -> Vec<(Res, Option<DefId>)> {
         let disambiguator = key.dis;
         let path_str = &key.path_str;
@@ -1308,7 +1328,9 @@ impl LinkCollector<'_, '_> {
                                 }
                             }
                         }
-                        resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        if !recoverable {
+                            resolution_failure(self, diag, path_str, disambiguator, smallvec![err]);
+                        }
                         return vec![];
                     }
                 }
@@ -1345,13 +1367,15 @@ impl LinkCollector<'_, '_> {
                     .fold(0, |acc, res| if let Ok(res) = res { acc + res.len() } else { acc });
 
                 if len == 0 {
-                    resolution_failure(
-                        self,
-                        diag,
-                        path_str,
-                        disambiguator,
-                        candidates.into_iter().filter_map(|res| res.err()).collect(),
-                    );
+                    if !recoverable {
+                        resolution_failure(
+                            self,
+                            diag,
+                            path_str,
+                            disambiguator,
+                            candidates.into_iter().filter_map(|res| res.err()).collect(),
+                        );
+                    }
                     return vec![];
                 } else if len == 1 {
                     candidates.into_iter().filter_map(|res| res.ok()).flatten().collect::<Vec<_>>()
@@ -1372,6 +1396,58 @@ impl LinkCollector<'_, '_> {
             }
         }
     }
+
+    /// Resolve display text if the provided link has separated parts of links.
+    ///
+    /// For example:
+    /// Inline link `[display_text](dest_link)` and reference link `[display_text][reference_link]` has
+    /// separated parts of links.
+    fn resolve_display_text(
+        &mut self,
+        explicit_link: &Box<str>,
+        display_res_info: ResolutionInfo,
+        ori_link: &MarkdownLink,
+        diag_info: &DiagnosticInfo<'_>,
+    ) {
+        // Check if explicit resolution's path is same as resolution of original link's display text path, see
+        // tests/rustdoc-ui/lint/redundant_explicit_links.rs for more cases.
+        //
+        // To avoid disambiguator from panicking, we check if display text path is possible to be disambiguated
+        // into explicit path.
+        if !matches!(
+            ori_link.kind,
+            LinkType::Inline | LinkType::Reference | LinkType::ReferenceUnknown
+        ) {
+            return;
+        }
+
+        // Algorithm to check if display text could possibly be the explicit link:
+        //
+        // Consider 2 links which are display text and explicit link, pick the shorter
+        // one as symbol and longer one as full qualified path, and tries to match symbol
+        // to the full qualified path's last symbol.
+        //
+        // Otherwise, check if 2 links are same, if so, skip the resolve process.
+        //
+        // Notice that this algorithm is passive, might possibly miss actual redudant cases.
+        let explicit_link = explicit_link.to_string();
+        let display_text = ori_link.display_text.as_ref().unwrap();
+
+        if display_text.len() == explicit_link.len() {
+            // Whether they are same or not, skip the resolve process.
+            return;
+        }
+
+        if explicit_link.ends_with(&display_text[..]) || display_text.ends_with(&explicit_link[..])
+        {
+            self.resolve_with_disambiguator_cached(
+                display_res_info,
+                diag_info.clone(), // this struct should really be Copy, but Range is not :(
+                false,
+                true,
+            );
+        }
+    }
 }
 
 /// Get the section of a link between the backticks,
diff --git a/src/librustdoc/passes/lint.rs b/src/librustdoc/passes/lint.rs
index e653207b9b6..c6d5b7bd346 100644
--- a/src/librustdoc/passes/lint.rs
+++ b/src/librustdoc/passes/lint.rs
@@ -4,6 +4,7 @@
 mod bare_urls;
 mod check_code_block_syntax;
 mod html_tags;
+mod redundant_explicit_links;
 mod unescaped_backticks;
 
 use super::Pass;
@@ -29,6 +30,7 @@ impl<'a, 'tcx> DocVisitor for Linter<'a, 'tcx> {
         check_code_block_syntax::visit_item(self.cx, item);
         html_tags::visit_item(self.cx, item);
         unescaped_backticks::visit_item(self.cx, item);
+        redundant_explicit_links::visit_item(self.cx, item);
 
         self.visit_item_recur(item)
     }
diff --git a/src/librustdoc/passes/lint/redundant_explicit_links.rs b/src/librustdoc/passes/lint/redundant_explicit_links.rs
new file mode 100644
index 00000000000..67cd2cc9732
--- /dev/null
+++ b/src/librustdoc/passes/lint/redundant_explicit_links.rs
@@ -0,0 +1,347 @@
+use std::ops::Range;
+
+use pulldown_cmark::{BrokenLink, CowStr, Event, LinkType, OffsetIter, Parser, Tag};
+use rustc_ast::NodeId;
+use rustc_errors::SuggestionStyle;
+use rustc_hir::def::{DefKind, DocLinkResMap, Namespace, Res};
+use rustc_hir::HirId;
+use rustc_lint_defs::Applicability;
+use rustc_span::Symbol;
+
+use crate::clean::utils::find_nearest_parent_module;
+use crate::clean::utils::inherits_doc_hidden;
+use crate::clean::Item;
+use crate::core::DocContext;
+use crate::html::markdown::main_body_opts;
+use crate::passes::source_span_for_markdown_range;
+
+#[derive(Debug)]
+struct LinkData {
+    resolvable_link: Option<String>,
+    resolvable_link_range: Option<Range<usize>>,
+    display_link: String,
+}
+
+pub(crate) fn visit_item(cx: &DocContext<'_>, item: &Item) {
+    let Some(hir_id) = DocContext::as_local_hir_id(cx.tcx, item.item_id) else {
+        // If non-local, no need to check anything.
+        return;
+    };
+
+    let doc = item.doc_value();
+    if doc.is_empty() {
+        return;
+    }
+
+    if item.link_names(&cx.cache).is_empty() {
+        // If there's no link names in this item,
+        // then we skip resolution querying to
+        // avoid from panicking.
+        return;
+    }
+
+    let Some(item_id) = item.def_id() else {
+        return;
+    };
+    let Some(local_item_id) = item_id.as_local() else {
+        return;
+    };
+
+    let is_hidden = !cx.render_options.document_hidden
+        && (item.is_doc_hidden() || inherits_doc_hidden(cx.tcx, local_item_id, None));
+    if is_hidden {
+        return;
+    }
+    let is_private = !cx.render_options.document_private
+        && !cx.cache.effective_visibilities.is_directly_public(cx.tcx, item_id);
+    if is_private {
+        return;
+    }
+
+    check_redundant_explicit_link(cx, item, hir_id, &doc);
+}
+
+fn check_redundant_explicit_link<'md>(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &'md str,
+) -> Option<()> {
+    let mut broken_line_callback = |link: BrokenLink<'md>| Some((link.reference, "".into()));
+    let mut offset_iter = Parser::new_with_broken_link_callback(
+        &doc,
+        main_body_opts(),
+        Some(&mut broken_line_callback),
+    )
+    .into_offset_iter();
+    let item_id = item.def_id()?;
+    let module_id = match cx.tcx.def_kind(item_id) {
+        DefKind::Mod if item.inner_docs(cx.tcx) => item_id,
+        _ => find_nearest_parent_module(cx.tcx, item_id).unwrap(),
+    };
+    let resolutions = cx.tcx.doc_link_resolutions(module_id);
+
+    while let Some((event, link_range)) = offset_iter.next() {
+        match event {
+            Event::Start(Tag::Link(link_type, dest, _)) => {
+                let link_data = collect_link_data(&mut offset_iter);
+
+                if let Some(resolvable_link) = link_data.resolvable_link.as_ref() {
+                    if &link_data.display_link.replace("`", "") != resolvable_link {
+                        // Skips if display link does not match to actual
+                        // resolvable link, usually happens if display link
+                        // has several segments, e.g.
+                        // [this is just an `Option`](Option)
+                        continue;
+                    }
+                }
+
+                let explicit_link = dest.to_string();
+                let display_link = link_data.resolvable_link.clone()?;
+
+                if explicit_link.ends_with(&display_link) || display_link.ends_with(&explicit_link)
+                {
+                    match link_type {
+                        LinkType::Inline | LinkType::ReferenceUnknown => {
+                            check_inline_or_reference_unknown_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                dest.to_string(),
+                                link_data,
+                                if link_type == LinkType::Inline {
+                                    (b'(', b')')
+                                } else {
+                                    (b'[', b']')
+                                },
+                            );
+                        }
+                        LinkType::Reference => {
+                            check_reference_redundancy(
+                                cx,
+                                item,
+                                hir_id,
+                                doc,
+                                resolutions,
+                                link_range,
+                                &dest,
+                                link_data,
+                            );
+                        }
+                        _ => {}
+                    }
+                }
+            }
+            _ => {}
+        }
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_inline_or_reference_unknown_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: String,
+    link_data: LinkData,
+    (open, close): (u8, u8),
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range, open, close),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+/// FIXME(ChAoSUnItY): Too many arguments.
+fn check_reference_redundancy(
+    cx: &DocContext<'_>,
+    item: &Item,
+    hir_id: HirId,
+    doc: &str,
+    resolutions: &DocLinkResMap,
+    link_range: Range<usize>,
+    dest: &CowStr<'_>,
+    link_data: LinkData,
+) -> Option<()> {
+    let (resolvable_link, resolvable_link_range) =
+        (&link_data.resolvable_link?, &link_data.resolvable_link_range?);
+    let (dest_res, display_res) =
+        (find_resolution(resolutions, &dest)?, find_resolution(resolutions, resolvable_link)?);
+
+    if dest_res == display_res {
+        let link_span = source_span_for_markdown_range(cx.tcx, &doc, &link_range, &item.attrs)
+            .unwrap_or(item.attr_span(cx.tcx));
+        let explicit_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_explicit_range(doc, link_range.clone(), b'[', b']'),
+            &item.attrs,
+        )?;
+        let display_span =
+            source_span_for_markdown_range(cx.tcx, &doc, &resolvable_link_range, &item.attrs)?;
+        let def_span = source_span_for_markdown_range(
+            cx.tcx,
+            &doc,
+            &offset_reference_def_range(doc, dest, link_range),
+            &item.attrs,
+        )?;
+
+        cx.tcx.struct_span_lint_hir(crate::lint::REDUNDANT_EXPLICIT_LINKS, hir_id, explicit_span, "redundant explicit link target", |lint| {
+            lint.span_label(explicit_span, "explicit target is redundant")
+                .span_label(display_span, "because label contains path that resolves to same destination")
+                .span_note(def_span, "referenced explicit link target defined here")
+                .note("when a link's destination is not specified,\nthe label is used to resolve intra-doc links")
+                .span_suggestion_with_style(link_span, "remove explicit link target", format!("[{}]", link_data.display_link), Applicability::MaybeIncorrect, SuggestionStyle::ShowAlways);
+
+            lint
+        });
+    }
+
+    None
+}
+
+fn find_resolution(resolutions: &DocLinkResMap, path: &str) -> Option<Res<NodeId>> {
+    [Namespace::TypeNS, Namespace::ValueNS, Namespace::MacroNS]
+        .into_iter()
+        .find_map(|ns| resolutions.get(&(Symbol::intern(path), ns)).copied().flatten())
+}
+
+/// Collects all neccessary data of link.
+fn collect_link_data(offset_iter: &mut OffsetIter<'_, '_>) -> LinkData {
+    let mut resolvable_link = None;
+    let mut resolvable_link_range = None;
+    let mut display_link = String::new();
+
+    while let Some((event, range)) = offset_iter.next() {
+        match event {
+            Event::Text(code) => {
+                let code = code.to_string();
+                display_link.push_str(&code);
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::Code(code) => {
+                let code = code.to_string();
+                display_link.push('`');
+                display_link.push_str(&code);
+                display_link.push('`');
+                resolvable_link = Some(code);
+                resolvable_link_range = Some(range);
+            }
+            Event::End(_) => {
+                break;
+            }
+            _ => {}
+        }
+    }
+
+    LinkData { resolvable_link, resolvable_link_range, display_link }
+}
+
+fn offset_explicit_range(md: &str, link_range: Range<usize>, open: u8, close: u8) -> Range<usize> {
+    let mut open_brace = !0;
+    let mut close_brace = !0;
+    for (i, b) in md.as_bytes()[link_range.clone()].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            close_brace = i;
+            break;
+        }
+    }
+
+    if close_brace < link_range.start || close_brace >= link_range.end {
+        return link_range;
+    }
+
+    let mut nesting = 1;
+
+    for (i, b) in md.as_bytes()[link_range.start..close_brace].iter().copied().enumerate().rev() {
+        let i = i + link_range.start;
+        if b == close {
+            nesting += 1;
+        }
+        if b == open {
+            nesting -= 1;
+        }
+        if nesting == 0 {
+            open_brace = i;
+            break;
+        }
+    }
+
+    assert!(open_brace != close_brace);
+
+    if open_brace < link_range.start || open_brace >= link_range.end {
+        return link_range;
+    }
+    // do not actually include braces in the span
+    (open_brace + 1)..close_brace
+}
+
+fn offset_reference_def_range(
+    md: &str,
+    dest: &CowStr<'_>,
+    link_range: Range<usize>,
+) -> Range<usize> {
+    // For diagnostics, we want to underline the link's definition but `span` will point at
+    // where the link is used. This is a problem for reference-style links, where the definition
+    // is separate from the usage.
+
+    match dest {
+        // `Borrowed` variant means the string (the link's destination) may come directly from
+        // the markdown text and we can locate the original link destination.
+        // NOTE: LinkReplacer also provides `Borrowed` but possibly from other sources,
+        // so `locate()` can fall back to use `span`.
+        CowStr::Borrowed(s) => {
+            // FIXME: remove this function once pulldown_cmark can provide spans for link definitions.
+            unsafe {
+                let s_start = dest.as_ptr();
+                let s_end = s_start.add(s.len());
+                let md_start = md.as_ptr();
+                let md_end = md_start.add(md.len());
+                if md_start <= s_start && s_end <= md_end {
+                    let start = s_start.offset_from(md_start) as usize;
+                    let end = s_end.offset_from(md_start) as usize;
+                    start..end
+                } else {
+                    link_range
+                }
+            }
+        }
+
+        // For anything else, we can only use the provided range.
+        CowStr::Boxed(_) | CowStr::Inlined(_) => link_range,
+    }
+}
diff --git a/src/tools/cargo b/src/tools/cargo
-Subproject 7c3904d6c3ed54e8a413023519b55a536ad44d5
+Subproject 2cc50bc0b63ad20da193e002ba11d391af0104b
diff --git a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
index c634de960d1..7b00eabf97b 100644
--- a/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/clippy_lints/src/needless_pass_by_ref_mut.rs
@@ -5,14 +5,16 @@ use clippy_utils::{get_parent_node, inherits_cfg, is_from_proc_macro, is_self};
 use rustc_data_structures::fx::{FxHashSet, FxIndexMap};
 use rustc_errors::Applicability;
 use rustc_hir::intravisit::{walk_qpath, FnKind, Visitor};
-use rustc_hir::{Body, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath};
+use rustc_hir::{
+    Body, Closure, Expr, ExprKind, FnDecl, HirId, HirIdMap, HirIdSet, Impl, ItemKind, Mutability, Node, PatKind, QPath,
+};
 use rustc_hir_typeck::expr_use_visitor as euv;
 use rustc_infer::infer::TyCtxtInferExt;
 use rustc_lint::{LateContext, LateLintPass};
 use rustc_middle::hir::map::associated_body;
 use rustc_middle::hir::nested_filter::OnlyBodies;
 use rustc_middle::mir::FakeReadCause;
-use rustc_middle::ty::{self, Ty, UpvarId, UpvarPath};
+use rustc_middle::ty::{self, Ty, TyCtxt, UpvarId, UpvarPath};
 use rustc_session::{declare_tool_lint, impl_lint_pass};
 use rustc_span::def_id::LocalDefId;
 use rustc_span::symbol::kw;
@@ -147,22 +149,36 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
         // Collect variables mutably used and spans which will need dereferencings from the
         // function body.
         let MutablyUsedVariablesCtxt { mutably_used_vars, .. } = {
-            let mut ctx = MutablyUsedVariablesCtxt::default();
+            let mut ctx = MutablyUsedVariablesCtxt {
+                mutably_used_vars: HirIdSet::default(),
+                prev_bind: None,
+                prev_move_to_closure: HirIdSet::default(),
+                aliases: HirIdMap::default(),
+                async_closures: FxHashSet::default(),
+                tcx: cx.tcx,
+            };
             let infcx = cx.tcx.infer_ctxt().build();
             euv::ExprUseVisitor::new(&mut ctx, &infcx, fn_def_id, cx.param_env, cx.typeck_results()).consume_body(body);
             if is_async {
-                let closures = ctx.async_closures.clone();
-                let hir = cx.tcx.hir();
-                for closure in closures {
-                    ctx.prev_bind = None;
-                    ctx.prev_move_to_closure.clear();
-                    if let Some(body) = hir
-                        .find_by_def_id(closure)
-                        .and_then(associated_body)
-                        .map(|(_, body_id)| hir.body(body_id))
-                    {
-                        euv::ExprUseVisitor::new(&mut ctx, &infcx, closure, cx.param_env, cx.typeck_results())
-                            .consume_body(body);
+                let mut checked_closures = FxHashSet::default();
+                while !ctx.async_closures.is_empty() {
+                    let closures = ctx.async_closures.clone();
+                    ctx.async_closures.clear();
+                    let hir = cx.tcx.hir();
+                    for closure in closures {
+                        if !checked_closures.insert(closure) {
+                            continue;
+                        }
+                        ctx.prev_bind = None;
+                        ctx.prev_move_to_closure.clear();
+                        if let Some(body) = hir
+                            .find_by_def_id(closure)
+                            .and_then(associated_body)
+                            .map(|(_, body_id)| hir.body(body_id))
+                        {
+                            euv::ExprUseVisitor::new(&mut ctx, &infcx, closure, cx.param_env, cx.typeck_results())
+                                .consume_body(body);
+                        }
                     }
                 }
             }
@@ -225,16 +241,16 @@ impl<'tcx> LateLintPass<'tcx> for NeedlessPassByRefMut<'tcx> {
     }
 }
 
-#[derive(Default)]
-struct MutablyUsedVariablesCtxt {
+struct MutablyUsedVariablesCtxt<'tcx> {
     mutably_used_vars: HirIdSet,
     prev_bind: Option<HirId>,
     prev_move_to_closure: HirIdSet,
     aliases: HirIdMap<HirId>,
     async_closures: FxHashSet<LocalDefId>,
+    tcx: TyCtxt<'tcx>,
 }
 
-impl MutablyUsedVariablesCtxt {
+impl<'tcx> MutablyUsedVariablesCtxt<'tcx> {
     fn add_mutably_used_var(&mut self, mut used_id: HirId) {
         while let Some(id) = self.aliases.get(&used_id) {
             self.mutably_used_vars.insert(used_id);
@@ -242,9 +258,27 @@ impl MutablyUsedVariablesCtxt {
         }
         self.mutably_used_vars.insert(used_id);
     }
+
+    fn would_be_alias_cycle(&self, alias: HirId, mut target: HirId) -> bool {
+        while let Some(id) = self.aliases.get(&target) {
+            if *id == alias {
+                return true;
+            }
+            target = *id;
+        }
+        false
+    }
+
+    fn add_alias(&mut self, alias: HirId, target: HirId) {
+        // This is to prevent alias loop.
+        if alias == target || self.would_be_alias_cycle(alias, target) {
+            return;
+        }
+        self.aliases.insert(alias, target);
+    }
 }
 
-impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
+impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt<'tcx> {
     fn consume(&mut self, cmt: &euv::PlaceWithHirId<'tcx>, _id: HirId) {
         if let euv::Place {
             base:
@@ -259,7 +293,7 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
         {
             if let Some(bind_id) = self.prev_bind.take() {
                 if bind_id != *vid {
-                    self.aliases.insert(bind_id, *vid);
+                    self.add_alias(bind_id, *vid);
                 }
             } else if !self.prev_move_to_closure.contains(vid)
                 && matches!(base_ty.ref_mutability(), Some(Mutability::Mut))
@@ -289,6 +323,25 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
             {
                 self.add_mutably_used_var(*vid);
             }
+        } else if borrow == ty::ImmBorrow {
+            // If there is an `async block`, it'll contain a call to a closure which we need to
+            // go into to ensure all "mutate" checks are found.
+            if let Node::Expr(Expr {
+                kind:
+                    ExprKind::Call(
+                        _,
+                        [
+                            Expr {
+                                kind: ExprKind::Closure(Closure { def_id, .. }),
+                                ..
+                            },
+                        ],
+                    ),
+                ..
+            }) = self.tcx.hir().get(cmt.hir_id)
+            {
+                self.async_closures.insert(*def_id);
+            }
         }
     }
 
@@ -296,7 +349,12 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
         self.prev_bind = None;
         if let euv::Place {
             projections,
-            base: euv::PlaceBase::Local(vid),
+            base:
+                euv::PlaceBase::Local(vid)
+                | euv::PlaceBase::Upvar(UpvarId {
+                    var_path: UpvarPath { hir_id: vid },
+                    ..
+                }),
             ..
         } = &cmt.place
         {
@@ -329,8 +387,9 @@ impl<'tcx> euv::Delegate<'tcx> for MutablyUsedVariablesCtxt {
                 // Seems like we are inside an async function. We need to store the closure `DefId`
                 // to go through it afterwards.
                 self.async_closures.insert(inner);
-                self.aliases.insert(cmt.hir_id, *vid);
+                self.add_alias(cmt.hir_id, *vid);
                 self.prev_move_to_closure.insert(*vid);
+                self.prev_bind = None;
             }
         }
     }
diff --git a/src/tools/clippy/clippy_lints/src/useless_conversion.rs b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
index bd4dc07a42b..5ac4f0aa46c 100644
--- a/src/tools/clippy/clippy_lints/src/useless_conversion.rs
+++ b/src/tools/clippy/clippy_lints/src/useless_conversion.rs
@@ -5,6 +5,7 @@ use clippy_utils::ty::{is_copy, is_type_diagnostic_item, same_type_and_consts};
 use clippy_utils::{get_parent_expr, is_trait_method, is_ty_alias, match_def_path, path_to_local, paths};
 use if_chain::if_chain;
 use rustc_errors::Applicability;
+use rustc_hir::def::DefKind;
 use rustc_hir::def_id::DefId;
 use rustc_hir::{BindingAnnotation, Expr, ExprKind, HirId, MatchSource, Node, PatKind};
 use rustc_lint::{LateContext, LateLintPass};
@@ -39,6 +40,7 @@ declare_clippy_lint! {
 #[derive(Default)]
 pub struct UselessConversion {
     try_desugar_arm: Vec<HirId>,
+    expn_depth: u32,
 }
 
 impl_lint_pass!(UselessConversion => [USELESS_CONVERSION]);
@@ -105,6 +107,7 @@ fn into_iter_deep_call<'hir>(cx: &LateContext<'_>, mut expr: &'hir Expr<'hir>) -
 impl<'tcx> LateLintPass<'tcx> for UselessConversion {
     fn check_expr(&mut self, cx: &LateContext<'tcx>, e: &'tcx Expr<'_>) {
         if e.span.from_expansion() {
+            self.expn_depth += 1;
             return;
         }
 
@@ -150,9 +153,14 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                 {
                     if let Some(parent) = get_parent_expr(cx, e) {
                         let parent_fn = match parent.kind {
-                            ExprKind::Call(recv, args) if let ExprKind::Path(ref qpath) = recv.kind => {
-                                cx.qpath_res(qpath, recv.hir_id).opt_def_id()
-                                    .map(|did| (did, args, MethodOrFunction::Function))
+                            ExprKind::Call(recv, args)
+                                if let ExprKind::Path(ref qpath) = recv.kind
+                                    && let Some(did) = cx.qpath_res(qpath, recv.hir_id).opt_def_id()
+                                    // make sure that the path indeed points to a fn-like item, so that
+                                    // `fn_sig` does not ICE. (see #11065)
+                                    && cx.tcx.opt_def_kind(did).is_some_and(DefKind::is_fn_like) =>
+                            {
+                                    Some((did, args, MethodOrFunction::Function))
                             }
                             ExprKind::MethodCall(.., args, _) => {
                                 cx.typeck_results().type_dependent_def_id(parent.hir_id)
@@ -168,6 +176,7 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
                             && let Some(&into_iter_param) = sig.inputs().get(kind.param_pos(arg_pos))
                             && let ty::Param(param) = into_iter_param.kind()
                             && let Some(span) = into_iter_bound(cx, parent_fn_did, into_iter_did, param.index)
+                            && self.expn_depth == 0
                         {
                             // Get the "innermost" `.into_iter()` call, e.g. given this expression:
                             // `foo.into_iter().into_iter()`
@@ -303,5 +312,8 @@ impl<'tcx> LateLintPass<'tcx> for UselessConversion {
         if Some(&e.hir_id) == self.try_desugar_arm.last() {
             self.try_desugar_arm.pop();
         }
+        if e.span.from_expansion() {
+            self.expn_depth -= 1;
+        }
     }
 }
diff --git a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
index 139e31bc528..43523faa236 100644
--- a/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
+++ b/src/tools/clippy/clippy_utils/src/qualify_min_const_fn.rs
@@ -291,8 +291,8 @@ fn check_terminator<'tcx>(
         | TerminatorKind::FalseUnwind { .. }
         | TerminatorKind::Goto { .. }
         | TerminatorKind::Return
-        | TerminatorKind::Resume
-        | TerminatorKind::Terminate
+        | TerminatorKind::UnwindResume
+        | TerminatorKind::UnwindTerminate
         | TerminatorKind::Unreachable => Ok(()),
         TerminatorKind::Drop { place, .. } => {
             if !is_ty_const_destruct(tcx, place.ty(&body.local_decls, tcx).ty, body) {
diff --git a/src/tools/clippy/tests/ui/crashes/ice-11065.rs b/src/tools/clippy/tests/ui/crashes/ice-11065.rs
new file mode 100644
index 00000000000..f5cf6b1cd77
--- /dev/null
+++ b/src/tools/clippy/tests/ui/crashes/ice-11065.rs
@@ -0,0 +1,19 @@
+#![warn(clippy::useless_conversion)]
+
+use std::iter::FromIterator;
+use std::option::IntoIter as OptionIter;
+
+fn eq<T: Eq>(a: T, b: T) -> bool {
+    a == b
+}
+
+macro_rules! tests {
+    ($($expr:expr, $ty:ty, ($($test:expr),*);)+) => (pub fn main() {$({
+        const C: $ty = $expr;
+        assert!(eq(C($($test),*), $expr($($test),*)));
+    })+})
+}
+
+tests! {
+    FromIterator::from_iter, fn(OptionIter<i32>) -> Vec<i32>, (Some(5).into_iter());
+}
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
index ae7b018d0e2..ec87d447597 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.rs
@@ -196,6 +196,41 @@ mod foo {
     //~| NOTE: this is cfg-gated and may require further changes
 }
 
+// Should not warn.
+async fn inner_async(x: &mut i32, y: &mut u32) {
+    async {
+        *y += 1;
+        *x += 1;
+    }
+    .await;
+}
+
+async fn inner_async2(x: &mut i32, y: &mut u32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
+    async {
+        *x += 1;
+    }
+    .await;
+}
+
+async fn inner_async3(x: &mut i32, y: &mut u32) {
+    //~^ ERROR: this argument is a mutable reference, but not used mutably
+    async {
+        *y += 1;
+    }
+    .await;
+}
+
+// Should not warn.
+async fn async_vec(b: &mut Vec<bool>) {
+    b.append(&mut vec![]);
+}
+
+// Should not warn.
+async fn async_vec2(b: &mut Vec<bool>) {
+    b.push(true);
+}
+
 fn main() {
     let mut u = 0;
     let mut v = vec![0];
diff --git a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
index 0d426ce32f9..2e06e7252d9 100644
--- a/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
+++ b/src/tools/clippy/tests/ui/needless_pass_by_ref_mut.stderr
@@ -94,5 +94,17 @@ LL |     fn cfg_warn(s: &mut u32) {}
    |
    = note: this is cfg-gated and may require further changes
 
-error: aborting due to 15 previous errors
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:208:39
+   |
+LL | async fn inner_async2(x: &mut i32, y: &mut u32) {
+   |                                       ^^^^^^^^ help: consider changing to: `&u32`
+
+error: this argument is a mutable reference, but not used mutably
+  --> $DIR/needless_pass_by_ref_mut.rs:216:26
+   |
+LL | async fn inner_async3(x: &mut i32, y: &mut u32) {
+   |                          ^^^^^^^^ help: consider changing to: `&i32`
+
+error: aborting due to 17 previous errors
 
diff --git a/src/tools/clippy/tests/ui/useless_conversion.fixed b/src/tools/clippy/tests/ui/useless_conversion.fixed
index 5d2c5b11658..53d8a5a9ff1 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.fixed
+++ b/src/tools/clippy/tests/ui/useless_conversion.fixed
@@ -156,6 +156,20 @@ fn main() {
 }
 
 #[allow(dead_code)]
+fn issue11065_fp() {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    macro_rules! x {
+        ($e:expr) => {
+            takes_into_iter($e);
+            let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
+        };
+    }
+    x!(Some(5).into_iter());
+}
+
+#[allow(dead_code)]
 fn explicit_into_iter_fn_arg() {
     fn a<T>(_: T) {}
     fn b<T: IntoIterator<Item = i32>>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/useless_conversion.rs b/src/tools/clippy/tests/ui/useless_conversion.rs
index 03a3e3f95ba..51ba4987339 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.rs
+++ b/src/tools/clippy/tests/ui/useless_conversion.rs
@@ -156,6 +156,20 @@ fn main() {
 }
 
 #[allow(dead_code)]
+fn issue11065_fp() {
+    use std::option::IntoIter;
+    fn takes_into_iter(_: impl IntoIterator<Item = i32>) {}
+
+    macro_rules! x {
+        ($e:expr) => {
+            takes_into_iter($e);
+            let _: IntoIter<i32> = $e; // removing `.into_iter()` leads to a type error here
+        };
+    }
+    x!(Some(5).into_iter());
+}
+
+#[allow(dead_code)]
 fn explicit_into_iter_fn_arg() {
     fn a<T>(_: T) {}
     fn b<T: IntoIterator<Item = i32>>(_: T) {}
diff --git a/src/tools/clippy/tests/ui/useless_conversion.stderr b/src/tools/clippy/tests/ui/useless_conversion.stderr
index 4957f73a469..6f7dc01d2cd 100644
--- a/src/tools/clippy/tests/ui/useless_conversion.stderr
+++ b/src/tools/clippy/tests/ui/useless_conversion.stderr
@@ -119,61 +119,61 @@ LL |     let _ = vec![s4, s4, s4].into_iter().into_iter();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing `.into_iter()`: `vec![s4, s4, s4].into_iter()`
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:171:7
+  --> $DIR/useless_conversion.rs:185:7
    |
 LL |     b(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:172:7
+  --> $DIR/useless_conversion.rs:186:7
    |
 LL |     c(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:162:18
+  --> $DIR/useless_conversion.rs:176:18
    |
 LL |     fn c(_: impl IntoIterator<Item = i32>) {}
    |                  ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:173:7
+  --> $DIR/useless_conversion.rs:187:7
    |
 LL |     d(vec![1, 2].into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:165:12
+  --> $DIR/useless_conversion.rs:179:12
    |
 LL |         T: IntoIterator<Item = i32>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:176:7
+  --> $DIR/useless_conversion.rs:190:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: explicit call to `.into_iter()` in function argument accepting `IntoIterator`
-  --> $DIR/useless_conversion.rs:177:7
+  --> $DIR/useless_conversion.rs:191:7
    |
 LL |     b(vec![1, 2].into_iter().into_iter().into_iter());
    |       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: consider removing the `.into_iter()`s: `vec![1, 2]`
    |
 note: this parameter accepts any `IntoIterator`, so you don't need to call `.into_iter()`
-  --> $DIR/useless_conversion.rs:161:13
+  --> $DIR/useless_conversion.rs:175:13
    |
 LL |     fn b<T: IntoIterator<Item = i32>>(_: T) {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/src/tools/miri/.github/workflows/ci.yml b/src/tools/miri/.github/workflows/ci.yml
index 8ced9fa86be..5e2abdde6ac 100644
--- a/src/tools/miri/.github/workflows/ci.yml
+++ b/src/tools/miri/.github/workflows/ci.yml
@@ -189,8 +189,6 @@ jobs:
           fetch-depth: 256 # get a bit more of the history
       - name: install josh-proxy
         run: cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
-      - name: start josh-proxy
-        run: josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background &
       - name: setup bot git name and email
         run: |
           git config --global user.name 'The Miri Conjob Bot'
diff --git a/src/tools/miri/CONTRIBUTING.md b/src/tools/miri/CONTRIBUTING.md
index b67e7103fd0..4e50b8fae81 100644
--- a/src/tools/miri/CONTRIBUTING.md
+++ b/src/tools/miri/CONTRIBUTING.md
@@ -165,16 +165,17 @@ to `.vscode/settings.json` in your local Miri clone:
 {
     "rust-analyzer.rustc.source": "discover",
     "rust-analyzer.linkedProjects": [
-        "./Cargo.toml",
-        "./cargo-miri/Cargo.toml"
+        "Cargo.toml",
+        "cargo-miri/Cargo.toml",
+        "miri-script/Cargo.toml",
     ],
-    "rust-analyzer.checkOnSave.overrideCommand": [
+    "rust-analyzer.check.overrideCommand": [
         "env",
         "MIRI_AUTO_OPS=no",
         "./miri",
         "cargo",
         "clippy", // make this `check` when working with a locally built rustc
-        "--message-format=json"
+        "--message-format=json",
     ],
     // Contrary to what the name suggests, this also affects proc macros.
     "rust-analyzer.cargo.buildScripts.overrideCommand": [
@@ -230,25 +231,16 @@ You can also directly run Miri on a Rust source file:
 ## Advanced topic: Syncing with the rustc repo
 
 We use the [`josh` proxy](https://github.com/josh-project/josh) to transmit changes between the
-rustc and Miri repositories.
+rustc and Miri repositories. You can install it as follows:
 
 ```sh
 cargo +stable install josh-proxy --git https://github.com/josh-project/josh --tag r22.12.06
-josh-proxy --local=$HOME/.cache/josh --remote=https://github.com --no-background
 ```
 
-This uses a directory `$HOME/.cache/josh` as a cache, to speed up repeated pulling/pushing.
-
-To make josh push via ssh instead of https, you can add the following to your `.gitconfig`:
-
-```toml
-[url "git@github.com:"]
-    pushInsteadOf = https://github.com/
-```
+Josh will automatically be started and stopped by `./miri`.
 
 ### Importing changes from the rustc repo
 
-Josh needs to be running, as described above.
 We assume we start on an up-to-date master branch in the Miri repo.
 
 ```sh
@@ -267,16 +259,14 @@ needed.
 
 ### Exporting changes to the rustc repo
 
-Keep in mind that pushing is the most complicated job that josh has to do --
-pulling just filters the rustc history, but pushing needs to construct a new
-rustc history that would filter to the given Miri history! To avoid problems, it
-is a good idea to always pull immediately before you push. In particular, you
-should never do two josh pushes without an intermediate pull; that can lead to
-duplicated commits.
+Keep in mind that pushing is the most complicated job that josh has to do -- pulling just filters
+the rustc history, but pushing needs to construct a new rustc history that would filter to the given
+Miri history! To avoid problems, it is a good idea to always pull immediately before you push. If
+you are getting strange errors, chances are you are running into [this josh
+bug](https://github.com/josh-project/josh/issues/998). In that case, please get in touch on Zulip.
 
-Josh needs to be running, as described above. We will use the josh proxy to push
-to your fork of rustc. Run the following in the Miri repo, assuming we are on an
-up-to-date master branch:
+We will use the josh proxy to push to your fork of rustc. Run the following in the Miri repo,
+assuming we are on an up-to-date master branch:
 
 ```sh
 # Push the Miri changes to your rustc fork (substitute your github handle for YOUR_NAME).
@@ -286,3 +276,11 @@ up-to-date master branch:
 This will create a new branch called 'miri' in your fork, and the output should
 include a link to create a rustc PR that will integrate those changes into the
 main repository.
+
+If this fails due to authentication problems, it can help to make josh push via ssh instead of
+https. Add the following to your `.gitconfig`:
+
+```toml
+[url "git@github.com:"]
+    pushInsteadOf = https://github.com/
+```
diff --git a/src/tools/miri/Cargo.lock b/src/tools/miri/Cargo.lock
index 4232d7fda78..ca5b6d22515 100644
--- a/src/tools/miri/Cargo.lock
+++ b/src/tools/miri/Cargo.lock
@@ -443,6 +443,7 @@ dependencies = [
  "rand",
  "regex",
  "rustc_version",
+ "serde",
  "smallvec",
  "ui_test",
 ]
@@ -528,18 +529,18 @@ checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
 dependencies = [
  "proc-macro2",
 ]
@@ -685,18 +686,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.162"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
+checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.162"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
+checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -737,9 +738,9 @@ checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/tools/miri/Cargo.toml b/src/tools/miri/Cargo.toml
index a625e1696e1..67a2aeefa02 100644
--- a/src/tools/miri/Cargo.toml
+++ b/src/tools/miri/Cargo.toml
@@ -41,6 +41,8 @@ rustc_version = "0.4"
 # Features chosen to match those required by env_logger, to avoid rebuilds
 regex = { version = "1.5.5", default-features = false, features = ["perf", "std"] }
 lazy_static = "1.4.0"
+# Require a version of serde without intransparent unreproducible binary blobs.
+serde = { version = "1.0.185", features = ["derive"] }
 
 [package.metadata.rust-analyzer]
 # This crate uses #[feature(rustc_private)].
diff --git a/src/tools/miri/README.md b/src/tools/miri/README.md
index 89d4b29ebb8..06fe668354a 100644
--- a/src/tools/miri/README.md
+++ b/src/tools/miri/README.md
@@ -53,7 +53,7 @@ behavior** in your program, and cannot run all programs:
   positives here, so if your program runs fine in Miri right now that is by no
   means a guarantee that it is UB-free when these questions get answered.
 
-    In particular, Miri does currently not check that references point to valid data.
+    In particular, Miri does not check that references point to valid data.
 * If the program relies on unspecified details of how data is laid out, it will
   still run fine in Miri -- but might break (including causing UB) on different
   compiler versions or different platforms.
@@ -458,8 +458,8 @@ Some native rustc `-Z` flags are also very relevant for Miri:
 Moreover, Miri recognizes some environment variables:
 
 * `MIRI_AUTO_OPS` indicates whether the automatic execution of rustfmt, clippy and toolchain setup
-  should be skipped. If it is set to any value, they are skipped. This is used for avoiding infinite
-  recursion in `./miri` and to allow automated IDE actions to avoid the auto ops.
+  should be skipped. If it is set to `no`, they are skipped. This is used to allow automated IDE
+  actions to avoid the auto ops.
 * `MIRI_LOG`, `MIRI_BACKTRACE` control logging and backtrace printing during
   Miri executions, also [see "Testing the Miri driver" in `CONTRIBUTING.md`][testing-miri].
 * `MIRIFLAGS` (recognized by `cargo miri` and the test suite) defines extra
diff --git a/src/tools/miri/cargo-miri/Cargo.lock b/src/tools/miri/cargo-miri/Cargo.lock
index 47fdc65fa96..1f3a33270e1 100644
--- a/src/tools/miri/cargo-miri/Cargo.lock
+++ b/src/tools/miri/cargo-miri/Cargo.lock
@@ -178,18 +178,18 @@ checksum = "ece97ea872ece730aed82664c424eb4c8291e1ff2480247ccf7409044bc6479f"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.26"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "4424af4bf778aae2051a77b60283332f386554255d722233d09fbfc7e30da2fc"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
 dependencies = [
  "proc-macro2",
 ]
@@ -280,18 +280,18 @@ dependencies = [
 
 [[package]]
 name = "serde"
-version = "1.0.162"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "71b2f6e1ab5c2b98c05f0f35b236b22e8df7ead6ffbf51d7808da7f8817e7ab6"
+checksum = "be9b6f69f1dfd54c3b568ffa45c310d6973a5e5148fd40cf515acaf38cf5bc31"
 dependencies = [
  "serde_derive",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.162"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a2a0814352fd64b58489904a44ea8d90cb1a91dcb6b4f5ebabc32c8318e93cb6"
+checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -311,9 +311,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "2.0.15"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a34fcf3e8b60f57e6a14301a2e916d323af98b0ea63c599441eec8558660c822"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/tools/miri/cargo-miri/Cargo.toml b/src/tools/miri/cargo-miri/Cargo.toml
index cfa5ac5281d..e118d12897a 100644
--- a/src/tools/miri/cargo-miri/Cargo.toml
+++ b/src/tools/miri/cargo-miri/Cargo.toml
@@ -22,7 +22,8 @@ rustc-build-sysroot = "0.4.1"
 
 # Enable some feature flags that dev-dependencies need but dependencies
 # do not.  This makes `./miri install` after `./miri build` faster.
-serde = { version = "*", features = ["derive"] }
+# Require a version of serde without intransparent unreproducible binary blobs.
+serde = { version = "1.0.185", features = ["derive"] }
 
 [build-dependencies]
 rustc_tools_util = "0.3"
diff --git a/src/tools/miri/ci.sh b/src/tools/miri/ci.sh
index a8aae524e71..3146ef41a3b 100755
--- a/src/tools/miri/ci.sh
+++ b/src/tools/miri/ci.sh
@@ -52,7 +52,7 @@ function run_tests {
 
     # Also run some many-seeds tests. 64 seeds means this takes around a minute per test.
     for FILE in tests/many-seeds/*.rs; do
-      MIRI_SEEDS=64 CARGO_EXTRA_FLAGS="$CARGO_EXTRA_FLAGS -q" ./miri many-seeds ./miri run "$FILE"
+      MIRI_SEEDS=64 ./miri many-seeds ./miri run "$FILE"
     done
 
     # Check that the benchmarks build and run, but without actually benchmarking.
diff --git a/src/tools/miri/miri b/src/tools/miri/miri
index c816a4bb06b..938df9799da 100755
--- a/src/tools/miri/miri
+++ b/src/tools/miri/miri
@@ -2,5 +2,5 @@
 set -e
 # Instead of doing just `cargo run --manifest-path .. $@`, we invoke miri-script binary directly. Invoking `cargo run` goes through
 # rustup (that sets it's own environmental variables), which is undesirable.
-cargo build -q --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml
+cargo build $CARGO_EXTRA_FLAGS -q --manifest-path "$(dirname "$0")"/miri-script/Cargo.toml
 "$(dirname "$0")"/miri-script/target/debug/miri-script "$@"
diff --git a/src/tools/miri/miri-script/Cargo.lock b/src/tools/miri/miri-script/Cargo.lock
index cf6062d7d7f..1a22596b774 100644
--- a/src/tools/miri/miri-script/Cargo.lock
+++ b/src/tools/miri/miri-script/Cargo.lock
@@ -9,6 +9,38 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "9c7d0618f0e0b7e8ff11427422b64564d5fb0be1940354bfe2e0529b18a9d9b8"
 
 [[package]]
+name = "bitflags"
+version = "1.3.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bef38d45163c2f1dde094a7dfd33ccf595c92905c8f8f4fdc18d06fb1037718a"
+
+[[package]]
+name = "cfg-if"
+version = "1.0.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
+
+[[package]]
+name = "directories"
+version = "4.0.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "f51c5d4ddabd36886dd3e1438cb358cdcb0d7c499cb99cb4ac2e38e18b5cb210"
+dependencies = [
+ "dirs-sys",
+]
+
+[[package]]
+name = "dirs-sys"
+version = "0.3.7"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6"
+dependencies = [
+ "libc",
+ "redox_users",
+ "winapi",
+]
+
+[[package]]
 name = "dunce"
 version = "1.0.4"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -21,6 +53,17 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "7fcaabb2fef8c910e7f4c7ce9f67a1283a1715879a7c230ca9d6d1ae31f16d91"
 
 [[package]]
+name = "getrandom"
+version = "0.2.10"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "be4136b2a15dd319360be1c07d9933517ccf0be8f16bf62a3bee4f0d618df427"
+dependencies = [
+ "cfg-if",
+ "libc",
+ "wasi",
+]
+
+[[package]]
 name = "itertools"
 version = "0.10.5"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -40,6 +83,7 @@ name = "miri-script"
 version = "0.1.0"
 dependencies = [
  "anyhow",
+ "directories",
  "dunce",
  "itertools",
  "path_macro",
@@ -63,6 +107,44 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "a6e819bbd49d5939f682638fa54826bf1650abddcd65d000923de8ad63cc7d15"
 
 [[package]]
+name = "proc-macro2"
+version = "1.0.66"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
+dependencies = [
+ "unicode-ident",
+]
+
+[[package]]
+name = "quote"
+version = "1.0.33"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
+dependencies = [
+ "proc-macro2",
+]
+
+[[package]]
+name = "redox_syscall"
+version = "0.2.16"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "fb5a58c1855b4b6819d59012155603f0b22ad30cad752600aadfcb695265519a"
+dependencies = [
+ "bitflags",
+]
+
+[[package]]
+name = "redox_users"
+version = "0.4.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "b033d837a7cf162d7993aded9304e30a83213c648b6e389db233191f891e5c2b"
+dependencies = [
+ "getrandom",
+ "redox_syscall",
+ "thiserror",
+]
+
+[[package]]
 name = "rustc_version"
 version = "0.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -93,6 +175,43 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde"
 
 [[package]]
+name = "syn"
+version = "2.0.29"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "unicode-ident",
+]
+
+[[package]]
+name = "thiserror"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "97a802ec30afc17eee47b2855fc72e0c4cd62be9b4efe6591edde0ec5bd68d8f"
+dependencies = [
+ "thiserror-impl",
+]
+
+[[package]]
+name = "thiserror-impl"
+version = "1.0.47"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "6bb623b56e39ab7dcd4b1b98bb6c8f8d907ed255b18de254088016b27a8ee19b"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn",
+]
+
+[[package]]
+name = "unicode-ident"
+version = "1.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "301abaae475aa91687eb82514b328ab47a211a533026cb25fc3e519b86adfc3c"
+
+[[package]]
 name = "walkdir"
 version = "2.3.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -103,6 +222,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "wasi"
+version = "0.11.0+wasi-snapshot-preview1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423"
+
+[[package]]
 name = "which"
 version = "4.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/tools/miri/miri-script/Cargo.toml b/src/tools/miri/miri-script/Cargo.toml
index c0414a2fe37..d805a94c8f5 100644
--- a/src/tools/miri/miri-script/Cargo.toml
+++ b/src/tools/miri/miri-script/Cargo.toml
@@ -20,3 +20,4 @@ anyhow = "1.0"
 xshell = "0.2"
 rustc_version = "0.4"
 dunce = "1.0.4"
+directories = "4"
diff --git a/src/tools/miri/miri-script/src/commands.rs b/src/tools/miri/miri-script/src/commands.rs
index ed78f80c023..2948219ad89 100644
--- a/src/tools/miri/miri-script/src/commands.rs
+++ b/src/tools/miri/miri-script/src/commands.rs
@@ -2,6 +2,9 @@ use std::env;
 use std::ffi::OsString;
 use std::io::Write;
 use std::ops::Not;
+use std::process;
+use std::thread;
+use std::time;
 
 use anyhow::{anyhow, bail, Context, Result};
 use path_macro::path;
@@ -14,6 +17,7 @@ use crate::Command;
 /// Used for rustc syncs.
 const JOSH_FILTER: &str =
     ":rev(75dd959a3a40eb5b4574f8d2e23aa6efbeb33573:prefix=src/tools/miri):/src/tools/miri";
+const JOSH_PORT: &str = "42042";
 
 impl MiriEnv {
     fn build_miri_sysroot(&mut self, quiet: bool) -> Result<()> {
@@ -57,6 +61,10 @@ impl MiriEnv {
 
 impl Command {
     fn auto_actions() -> Result<()> {
+        if env::var_os("MIRI_AUTO_OPS").is_some_and(|x| x == "no") {
+            return Ok(());
+        }
+
         let miri_dir = miri_dir()?;
         let auto_everything = path!(miri_dir / ".auto-everything").exists();
         let auto_toolchain = auto_everything || path!(miri_dir / ".auto-toolchain").exists();
@@ -77,7 +85,57 @@ impl Command {
         Ok(())
     }
 
+    fn start_josh() -> Result<impl Drop> {
+        // Determine cache directory.
+        let local_dir = {
+            let user_dirs =
+                directories::ProjectDirs::from("org", "rust-lang", "miri-josh").unwrap();
+            user_dirs.cache_dir().to_owned()
+        };
+
+        // Start josh, silencing its output.
+        let mut cmd = process::Command::new("josh-proxy");
+        cmd.arg("--local").arg(local_dir);
+        cmd.arg("--remote").arg("https://github.com");
+        cmd.arg("--port").arg(JOSH_PORT);
+        cmd.arg("--no-background");
+        cmd.stdout(process::Stdio::null());
+        cmd.stderr(process::Stdio::null());
+        let josh = cmd.spawn().context("failed to start josh-proxy, make sure it is installed")?;
+        // Give it some time so hopefully the port is open. (10ms was not enough.)
+        thread::sleep(time::Duration::from_millis(100));
+
+        // Create a wrapper that stops it on drop.
+        struct Josh(process::Child);
+        impl Drop for Josh {
+            fn drop(&mut self) {
+                #[cfg(unix)]
+                {
+                    // Try to gracefully shut it down.
+                    process::Command::new("kill")
+                        .args(["-s", "INT", &self.0.id().to_string()])
+                        .output()
+                        .expect("failed to SIGINT josh-proxy");
+                    // Sadly there is no "wait with timeout"... so we just give it some time to finish.
+                    thread::sleep(time::Duration::from_millis(100));
+                    // Now hopefully it is gone.
+                    if self.0.try_wait().expect("failed to wait for josh-proxy").is_some() {
+                        return;
+                    }
+                }
+                // If that didn't work (or we're not on Unix), kill it hard.
+                eprintln!(
+                    "I have to kill josh-proxy the hard way, let's hope this does not break anything."
+                );
+                self.0.kill().expect("failed to SIGKILL josh-proxy");
+            }
+        }
+
+        Ok(Josh(josh))
+    }
+
     pub fn exec(self) -> Result<()> {
+        // First, and crucially only once, run the auto-actions -- but not for all commands.
         match &self {
             Command::Install { .. }
             | Command::Build { .. }
@@ -89,10 +147,11 @@ impl Command {
             | Command::Cargo { .. } => Self::auto_actions()?,
             | Command::ManySeeds { .. }
             | Command::Toolchain { .. }
-            | Command::RustcPull { .. }
             | Command::Bench { .. }
+            | Command::RustcPull { .. }
             | Command::RustcPush { .. } => {}
         }
+        // Then run the actual command.
         match self {
             Command::Install { flags } => Self::install(flags),
             Command::Build { flags } => Self::build(flags),
@@ -168,6 +227,8 @@ impl Command {
         if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
             bail!("working directory must be clean before running `./miri rustc-pull`");
         }
+        // Make sure josh is running.
+        let josh = Self::start_josh()?;
 
         // Update rust-version file. As a separate commit, since making it part of
         // the merge has confused the heck out of josh in the past.
@@ -180,7 +241,7 @@ impl Command {
             .context("FAILED to commit rust-version file, something went wrong")?;
 
         // Fetch given rustc commit.
-        cmd!(sh, "git fetch http://localhost:8000/rust-lang/rust.git@{commit}{JOSH_FILTER}.git")
+        cmd!(sh, "git fetch http://localhost:{JOSH_PORT}/rust-lang/rust.git@{commit}{JOSH_FILTER}.git")
             .run()
             .map_err(|e| {
                 // Try to un-do the previous `git commit`, to leave the repo in the state we found it it.
@@ -196,6 +257,8 @@ impl Command {
         cmd!(sh, "git merge FETCH_HEAD --no-verify --no-ff -m {MERGE_COMMIT_MESSAGE}")
             .run()
             .context("FAILED to merge new commits, something went wrong")?;
+
+        drop(josh);
         Ok(())
     }
 
@@ -207,6 +270,8 @@ impl Command {
         if cmd!(sh, "git status --untracked-files=no --porcelain").read()?.is_empty().not() {
             bail!("working directory must be clean before running `./miri rustc-push`");
         }
+        // Make sure josh is running.
+        let josh = Self::start_josh()?;
 
         // Find a repo we can do our preparation in.
         if let Ok(rustc_git) = env::var("RUSTC_GIT") {
@@ -243,6 +308,8 @@ impl Command {
         }
         cmd!(sh, "git fetch https://github.com/rust-lang/rust {base}").run()?;
         cmd!(sh, "git push https://github.com/{github_user}/rust {base}:refs/heads/{branch}")
+            .ignore_stdout()
+            .ignore_stderr() // silence the "create GitHub PR" message
             .run()?;
         println!();
 
@@ -251,7 +318,7 @@ impl Command {
         println!("Pushing miri changes...");
         cmd!(
             sh,
-            "git push http://localhost:8000/{github_user}/rust.git{JOSH_FILTER}.git HEAD:{branch}"
+            "git push http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git HEAD:{branch}"
         )
         .run()?;
         println!();
@@ -259,7 +326,7 @@ impl Command {
         // Do a round-trip check to make sure the push worked as expected.
         cmd!(
             sh,
-            "git fetch http://localhost:8000/{github_user}/rust.git{JOSH_FILTER}.git {branch}"
+            "git fetch http://localhost:{JOSH_PORT}/{github_user}/rust.git{JOSH_FILTER}.git {branch}"
         )
         .ignore_stderr()
         .read()?;
@@ -272,6 +339,8 @@ impl Command {
             "Confirmed that the push round-trips back to Miri properly. Please create a rustc PR:"
         );
         println!("    https://github.com/{github_user}/rust/pull/new/{branch}");
+
+        drop(josh);
         Ok(())
     }
 
@@ -289,6 +358,7 @@ impl Command {
             bail!("expected many-seeds command to be non-empty");
         };
         let sh = Shell::new()?;
+        sh.set_var("MIRI_AUTO_OPS", "no"); // just in case we get recursively invoked
         for seed in seed_start..seed_end {
             println!("Trying seed: {seed}");
             let mut miriflags = env::var_os("MIRIFLAGS").unwrap_or_default();
@@ -313,6 +383,8 @@ impl Command {
         let Some((program_name, args)) = hyperfine.split_first() else {
             bail!("expected HYPERFINE environment variable to be non-empty");
         };
+        // Extra flags to pass to cargo.
+        let cargo_extra_flags = std::env::var("CARGO_EXTRA_FLAGS").unwrap_or_default();
         // Make sure we have an up-to-date Miri installed and selected the right toolchain.
         Self::install(vec![])?;
 
@@ -335,7 +407,7 @@ impl Command {
             // That seems to make Windows CI happy.
             cmd!(
                 sh,
-                "{program_name} {args...} 'cargo miri run --manifest-path \"'{current_bench}'\"'"
+                "{program_name} {args...} 'cargo miri run '{cargo_extra_flags}' --manifest-path \"'{current_bench}'\"'"
             )
             .run()?;
         }
diff --git a/src/tools/miri/miri-script/src/main.rs b/src/tools/miri/miri-script/src/main.rs
index 849a9168028..41b82cfc472 100644
--- a/src/tools/miri/miri-script/src/main.rs
+++ b/src/tools/miri/miri-script/src/main.rs
@@ -1,3 +1,5 @@
+#![allow(clippy::needless_question_mark)]
+
 mod commands;
 mod util;
 
diff --git a/src/tools/miri/rust-version b/src/tools/miri/rust-version
index 22a3d439861..d96e7040aaf 100644
--- a/src/tools/miri/rust-version
+++ b/src/tools/miri/rust-version
@@ -1 +1 @@
-9fa6bdd764a1f7bdf69eccceeace6d13f38cb2e1
+c40cfcf0494ff7506e753e750adb00eeea839f9c
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
index 0ce29ac5437..dab216bc5b1 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/perms.rs
@@ -68,17 +68,31 @@ mod transition {
     fn foreign_read(state: PermissionPriv, protected: bool) -> Option<PermissionPriv> {
         use Option::*;
         Some(match state {
+            // Non-writeable states just ignore foreign reads.
+            non_writeable @ (Frozen | Disabled) => non_writeable,
+            // Writeable states are more tricky, and depend on whether things are protected.
             // The inner data `ty_is_freeze` of `Reserved` is always irrelevant for Read
             // accesses, since the data is not being mutated. Hence the `{ .. }`
-            res @ Reserved { .. } if !protected => res,
-            Reserved { .. } => Frozen, // protected reserved
+            res @ Reserved { .. } =>
+                if protected {
+                    // Someone else read, make sure we won't write.
+                    // We could make this `Disabled` but it doesn't look like we get anything out of that extra UB.
+                    Frozen
+                } else {
+                    // Before activation and without protectors, foreign reads are fine.
+                    // That's the entire point of 2-phase borrows.
+                    res
+                },
             Active =>
                 if protected {
+                    // We wrote, someone else reads -- that's bad.
+                    // (If this is initialized, this move-to-protected will mean insta-UB.)
                     Disabled
                 } else {
+                    // We don't want to disable here to allow read-read reordering: it is crucial
+                    // that the foreign read does not invalidate future reads through this tag.
                     Frozen
                 },
-            non_writeable @ (Frozen | Disabled) => non_writeable,
         })
     }
 
diff --git a/src/tools/miri/src/diagnostics.rs b/src/tools/miri/src/diagnostics.rs
index 6bd4be91e51..f3285ccf917 100644
--- a/src/tools/miri/src/diagnostics.rs
+++ b/src/tools/miri/src/diagnostics.rs
@@ -304,11 +304,21 @@ pub fn report_error<'tcx, 'mir>(
                     (None, format!("this usually indicates that your program performed an invalid operation and caused Undefined Behavior")),
                     (None, format!("but due to `-Zmiri-symbolic-alignment-check`, alignment errors can also be false positives")),
                 ],
-            UndefinedBehavior(_) =>
-                vec![
+            UndefinedBehavior(info) => {
+                let mut helps = vec![
                     (None, format!("this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior")),
                     (None, format!("see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information")),
-                ],
+                ];
+                if let UndefinedBehaviorInfo::PointerUseAfterFree(alloc_id, _) | UndefinedBehaviorInfo::PointerOutOfBounds { alloc_id, .. } = info {
+                    if let Some(span) = ecx.machine.allocated_span(*alloc_id) {
+                        helps.push((Some(span), format!("{:?} was allocated here:", alloc_id)));
+                    }
+                    if let Some(span) = ecx.machine.deallocated_span(*alloc_id) {
+                        helps.push((Some(span), format!("{:?} was deallocated here:", alloc_id)));
+                    }
+                }
+                helps
+            }
             InvalidProgram(
                 InvalidProgramInfo::AlreadyReported(_)
             ) => {
diff --git a/src/tools/miri/src/helpers.rs b/src/tools/miri/src/helpers.rs
index ea1931f7a18..b5cc5c7e486 100644
--- a/src/tools/miri/src/helpers.rs
+++ b/src/tools/miri/src/helpers.rs
@@ -13,11 +13,11 @@ use rustc_index::IndexVec;
 use rustc_middle::mir;
 use rustc_middle::ty::{
     self,
-    layout::{LayoutOf, TyAndLayout},
-    List, TyCtxt,
+    layout::{IntegerExt as _, LayoutOf, TyAndLayout},
+    List, Ty, TyCtxt,
 };
 use rustc_span::{def_id::CrateNum, sym, Span, Symbol};
-use rustc_target::abi::{Align, FieldIdx, FieldsShape, Size, Variants};
+use rustc_target::abi::{Align, FieldIdx, FieldsShape, Integer, Size, Variants};
 use rustc_target::spec::abi::Abi;
 
 use rand::RngCore;
@@ -1011,6 +1011,65 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             None => tcx.item_name(def_id),
         }
     }
+
+    /// Converts `f` to integer type `dest_ty` after rounding with mode `round`.
+    /// Returns `None` if `f` is NaN or out of range.
+    fn float_to_int_checked<F>(
+        &self,
+        f: F,
+        dest_ty: Ty<'tcx>,
+        round: rustc_apfloat::Round,
+    ) -> Option<Scalar<Provenance>>
+    where
+        F: rustc_apfloat::Float + Into<Scalar<Provenance>>,
+    {
+        let this = self.eval_context_ref();
+
+        match dest_ty.kind() {
+            // Unsigned
+            ty::Uint(t) => {
+                let size = Integer::from_uint_ty(this, *t).size();
+                let res = f.to_u128_r(size.bits_usize(), round, &mut false);
+                if res.status.intersects(
+                    rustc_apfloat::Status::INVALID_OP
+                        | rustc_apfloat::Status::OVERFLOW
+                        | rustc_apfloat::Status::UNDERFLOW,
+                ) {
+                    // Floating point value is NaN (flagged with INVALID_OP) or outside the range
+                    // of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
+                    None
+                } else {
+                    // Floating point value can be represented by the integer type after rounding.
+                    // The INEXACT flag is ignored on purpose to allow rounding.
+                    Some(Scalar::from_uint(res.value, size))
+                }
+            }
+            // Signed
+            ty::Int(t) => {
+                let size = Integer::from_int_ty(this, *t).size();
+                let res = f.to_i128_r(size.bits_usize(), round, &mut false);
+                if res.status.intersects(
+                    rustc_apfloat::Status::INVALID_OP
+                        | rustc_apfloat::Status::OVERFLOW
+                        | rustc_apfloat::Status::UNDERFLOW,
+                ) {
+                    // Floating point value is NaN (flagged with INVALID_OP) or outside the range
+                    // of values of the integer type (flagged with OVERFLOW or UNDERFLOW).
+                    None
+                } else {
+                    // Floating point value can be represented by the integer type after rounding.
+                    // The INEXACT flag is ignored on purpose to allow rounding.
+                    Some(Scalar::from_int(res.value, size))
+                }
+            }
+            // Nothing else
+            _ =>
+                span_bug!(
+                    this.cur_span(),
+                    "attempted float-to-int conversion with non-int output type {dest_ty:?}"
+                ),
+        }
+    }
 }
 
 impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index d57da574315..03dd9037808 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -32,6 +32,7 @@
     clippy::needless_return,
     clippy::bool_to_int_with_if,
     clippy::box_default,
+    clippy::needless_question_mark,
     // We are not implementing queries here so it's fine
     rustc::potential_query_instability
 )]
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index e19be417b22..550c9650fb3 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -25,7 +25,7 @@ use rustc_middle::{
     },
 };
 use rustc_span::def_id::{CrateNum, DefId};
-use rustc_span::Symbol;
+use rustc_span::{Span, SpanData, Symbol};
 use rustc_target::abi::{Align, Size};
 use rustc_target::spec::abi::Abi;
 
@@ -135,6 +135,19 @@ impl MayLeak for MiriMemoryKind {
     }
 }
 
+impl MiriMemoryKind {
+    /// Whether we have a useful allocation span for an allocation of this kind.
+    fn should_save_allocation_span(self) -> bool {
+        use self::MiriMemoryKind::*;
+        match self {
+            // Heap allocations are fine since the `Allocation` is created immediately.
+            Rust | Miri | C | WinHeap | Mmap => true,
+            // Everything else is unclear, let's not show potentially confusing spans.
+            Machine | Global | ExternStatic | Tls | Runtime => false,
+        }
+    }
+}
+
 impl fmt::Display for MiriMemoryKind {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         use self::MiriMemoryKind::*;
@@ -497,6 +510,10 @@ pub struct MiriMachine<'mir, 'tcx> {
 
     /// Whether to collect a backtrace when each allocation is created, just in case it leaks.
     pub(crate) collect_leak_backtraces: bool,
+
+    /// The spans we will use to report where an allocation was created and deallocated in
+    /// diagnostics.
+    pub(crate) allocation_spans: RefCell<FxHashMap<AllocId, (Span, Option<Span>)>>,
 }
 
 impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
@@ -621,6 +638,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             stack_addr,
             stack_size,
             collect_leak_backtraces: config.collect_leak_backtraces,
+            allocation_spans: RefCell::new(FxHashMap::default()),
         }
     }
 
@@ -742,6 +760,21 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
     pub(crate) fn page_align(&self) -> Align {
         Align::from_bytes(self.page_size).unwrap()
     }
+
+    pub(crate) fn allocated_span(&self, alloc_id: AllocId) -> Option<SpanData> {
+        self.allocation_spans
+            .borrow()
+            .get(&alloc_id)
+            .map(|(allocated, _deallocated)| allocated.data())
+    }
+
+    pub(crate) fn deallocated_span(&self, alloc_id: AllocId) -> Option<SpanData> {
+        self.allocation_spans
+            .borrow()
+            .get(&alloc_id)
+            .and_then(|(_allocated, deallocated)| *deallocated)
+            .map(Span::data)
+    }
 }
 
 impl VisitTags for MiriMachine<'_, '_> {
@@ -791,6 +824,7 @@ impl VisitTags for MiriMachine<'_, '_> {
             stack_addr: _,
             stack_size: _,
             collect_leak_backtraces: _,
+            allocation_spans: _,
         } = self;
 
         threads.visit_tags(visit);
@@ -937,9 +971,22 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx.assert_panic(msg, unwind)
     }
 
-    #[inline(always)]
-    fn abort(_ecx: &mut MiriInterpCx<'mir, 'tcx>, msg: String) -> InterpResult<'tcx, !> {
-        throw_machine_stop!(TerminationInfo::Abort(msg))
+    fn panic_nounwind(ecx: &mut InterpCx<'mir, 'tcx, Self>, msg: &str) -> InterpResult<'tcx> {
+        ecx.start_panic_nounwind(msg)
+    }
+
+    fn unwind_terminate(ecx: &mut InterpCx<'mir, 'tcx, Self>) -> InterpResult<'tcx> {
+        // Call the lang item.
+        let panic = ecx.tcx.lang_items().panic_cannot_unwind().unwrap();
+        let panic = ty::Instance::mono(ecx.tcx.tcx, panic);
+        ecx.call_function(
+            panic,
+            Abi::Rust,
+            &[],
+            None,
+            StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
+        )?;
+        Ok(())
     }
 
     #[inline(always)]
@@ -1051,6 +1098,14 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             },
             |ptr| ecx.global_base_pointer(ptr),
         )?;
+
+        if matches!(kind, MemoryKind::Machine(kind) if kind.should_save_allocation_span()) {
+            ecx.machine
+                .allocation_spans
+                .borrow_mut()
+                .insert(id, (ecx.machine.current_span(), None));
+        }
+
         Ok(Cow::Owned(alloc))
     }
 
@@ -1181,6 +1236,10 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         if let Some(borrow_tracker) = &mut alloc_extra.borrow_tracker {
             borrow_tracker.before_memory_deallocation(alloc_id, prove_extra, range, machine)?;
         }
+        if let Some((_, deallocated_at)) = machine.allocation_spans.borrow_mut().get_mut(&alloc_id)
+        {
+            *deallocated_at = Some(machine.current_span());
+        }
         Ok(())
     }
 
diff --git a/src/tools/miri/src/range_map.rs b/src/tools/miri/src/range_map.rs
index 146715ddda2..4a3670b76ac 100644
--- a/src/tools/miri/src/range_map.rs
+++ b/src/tools/miri/src/range_map.rs
@@ -27,35 +27,27 @@ impl<T> RangeMap<T> {
     #[inline(always)]
     pub fn new(size: Size, init: T) -> RangeMap<T> {
         let size = size.bytes();
-        let mut map = RangeMap { v: Vec::new() };
-        if size > 0 {
-            map.v.push(Elem { range: 0..size, data: init });
-        }
-        map
+        let v = if size > 0 { vec![Elem { range: 0..size, data: init }] } else { Vec::new() };
+        RangeMap { v }
     }
 
     /// Finds the index containing the given offset.
     fn find_offset(&self, offset: u64) -> usize {
-        // We do a binary search.
-        let mut left = 0usize; // inclusive
-        let mut right = self.v.len(); // exclusive
-        loop {
-            debug_assert!(left < right, "find_offset: offset {offset} is out-of-bounds");
-            let candidate = left.checked_add(right).unwrap() / 2;
-            let elem = &self.v[candidate];
-            if offset < elem.range.start {
-                // We are too far right (offset is further left).
-                debug_assert!(candidate < right); // we are making progress
-                right = candidate;
-            } else if offset >= elem.range.end {
-                // We are too far left (offset is further right).
-                debug_assert!(candidate >= left); // we are making progress
-                left = candidate + 1;
-            } else {
-                // This is it!
-                return candidate;
-            }
-        }
+        self.v
+            .binary_search_by(|elem| -> std::cmp::Ordering {
+                if offset < elem.range.start {
+                    // We are too far right (offset is further left).
+                    // (`Greater` means that `elem` is greater than the desired target.)
+                    std::cmp::Ordering::Greater
+                } else if offset >= elem.range.end {
+                    // We are too far left (offset is further right).
+                    std::cmp::Ordering::Less
+                } else {
+                    // This is it!
+                    std::cmp::Ordering::Equal
+                }
+            })
+            .unwrap()
     }
 
     /// Provides read-only iteration over everything in the given range. This does
diff --git a/src/tools/miri/src/shims/foreign_items.rs b/src/tools/miri/src/shims/foreign_items.rs
index 953677d3290..7996e72615f 100644
--- a/src/tools/miri/src/shims/foreign_items.rs
+++ b/src/tools/miri/src/shims/foreign_items.rs
@@ -690,6 +690,10 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let right = this.read_pointer(right)?;
                 let n = Size::from_bytes(this.read_target_usize(n)?);
 
+                // C requires that this must always be a valid pointer (C18 §7.1.4).
+                this.ptr_get_alloc_id(left)?;
+                this.ptr_get_alloc_id(right)?;
+
                 let result = {
                     let left_bytes = this.read_bytes_ptr_strip_provenance(left, n)?;
                     let right_bytes = this.read_bytes_ptr_strip_provenance(right, n)?;
@@ -714,6 +718,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
                 let val = val as u8;
 
+                // C requires that this must always be a valid pointer (C18 §7.1.4).
+                this.ptr_get_alloc_id(ptr)?;
+
                 if let Some(idx) = this
                     .read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
                     .iter()
@@ -738,6 +745,9 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 #[allow(clippy::cast_sign_loss, clippy::cast_possible_truncation)]
                 let val = val as u8;
 
+                // C requires that this must always be a valid pointer (C18 §7.1.4).
+                this.ptr_get_alloc_id(ptr)?;
+
                 let idx = this
                     .read_bytes_ptr_strip_provenance(ptr, Size::from_bytes(num))?
                     .iter()
@@ -752,6 +762,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "strlen" => {
                 let [ptr] = this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
                 let ptr = this.read_pointer(ptr)?;
+                // This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
                 let n = this.read_c_str(ptr)?.len();
                 this.write_scalar(
                     Scalar::from_target_usize(u64::try_from(n).unwrap(), this),
@@ -791,6 +802,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 // pointer provenance is preserved by this implementation of `strcpy`.
                 // That is probably overly cautious, but there also is no fundamental
                 // reason to have `strcpy` destroy pointer provenance.
+                // This reads at least 1 byte, so we are already enforcing that this is a valid pointer.
                 let n = this.read_c_str(ptr_src)?.len().checked_add(1).unwrap();
                 this.mem_copy(
                     ptr_src,
@@ -942,6 +954,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 this.write_scalar(Scalar::from_u64(res.to_bits()), dest)?;
             }
 
+            // LLVM intrinsics
             "llvm.prefetch" => {
                 let [p, rw, loc, ty] =
                     this.check_shim(abi, Abi::C { unwind: false }, link_name, args)?;
@@ -968,8 +981,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     throw_unsup_format!("unsupported `llvm.prefetch` type argument: {}", ty);
                 }
             }
-
-            // Architecture-specific shims
             "llvm.x86.addcarry.64" if this.tcx.sess.target.arch == "x86_64" => {
                 // Computes u8+u64+u64, returning tuple (u8,u64) comprising the output carry and truncated sum.
                 let [c_in, a, b] = this.check_shim(abi, Abi::Unadjusted, link_name, args)?;
diff --git a/src/tools/miri/src/shims/intrinsics/mod.rs b/src/tools/miri/src/shims/intrinsics/mod.rs
index c900ced19cd..8a84b4f51b7 100644
--- a/src/tools/miri/src/shims/intrinsics/mod.rs
+++ b/src/tools/miri/src/shims/intrinsics/mod.rs
@@ -6,12 +6,12 @@ use std::iter;
 use log::trace;
 
 use rustc_apfloat::{Float, Round};
-use rustc_middle::ty::layout::{IntegerExt, LayoutOf};
+use rustc_middle::ty::layout::LayoutOf;
 use rustc_middle::{
     mir,
-    ty::{self, FloatTy, Ty},
+    ty::{self, FloatTy},
 };
-use rustc_target::abi::{Integer, Size};
+use rustc_target::abi::Size;
 
 use crate::*;
 use atomic::EvalContextExt as _;
@@ -34,10 +34,20 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         if this.emulate_intrinsic(instance, args, dest, ret)? {
             return Ok(());
         }
-
-        // All remaining supported intrinsics have a return place.
         let intrinsic_name = this.tcx.item_name(instance.def_id());
         let intrinsic_name = intrinsic_name.as_str();
+
+        // Handle intrinsics without return place.
+        match intrinsic_name {
+            "abort" => {
+                throw_machine_stop!(TerminationInfo::Abort(
+                    "the program aborted execution".to_owned()
+                ))
+            }
+            _ => {}
+        }
+
+        // All remaining supported intrinsics have a return place.
         let ret = match ret {
             None => throw_unsup_format!("unimplemented (diverging) intrinsic: `{intrinsic_name}`"),
             Some(p) => p,
@@ -356,10 +366,28 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 let val = this.read_immediate(val)?;
 
                 let res = match val.layout.ty.kind() {
-                    ty::Float(FloatTy::F32) =>
-                        this.float_to_int_unchecked(val.to_scalar().to_f32()?, dest.layout.ty)?,
-                    ty::Float(FloatTy::F64) =>
-                        this.float_to_int_unchecked(val.to_scalar().to_f64()?, dest.layout.ty)?,
+                    ty::Float(FloatTy::F32) => {
+                        let f = val.to_scalar().to_f32()?;
+                        this
+                            .float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
+                            .ok_or_else(|| {
+                                err_ub_format!(
+                                    "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
+                                    dest.layout.ty
+                                )
+                            })?
+                    }
+                    ty::Float(FloatTy::F64) => {
+                        let f = val.to_scalar().to_f64()?;
+                        this
+                            .float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
+                            .ok_or_else(|| {
+                                err_ub_format!(
+                                    "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{:?}`",
+                                    dest.layout.ty
+                                )
+                            })?
+                    }
                     _ =>
                         span_bug!(
                             this.cur_span(),
@@ -375,7 +403,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             "breakpoint" => {
                 let [] = check_arg_count(args)?;
                 // normally this would raise a SIGTRAP, which aborts if no debugger is connected
-                throw_machine_stop!(TerminationInfo::Abort(format!("Trace/breakpoint trap")))
+                throw_machine_stop!(TerminationInfo::Abort(format!("trace/breakpoint trap")))
             }
 
             name => throw_unsup_format!("unimplemented intrinsic: `{name}`"),
@@ -383,57 +411,4 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         Ok(())
     }
-
-    fn float_to_int_unchecked<F>(
-        &self,
-        f: F,
-        dest_ty: Ty<'tcx>,
-    ) -> InterpResult<'tcx, Scalar<Provenance>>
-    where
-        F: Float + Into<Scalar<Provenance>>,
-    {
-        let this = self.eval_context_ref();
-
-        // Step 1: cut off the fractional part of `f`. The result of this is
-        // guaranteed to be precisely representable in IEEE floats.
-        let f = f.round_to_integral(Round::TowardZero).value;
-
-        // Step 2: Cast the truncated float to the target integer type and see if we lose any information in this step.
-        Ok(match dest_ty.kind() {
-            // Unsigned
-            ty::Uint(t) => {
-                let size = Integer::from_uint_ty(this, *t).size();
-                let res = f.to_u128(size.bits_usize());
-                if res.status.is_empty() {
-                    // No status flags means there was no further rounding or other loss of precision.
-                    Scalar::from_uint(res.value, size)
-                } else {
-                    // `f` was not representable in this integer type.
-                    throw_ub_format!(
-                        "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{dest_ty:?}`",
-                    );
-                }
-            }
-            // Signed
-            ty::Int(t) => {
-                let size = Integer::from_int_ty(this, *t).size();
-                let res = f.to_i128(size.bits_usize());
-                if res.status.is_empty() {
-                    // No status flags means there was no further rounding or other loss of precision.
-                    Scalar::from_int(res.value, size)
-                } else {
-                    // `f` was not representable in this integer type.
-                    throw_ub_format!(
-                        "`float_to_int_unchecked` intrinsic called on {f} which cannot be represented in target type `{dest_ty:?}`",
-                    );
-                }
-            }
-            // Nothing else
-            _ =>
-                span_bug!(
-                    this.cur_span(),
-                    "`float_to_int_unchecked` called with non-int output type {dest_ty:?}"
-                ),
-        })
-    }
 }
diff --git a/src/tools/miri/src/shims/intrinsics/simd.rs b/src/tools/miri/src/shims/intrinsics/simd.rs
index b6225713cd0..dd8c4a4f6ec 100644
--- a/src/tools/miri/src/shims/intrinsics/simd.rs
+++ b/src/tools/miri/src/shims/intrinsics/simd.rs
@@ -1,4 +1,4 @@
-use rustc_apfloat::Float;
+use rustc_apfloat::{Float, Round};
 use rustc_middle::ty::layout::{HasParamEnv, LayoutOf};
 use rustc_middle::{mir, ty, ty::FloatTy};
 use rustc_target::abi::{Endian, HasDataLayout, Size};
@@ -420,7 +420,6 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     }
                 }
             }
-            #[rustfmt::skip]
             "cast" | "as" | "cast_ptr" | "expose_addr" | "from_exposed_addr" => {
                 let [op] = check_arg_count(args)?;
                 let (op, op_len) = this.operand_to_simd(op)?;
@@ -440,7 +439,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
                     let val = match (op.layout.ty.kind(), dest.layout.ty.kind()) {
                         // Int-to-(int|float): always safe
-                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_)) if safe_cast || unsafe_cast =>
+                        (ty::Int(_) | ty::Uint(_), ty::Int(_) | ty::Uint(_) | ty::Float(_))
+                            if safe_cast || unsafe_cast =>
                             this.int_to_int_or_float(&op, dest.layout.ty)?,
                         // Float-to-float: always safe
                         (ty::Float(_), ty::Float(_)) if safe_cast || unsafe_cast =>
@@ -449,21 +449,36 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                         (ty::Float(_), ty::Int(_) | ty::Uint(_)) if safe_cast =>
                             this.float_to_float_or_int(&op, dest.layout.ty)?,
                         // Float-to-int in unchecked mode
-                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
-                            this.float_to_int_unchecked(op.to_scalar().to_f32()?, dest.layout.ty)?.into(),
-                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast =>
-                            this.float_to_int_unchecked(op.to_scalar().to_f64()?, dest.layout.ty)?.into(),
-                        // Ptr-to-ptr cast
-                        (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast => {
-                            this.ptr_to_ptr(&op, dest.layout.ty)?
-                        }
-                        // Ptr/Int casts
-                        (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast => {
-                            this.pointer_expose_address_cast(&op, dest.layout.ty)?
+                        (ty::Float(FloatTy::F32), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
+                            let f = op.to_scalar().to_f32()?;
+                            this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
+                                .ok_or_else(|| {
+                                    err_ub_format!(
+                                        "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
+                                        dest.layout.ty
+                                    )
+                                })?
+                                .into()
                         }
-                        (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast => {
-                            this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?
+                        (ty::Float(FloatTy::F64), ty::Int(_) | ty::Uint(_)) if unsafe_cast => {
+                            let f = op.to_scalar().to_f64()?;
+                            this.float_to_int_checked(f, dest.layout.ty, Round::TowardZero)
+                                .ok_or_else(|| {
+                                    err_ub_format!(
+                                        "`simd_cast` intrinsic called on {f} which cannot be represented in target type `{:?}`",
+                                        dest.layout.ty
+                                    )
+                                })?
+                                .into()
                         }
+                        // Ptr-to-ptr cast
+                        (ty::RawPtr(..), ty::RawPtr(..)) if ptr_cast =>
+                            this.ptr_to_ptr(&op, dest.layout.ty)?,
+                        // Ptr/Int casts
+                        (ty::RawPtr(..), ty::Int(_) | ty::Uint(_)) if expose_cast =>
+                            this.pointer_expose_address_cast(&op, dest.layout.ty)?,
+                        (ty::Int(_) | ty::Uint(_), ty::RawPtr(..)) if from_exposed_cast =>
+                            this.pointer_from_exposed_address_cast(&op, dest.layout.ty)?,
                         // Error otherwise
                         _ =>
                             throw_unsup_format!(
diff --git a/src/tools/miri/src/shims/panic.rs b/src/tools/miri/src/shims/panic.rs
index 7aefdfcb976..5c0f828e4e6 100644
--- a/src/tools/miri/src/shims/panic.rs
+++ b/src/tools/miri/src/shims/panic.rs
@@ -188,6 +188,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         )
     }
 
+    /// Start a non-unwinding panic in the interpreter with the given message as payload.
+    fn start_panic_nounwind(&mut self, msg: &str) -> InterpResult<'tcx> {
+        let this = self.eval_context_mut();
+
+        // First arg: message.
+        let msg = this.allocate_str(msg, MiriMemoryKind::Machine.into(), Mutability::Not)?;
+
+        // Call the lang item.
+        let panic = this.tcx.lang_items().panic_nounwind().unwrap();
+        let panic = ty::Instance::mono(this.tcx.tcx, panic);
+        this.call_function(
+            panic,
+            Abi::Rust,
+            &[msg.to_ref(this)],
+            None,
+            StackPopCleanup::Goto { ret: None, unwind: mir::UnwindAction::Unreachable },
+        )
+    }
+
     fn assert_panic(
         &mut self,
         msg: &mir::AssertMessage<'tcx>,
diff --git a/src/tools/miri/src/shims/x86/sse.rs b/src/tools/miri/src/shims/x86/sse.rs
index deae0875fb9..b18441bb408 100644
--- a/src/tools/miri/src/shims/x86/sse.rs
+++ b/src/tools/miri/src/shims/x86/sse.rs
@@ -195,24 +195,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     _ => unreachable!(),
                 };
 
-                let mut exact = false;
-                let cvt = op.to_i128_r(32, rnd, &mut exact);
-                let res = if cvt.status.intersects(
-                    rustc_apfloat::Status::INVALID_OP
-                        | rustc_apfloat::Status::OVERFLOW
-                        | rustc_apfloat::Status::UNDERFLOW,
-                ) {
-                    // Input is NaN (flagged with INVALID_OP) or does not fit
-                    // in an i32 (flagged with OVERFLOW or UNDERFLOW), fallback
-                    // to minimum acording to SSE semantics. The INEXACT flag
-                    // is ignored on purpose because rounding can happen during
-                    // float-to-int conversion.
-                    i32::MIN
-                } else {
-                    i32::try_from(cvt.value).unwrap()
-                };
+                let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| {
+                    // Fallback to minimum acording to SSE semantics.
+                    Scalar::from_i32(i32::MIN)
+                });
 
-                this.write_scalar(Scalar::from_i32(res), dest)?;
+                this.write_scalar(res, dest)?;
             }
             // Use to implement _mm_cvtss_si64 and _mm_cvttss_si64.
             // Converts the first component of `op` from f32 to i64.
@@ -232,24 +220,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                     _ => unreachable!(),
                 };
 
-                let mut exact = false;
-                let cvt = op.to_i128_r(64, rnd, &mut exact);
-                let res = if cvt.status.intersects(
-                    rustc_apfloat::Status::INVALID_OP
-                        | rustc_apfloat::Status::OVERFLOW
-                        | rustc_apfloat::Status::UNDERFLOW,
-                ) {
-                    // Input is NaN (flagged with INVALID_OP) or does not fit
-                    // in an i64 (flagged with OVERFLOW or UNDERFLOW), fallback
-                    // to minimum acording to SSE semantics. The INEXACT flag
-                    // is ignored on purpose because rounding can happen during
-                    // float-to-int conversion.
-                    i64::MIN
-                } else {
-                    i64::try_from(cvt.value).unwrap()
-                };
+                let res = this.float_to_int_checked(op, dest.layout.ty, rnd).unwrap_or_else(|| {
+                    // Fallback to minimum acording to SSE semantics.
+                    Scalar::from_i64(i64::MIN)
+                });
 
-                this.write_scalar(Scalar::from_i64(res), dest)?;
+                this.write_scalar(res, dest)?;
             }
             // Used to implement the _mm_cvtsi32_ss function.
             // Converts `right` from i32 to f32. Returns a SIMD vector with
diff --git a/src/tools/miri/test-cargo-miri/Cargo.lock b/src/tools/miri/test-cargo-miri/Cargo.lock
index cf5ec2aa883..d5e57a66a8d 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.lock
+++ b/src/tools/miri/test-cargo-miri/Cargo.lock
@@ -83,27 +83,27 @@ version = "0.1.0"
 
 [[package]]
 name = "proc-macro2"
-version = "1.0.60"
+version = "1.0.66"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dec2b086b7a862cf4de201096214fa870344cf922b2b30c167badb3af3195406"
+checksum = "18fb31db3f9bddb2ea821cde30a9f70117e3f119938b5ee630b7403aa6e2ead9"
 dependencies = [
  "unicode-ident",
 ]
 
 [[package]]
 name = "quote"
-version = "1.0.23"
+version = "1.0.33"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "8856d8364d252a14d474036ea1358d63c9e6965c8e5c1885c18f73d70bff9c7b"
+checksum = "5267fca4496028628a95160fc423a33e8b2e6af8a5302579e322e4b520293cae"
 dependencies = [
  "proc-macro2",
 ]
 
 [[package]]
 name = "serde_derive"
-version = "1.0.152"
+version = "1.0.185"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "af487d118eecd09402d70a5d72551860e788df87b464af30e5ea6a38c75c541e"
+checksum = "dc59dfdcbad1437773485e0367fea4b090a2e0a16d9ffc46af47764536a298ec"
 dependencies = [
  "proc-macro2",
  "quote",
@@ -119,9 +119,9 @@ dependencies = [
 
 [[package]]
 name = "syn"
-version = "1.0.107"
+version = "2.0.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "1f4064b5b16e03ae50984a5a8ed5d4f8803e6bc1fd170a3cda91a1be4b18e3f5"
+checksum = "c324c494eba9d92503e6f1ef2e6df781e78f6a7705a0202d9801b198807d518a"
 dependencies = [
  "proc-macro2",
  "quote",
diff --git a/src/tools/miri/test-cargo-miri/Cargo.toml b/src/tools/miri/test-cargo-miri/Cargo.toml
index 37c996de662..1688096fd9a 100644
--- a/src/tools/miri/test-cargo-miri/Cargo.toml
+++ b/src/tools/miri/test-cargo-miri/Cargo.toml
@@ -20,7 +20,8 @@ issue_rust_86261 = { path = "issue-rust-86261" }
 
 [dev-dependencies]
 byteorder_2 = { package = "byteorder", version = "0.5" } # to test dev-dependencies behave as expected, with renaming
-serde_derive = "1.0" # not actually used, but exercises some unique code path (`--extern` .so file)
+# Not actually used, but exercises some unique code path (`--extern` .so file).
+serde_derive = "1.0.185"
 
 [build-dependencies]
 autocfg = "1"
diff --git a/src/tools/miri/test-cargo-miri/run-test.py b/src/tools/miri/test-cargo-miri/run-test.py
index ca2f69fc8cf..db4341169ea 100755
--- a/src/tools/miri/test-cargo-miri/run-test.py
+++ b/src/tools/miri/test-cargo-miri/run-test.py
@@ -15,12 +15,14 @@ CGREEN  = '\33[32m'
 CBOLD   = '\33[1m'
 CEND    = '\33[0m'
 
+CARGO_EXTRA_FLAGS = os.environ.get("CARGO_EXTRA_FLAGS", "").split()
+
 def fail(msg):
     print("\nTEST FAIL: {}".format(msg))
     sys.exit(1)
 
 def cargo_miri(cmd, quiet = True):
-    args = ["cargo", "miri", cmd]
+    args = ["cargo", "miri", cmd] + CARGO_EXTRA_FLAGS
     if quiet:
         args += ["-q"]
     if 'MIRI_TEST_TARGET' in os.environ:
diff --git a/src/tools/miri/tests/compiletest.rs b/src/tools/miri/tests/compiletest.rs
index 8b97c8bb83c..78dd3df01ec 100644
--- a/src/tools/miri/tests/compiletest.rs
+++ b/src/tools/miri/tests/compiletest.rs
@@ -16,6 +16,11 @@ fn get_host() -> String {
         .host
 }
 
+pub fn flagsplit(flags: &str) -> Vec<String> {
+    // This code is taken from `RUSTFLAGS` handling in cargo.
+    flags.split(' ').map(str::trim).filter(|s| !s.is_empty()).map(str::to_string).collect()
+}
+
 // Build the shared object file for testing external C function calls.
 fn build_so_for_c_ffi_tests() -> PathBuf {
     let cc = option_env!("CC").unwrap_or("cc");
@@ -100,14 +105,16 @@ fn test_config(target: &str, path: &str, mode: Mode, with_dependencies: bool) ->
     if with_dependencies && use_std {
         config.dependencies_crate_manifest_path =
             Some(Path::new("test_dependencies").join("Cargo.toml"));
-        config.dependency_builder.args = vec![
-            "run".into(),
+        let mut builder_args = vec!["run".into()];
+        builder_args.extend(flagsplit(&env::var("CARGO_EXTRA_FLAGS").unwrap_or_default()));
+        builder_args.extend([
             "--manifest-path".into(),
             "cargo-miri/Cargo.toml".into(),
             "--".into(),
             "miri".into(),
             "run".into(), // There is no `cargo miri build` so we just use `cargo miri run`.
-        ];
+        ]);
+        config.dependency_builder.args = builder_args.into_iter().map(Into::into).collect();
     }
     config
 }
diff --git a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
index 23d145e7d30..48d63e59051 100644
--- a/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
+++ b/src/tools/miri/tests/fail/alloc/deallocate-twice.stderr
@@ -6,7 +6,17 @@ LL |     unsafe { __rust_dealloc(ptr, layout.size(), layout.align()) }
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/deallocate-twice.rs:LL:CC
+   |
+LL |         let x = alloc(Layout::from_size_align_unchecked(1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/deallocate-twice.rs:LL:CC
+   |
+LL |         dealloc(x, Layout::from_size_align_unchecked(1, 1));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `std::alloc::dealloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
 note: inside `main`
   --> $DIR/deallocate-twice.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr
index 7c7cec211b7..ff4cb399157 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr
+++ b/src/tools/miri/tests/fail/alloc/reallocate-change-alloc.stderr
@@ -6,7 +6,17 @@ LL |         let _z = *x;
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/reallocate-change-alloc.rs:LL:CC
+   |
+LL |         let x = alloc(Layout::from_size_align_unchecked(1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/reallocate-change-alloc.rs:LL:CC
+   |
+LL |         let _y = realloc(x, Layout::from_size_align_unchecked(1, 1), 1);
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/reallocate-change-alloc.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
index 9c222154716..52cc579c1e6 100644
--- a/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
+++ b/src/tools/miri/tests/fail/alloc/reallocate-dangling.stderr
@@ -6,7 +6,17 @@ LL |     unsafe { __rust_realloc(ptr, layout.size(), layout.align(), new_size) }
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/reallocate-dangling.rs:LL:CC
+   |
+LL |         let x = alloc(Layout::from_size_align_unchecked(1, 1));
+   |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/reallocate-dangling.rs:LL:CC
+   |
+LL |         dealloc(x, Layout::from_size_align_unchecked(1, 1));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `std::alloc::realloc` at RUSTLIB/alloc/src/alloc.rs:LL:CC
 note: inside `main`
   --> $DIR/reallocate-dangling.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
index c69a3af293c..a5580160c39 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.stack.stderr
@@ -6,7 +6,12 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/issue-miri-1050-1.rs:LL:CC
+   |
+LL |         let ptr = Box::into_raw(Box::new(0u16));
+   |                                 ^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
index c69a3af293c..a5580160c39 100644
--- a/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
+++ b/src/tools/miri/tests/fail/both_borrows/issue-miri-1050-1.tree.stderr
@@ -6,7 +6,12 @@ LL |         Box(unsafe { Unique::new_unchecked(raw) }, alloc)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/issue-miri-1050-1.rs:LL:CC
+   |
+LL |         let ptr = Box::into_raw(Box::new(0u16));
+   |                                 ^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `std::boxed::Box::<u32>::from_raw_in` at RUSTLIB/alloc/src/boxed.rs:LL:CC
    = note: inside `std::boxed::Box::<u32>::from_raw` at RUSTLIB/alloc/src/boxed.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/breakpoint.rs b/src/tools/miri/tests/fail/breakpoint.rs
index fb1d4d958ee..2dd87ea6083 100644
--- a/src/tools/miri/tests/fail/breakpoint.rs
+++ b/src/tools/miri/tests/fail/breakpoint.rs
@@ -2,6 +2,6 @@
 
 fn main() {
     unsafe {
-        core::intrinsics::breakpoint() //~ ERROR: Trace/breakpoint trap
+        core::intrinsics::breakpoint() //~ ERROR: trace/breakpoint trap
     };
 }
diff --git a/src/tools/miri/tests/fail/breakpoint.stderr b/src/tools/miri/tests/fail/breakpoint.stderr
index 7b9bbdb3828..8b99c1493b5 100644
--- a/src/tools/miri/tests/fail/breakpoint.stderr
+++ b/src/tools/miri/tests/fail/breakpoint.stderr
@@ -1,8 +1,8 @@
-error: abnormal termination: Trace/breakpoint trap
+error: abnormal termination: trace/breakpoint trap
   --> $DIR/breakpoint.rs:LL:CC
    |
 LL |         core::intrinsics::breakpoint()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ Trace/breakpoint trap
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ trace/breakpoint trap
    |
    = note: inside `main` at $DIR/breakpoint.rs:LL:CC
 
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr
index 398f216e731..6a3efbdd3dd 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_addr_of.stderr
@@ -6,7 +6,17 @@ LL |     let x = unsafe { ptr::addr_of!(*p) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_addr_of.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_addr_of.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at RUSTLIB/core/src/ptr/mod.rs:LL:CC
    = note: this error originates in the macro `ptr::addr_of` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr
index cb95d71a605..fad4b4be28c 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_deref.stderr
@@ -6,7 +6,17 @@ LL |     let x = unsafe { *p };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_deref.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_deref.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_pointer_deref.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr
index 85bd2bed9c3..7ef5fd329a4 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_offset.stderr
@@ -6,7 +6,17 @@ LL |     let x = unsafe { p.offset(42) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_offset.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_offset.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_pointer_offset.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr
index f2d58fe7697..1de6465802b 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_pointer_project_underscore.stderr
@@ -6,7 +6,17 @@ LL |         let _ = *p;
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dangling_pointer_project_underscore.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_pointer_project_underscore.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_pointer_project_underscore.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr
index c15f17f3b82..bf6ee775e94 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/dangling_zst_deref.stderr
@@ -6,7 +6,17 @@ LL |     let _x = unsafe { *p };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dangling_zst_deref.rs:LL:CC
+   |
+LL |         let b = Box::new(42);
+   |                 ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dangling_zst_deref.rs:LL:CC
+   |
+LL |     };
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/dangling_zst_deref.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read1.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read1.stderr
index b2461ce4230..7d2aed371bd 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read1.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read1.stderr
@@ -6,8 +6,14 @@ LL |     let x = unsafe { *v.as_ptr().wrapping_offset(5) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/out_of_bounds_read1.rs:LL:CC
+   |
+LL |     let v: Vec<u8> = vec![1, 2];
+   |                      ^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/out_of_bounds_read1.rs:LL:CC
+   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read2.stderr b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read2.stderr
index b17058b4062..69a8498f097 100644
--- a/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read2.stderr
+++ b/src/tools/miri/tests/fail/dangling_pointers/out_of_bounds_read2.stderr
@@ -6,8 +6,14 @@ LL |     let x = unsafe { *v.as_ptr().wrapping_offset(5) };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/out_of_bounds_read2.rs:LL:CC
+   |
+LL |     let v: Vec<u8> = vec![1, 2];
+   |                      ^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/out_of_bounds_read2.rs:LL:CC
+   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr
index 4efc35c15e2..810e48d59c6 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_read_race2.stderr
@@ -6,7 +6,21 @@ LL |             *ptr.0
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dealloc_read_race2.rs:LL:CC
+   |
+LL |     let pointer: *mut usize = Box::into_raw(Box::new(0usize));
+   |                                             ^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dealloc_read_race2.rs:LL:CC
+   |
+LL | /             __rust_dealloc(
+LL | |                 ptr.0 as *mut _,
+LL | |                 std::mem::size_of::<usize>(),
+LL | |                 std::mem::align_of::<usize>(),
+LL | |             )
+   | |_____________^
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_read_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr
index fad525830e6..7d672cd4d62 100644
--- a/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr
+++ b/src/tools/miri/tests/fail/data_race/dealloc_write_race2.stderr
@@ -6,7 +6,21 @@ LL |             *ptr.0 = 2;
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/dealloc_write_race2.rs:LL:CC
+   |
+LL |     let pointer: *mut usize = Box::into_raw(Box::new(0usize));
+   |                                             ^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/dealloc_write_race2.rs:LL:CC
+   |
+LL | /             __rust_dealloc(
+LL | |                 ptr.0 as *mut _,
+LL | |                 std::mem::size_of::<usize>(),
+LL | |                 std::mem::align_of::<usize>(),
+LL | |             );
+   | |_____________^
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/dealloc_write_race2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
index 625a8bda8af..d47af50d407 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
@@ -8,13 +8,13 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         {
             let non_copy = S(42);
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // Inside `callee`, the first argument and `*ptr` are basically
             // aliasing places!
-            Call(unit, after_call, callee(Move(*ptr), ptr))
+            Call(_unit = callee(Move(*ptr), ptr), after_call)
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
index 471dc1dd6dd..381442e69b1 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
index 8393b80f25b..544cd575ada 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.write(S(0)) };
 note: inside `main`
   --> $DIR/arg_inplace_mutate.rs:LL:CC
    |
-LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = callee(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
index 093b55759fd..ea773048dd4 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
@@ -6,12 +6,12 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         let _observe: i32;
         {
             let non_copy = S(42);
             // This could change `non_copy` in-place
-            Call(unit, after_call, change_arg(Move(non_copy)))
+            Call(_unit = change_arg(Move(non_copy)), after_call)
         }
         after_call = {
             // So now we must not be allowed to observe non-copy again.
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
index baa91484793..cba23c21d12 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
index 2e57872db96..8c6a7df7a6d 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
@@ -9,12 +9,12 @@ pub struct S(i32);
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 fn main() {
     mir! {
-        let unit: ();
+        let _unit: ();
         {
             let non_copy = S(42);
             let ptr = std::ptr::addr_of_mut!(non_copy);
             // This could change `non_copy` in-place
-            Call(unit, after_call, change_arg(Move(*ptr), ptr))
+            Call(_unit = change_arg(Move(*ptr), ptr), after_call)
         }
         after_call = {
             Return()
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
index a842d3a8044..f8532186be2 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -10,7 +10,7 @@ help: <TAG> was created by a SharedReadWrite retag at offsets [0x0..0x4]
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -27,8 +27,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
index 5af4856bbe3..c33645bdd28 100644
--- a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -12,7 +12,7 @@ help: the accessed tag <TAG> was created here
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
 LL | /     mir! {
-LL | |         let unit: ();
+LL | |         let _unit: ();
 LL | |         {
 LL | |             let non_copy = S(42);
 ...  |
@@ -29,8 +29,8 @@ LL |     x.0 = 0;
 note: inside `main`
   --> $DIR/arg_inplace_observe_during.rs:LL:CC
    |
-LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_unit = change_arg(Move(*ptr), ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
index bf5199307f6..e4821bc0bac 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.both.stderr
@@ -1,22 +1,35 @@
 thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `nounwind`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
-LL | |
-LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
index bf5199307f6..e4821bc0bac 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.definition.stderr
@@ -1,22 +1,35 @@
 thread 'main' panicked at $DIR/exported_symbol_bad_unwind2.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `nounwind`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL | / extern "C-unwind" fn nounwind() {
-LL | |
-LL | |
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `nounwind` at $DIR/exported_symbol_bad_unwind2.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
index c774bd4dd91..25e13d74754 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.extern_block.stderr
@@ -5,7 +5,7 @@ error: Undefined Behavior: unwinding past a stack frame that does not allow unwi
   --> $DIR/exported_symbol_bad_unwind2.rs:LL:CC
    |
 LL |     unsafe { nounwind() }
-   |              ^^^^^^^^^^ unwinding past a stack frame that does not allow unwinding
+   | ^ unwinding past a stack frame that does not allow unwinding
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
index 65ba3433c28..10bd5eb7211 100644
--- a/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
+++ b/src/tools/miri/tests/fail/function_calls/exported_symbol_bad_unwind2.rs
@@ -1,11 +1,14 @@
 //@revisions: extern_block definition both
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@[definition,both]error-in-other-file: aborted execution
 #![feature(rustc_attrs, c_unwind)]
 
 #[cfg_attr(any(definition, both), rustc_nounwind)]
 #[no_mangle]
 extern "C-unwind" fn nounwind() {
-    //~[definition]^ ERROR: abnormal termination: panic in a function that cannot unwind
-    //~[both]^^ ERROR: abnormal termination: panic in a function that cannot unwind
     panic!();
 }
 
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
index 9d9dfc89f89..0a31adabf73 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
@@ -11,8 +11,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
index 829809102fa..3d560af3d5e 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
@@ -15,7 +15,7 @@ pub fn main() {
             let ptr = &raw mut x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(*ptr, after_call, myfun(ptr))
+            Call(*ptr = myfun(ptr), after_call)
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
index d486dcb95df..875cc5edad9 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
@@ -27,8 +27,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
index c491a904a10..66c2fb8db19 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.read() };
 note: inside `main`
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |             Call(*ptr, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(*ptr = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
index 7e9a6320026..9d53faccd1e 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.rs
@@ -9,11 +9,11 @@ use std::intrinsics::mir::*;
 pub fn main() {
     mir! {
         {
-            let x = 0;
-            let ptr = &raw mut x;
+            let _x = 0;
+            let ptr = &raw mut _x;
             // We arrange for `myfun` to have a pointer that aliases
             // its return place. Even just reading from that pointer is UB.
-            Call(x, after_call, myfun(ptr))
+            Call(_x = myfun(ptr), after_call)
         }
 
         after_call = {
diff --git a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
index 33a8a4b46bd..443ee8643fc 100644
--- a/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing2.stderr
@@ -13,8 +13,8 @@ help: the accessed tag <TAG> was created here
    |
 LL | /     mir! {
 LL | |         {
-LL | |             let x = 0;
-LL | |             let ptr = &raw mut x;
+LL | |             let _x = 0;
+LL | |             let ptr = &raw mut _x;
 ...  |
 LL | |         }
 LL | |     }
@@ -29,8 +29,8 @@ LL |     unsafe { ptr.write(0) };
 note: inside `main`
   --> $DIR/return_pointer_aliasing2.rs:LL:CC
    |
-LL |             Call(x, after_call, myfun(ptr))
-   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |             Call(_x = myfun(ptr), after_call)
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: this error originates in the macro `::core::intrinsics::mir::__internal_remove_let` which comes from the expansion of the macro `mir` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/generator-pinned-moved.stderr b/src/tools/miri/tests/fail/generator-pinned-moved.stderr
index 3eb17f05584..e29e352e64b 100644
--- a/src/tools/miri/tests/fail/generator-pinned-moved.stderr
+++ b/src/tools/miri/tests/fail/generator-pinned-moved.stderr
@@ -6,7 +6,17 @@ LL |         *num += 1;
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/generator-pinned-moved.rs:LL:CC
+   |
+LL |         let mut generator_iterator = Box::new(GeneratorIteratorAdapter(firstn()));
+   |                                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/generator-pinned-moved.rs:LL:CC
+   |
+LL |     }; // *deallocate* generator_iterator
+   |     ^
+   = note: BACKTRACE (of the first span):
    = note: inside closure at $DIR/generator-pinned-moved.rs:LL:CC
 note: inside `<GeneratorIteratorAdapter<[static generator@$DIR/generator-pinned-moved.rs:LL:CC]> as std::iter::Iterator>::next`
   --> $DIR/generator-pinned-moved.rs:LL:CC
diff --git a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr
index 7e24f45f653..ddf3249d059 100644
--- a/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/float_to_int_64_neg.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u128`
+error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
   --> $DIR/float_to_int_64_neg.rs:LL:CC
    |
 LL |         float_to_int_unchecked::<f64, u128>(-1.0000000000001f64);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1 which cannot be represented in target type `u128`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on -1.0000000000000999 which cannot be represented in target type `u128`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr b/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr
index b18147ce379..7cc4bc184a1 100644
--- a/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/ptr_offset_ptr_plus_0.stderr
@@ -6,7 +6,12 @@ LL |     let _x = unsafe { x.offset(0) }; // UB despite offset 0, the pointer is
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/ptr_offset_ptr_plus_0.rs:LL:CC
+   |
+LL |     let x = Box::into_raw(Box::new(0u32));
+   |                           ^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/ptr_offset_ptr_plus_0.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
index ea5ad62aea9..7b2387944af 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-float-to-int.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
+error: Undefined Behavior: `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
   --> $DIR/simd-float-to-int.rs:LL:CC
    |
 LL |         let _x: i32x2 = f32x2::from_array([f32::MAX, f32::MIN]).to_int_unchecked();
-   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `float_to_int_unchecked` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
+   |                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `simd_cast` intrinsic called on 3.40282347E+38 which cannot be represented in target type `i32`
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
index a745b61029d..5beee034db2 100644
--- a/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/simd-scatter.stderr
@@ -11,8 +11,14 @@ LL | |         );
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/simd-scatter.rs:LL:CC
+   |
+LL |         let mut vec: Vec<i8> = vec![10, 11, 12, 13, 14, 15, 16, 17, 18];
+   |                                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/simd-scatter.rs:LL:CC
+   = note: this error originates in the macro `vec` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
index 59781f02366..b8fa32c986f 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.rs
@@ -1,7 +1,11 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
 #![feature(never_type)]
 
 #[allow(deprecated, invalid_value)]
 fn main() {
     let _ = unsafe { std::mem::uninitialized::<!>() };
-    //~^ ERROR: attempted to instantiate uninhabited type `!`
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
index f2cc3430326..70e10e8dc48 100644
--- a/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/uninit_uninhabited_type.stderr
@@ -1,10 +1,24 @@
-error: abnormal termination: aborted execution: attempted to instantiate uninhabited type `!`
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+aborted execution: attempted to instantiate uninhabited type `!`
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/uninit_uninhabited_type.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::uninitialized::<!>() };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
-   |
-   = note: inside `main` at $DIR/uninit_uninhabited_type.rs:LL:CC
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
index e9c6e464e88..70ae60593a1 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.rs
@@ -1,5 +1,10 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
+
 #[allow(deprecated, invalid_value)]
 fn main() {
     let _ = unsafe { std::mem::zeroed::<fn()>() };
-    //~^ ERROR: attempted to zero-initialize type `fn()`, which is invalid
 }
diff --git a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
index 77d58228043..56143b6c205 100644
--- a/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
+++ b/src/tools/miri/tests/fail/intrinsics/zero_fn_ptr.stderr
@@ -1,10 +1,24 @@
-error: abnormal termination: aborted execution: attempted to zero-initialize type `fn()`, which is invalid
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+aborted execution: attempted to zero-initialize type `fn()`, which is invalid
+note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/zero_fn_ptr.rs:LL:CC
    |
 LL |     let _ = unsafe { std::mem::zeroed::<fn()>() };
-   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `fn()`, which is invalid
-   |
-   = note: inside `main` at $DIR/zero_fn_ptr.rs:LL:CC
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/panic/double_panic.rs b/src/tools/miri/tests/fail/panic/double_panic.rs
index adb30714269..4627e9f1c8e 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.rs
+++ b/src/tools/miri/tests/fail/panic/double_panic.rs
@@ -1,6 +1,8 @@
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
 //@normalize-stderr-test: "\| +\^+" -> "| ^"
 //@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
 //@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
 
 struct Foo;
 impl Drop for Foo {
@@ -9,7 +11,6 @@ impl Drop for Foo {
     }
 }
 fn main() {
-    //~^ERROR: panic in a function that cannot unwind
     let _foo = Foo;
     panic!("first");
 }
diff --git a/src/tools/miri/tests/fail/panic/double_panic.stderr b/src/tools/miri/tests/fail/panic/double_panic.stderr
index 8e008da75ee..25c9a7c44bc 100644
--- a/src/tools/miri/tests/fail/panic/double_panic.stderr
+++ b/src/tools/miri/tests/fail/panic/double_panic.stderr
@@ -4,17 +4,31 @@ note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
 thread 'main' panicked at $DIR/double_panic.rs:LL:CC:
 second
 stack backtrace:
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `main`
   --> $DIR/double_panic.rs:LL:CC
    |
 LL | / fn main() {
-LL | |
 LL | |     let _foo = Foo;
 LL | |     panic!("first");
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `main` at $DIR/double_panic.rs:LL:CC
+   | |_^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/rc_as_ptr.stderr b/src/tools/miri/tests/fail/rc_as_ptr.stderr
index 129916ac73c..460ed977137 100644
--- a/src/tools/miri/tests/fail/rc_as_ptr.stderr
+++ b/src/tools/miri/tests/fail/rc_as_ptr.stderr
@@ -6,7 +6,17 @@ LL |     assert_eq!(42, **unsafe { &*Weak::as_ptr(&weak) });
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/rc_as_ptr.rs:LL:CC
+   |
+LL |     let strong = Rc::new(Box::new(42));
+   |                          ^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/rc_as_ptr.rs:LL:CC
+   |
+LL |     drop(strong);
+   |     ^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at RUSTLIB/core/src/macros/mod.rs:LL:CC
    = note: this error originates in the macro `assert_eq` (in Nightly builds, run with -Z macro-backtrace for more info)
 
diff --git a/src/tools/miri/tests/fail/shims/memchr_null.stderr b/src/tools/miri/tests/fail/shims/memchr_null.stderr
index d48606f34ad..54b58f22c6c 100644
--- a/src/tools/miri/tests/fail/shims/memchr_null.stderr
+++ b/src/tools/miri/tests/fail/shims/memchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
   --> $DIR/memchr_null.rs:LL:CC
    |
 LL |         libc::memchr(ptr::null(), 0, 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/memcmp_null.stderr b/src/tools/miri/tests/fail/shims/memcmp_null.stderr
index 7a09c779894..8b2882fc243 100644
--- a/src/tools/miri/tests/fail/shims/memcmp_null.stderr
+++ b/src/tools/miri/tests/fail/shims/memcmp_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
   --> $DIR/memcmp_null.rs:LL:CC
    |
 LL |         libc::memcmp(ptr::null(), ptr::null(), 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/memcmp_zero.rs b/src/tools/miri/tests/fail/shims/memcmp_zero.rs
new file mode 100644
index 00000000000..f2ddc200563
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/memcmp_zero.rs
@@ -0,0 +1,13 @@
+//@ignore-target-windows: No libc on Windows
+//@compile-flags: -Zmiri-permissive-provenance
+
+// C says that passing "invalid" pointers is UB for all string functions.
+// It is unclear whether `(int*)42` is "invalid", but there is no actually
+// a `char` living at that address, so arguably it cannot be a valid pointer.
+// Hence this is UB.
+fn main() {
+    let ptr = 42 as *const u8;
+    unsafe {
+        libc::memcmp(ptr.cast(), ptr.cast(), 0); //~ERROR: dangling
+    }
+}
diff --git a/src/tools/miri/tests/fail/shims/memcmp_zero.stderr b/src/tools/miri/tests/fail/shims/memcmp_zero.stderr
new file mode 100644
index 00000000000..e21b9b06008
--- /dev/null
+++ b/src/tools/miri/tests/fail/shims/memcmp_zero.stderr
@@ -0,0 +1,15 @@
+error: Undefined Behavior: out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+  --> $DIR/memcmp_zero.rs:LL:CC
+   |
+LL |         libc::memcmp(ptr.cast(), ptr.cast(), 0);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: 0x2a[noalloc] is a dangling pointer (it has no provenance)
+   |
+   = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
+   = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
+   = note: BACKTRACE:
+   = note: inside `main` at $DIR/memcmp_zero.rs:LL:CC
+
+note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
+
+error: aborting due to previous error
+
diff --git a/src/tools/miri/tests/fail/shims/memrchr_null.stderr b/src/tools/miri/tests/fail/shims/memrchr_null.stderr
index b5b7630e7fd..cc11ba89f8f 100644
--- a/src/tools/miri/tests/fail/shims/memrchr_null.stderr
+++ b/src/tools/miri/tests/fail/shims/memrchr_null.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: memory access failed: null pointer is a dangling pointer (it has no provenance)
+error: Undefined Behavior: out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
   --> $DIR/memrchr_null.rs:LL:CC
    |
 LL |         libc::memrchr(ptr::null(), 0, 0);
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ memory access failed: null pointer is a dangling pointer (it has no provenance)
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ out-of-bounds pointer use: null pointer is a dangling pointer (it has no provenance)
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
diff --git a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr
index 8b9969da8fd..44e122330bc 100644
--- a/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr
+++ b/src/tools/miri/tests/fail/shims/mmap_use_after_munmap.stderr
@@ -21,7 +21,24 @@ LL |         let _x = *(ptr as *mut u8);
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/mmap_use_after_munmap.rs:LL:CC
+   |
+LL |           let ptr = libc::mmap(
+   |  ___________________^
+LL | |             std::ptr::null_mut(),
+LL | |             4096,
+LL | |             libc::PROT_READ | libc::PROT_WRITE,
+...  |
+LL | |             0,
+LL | |         );
+   | |_________^
+help: ALLOC was deallocated here:
+  --> $DIR/mmap_use_after_munmap.rs:LL:CC
+   |
+LL |         libc::munmap(ptr, 4096);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/mmap_use_after_munmap.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/terminate-terminator.rs b/src/tools/miri/tests/fail/terminate-terminator.rs
index bd6cd69215a..5373b5f70c0 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.rs
+++ b/src/tools/miri/tests/fail/terminate-terminator.rs
@@ -1,5 +1,10 @@
 //@compile-flags: -Zmir-opt-level=3 -Zinline-mir-hint-threshold=1000
-// Enable MIR inlining to ensure that `TerminatorKind::Terminate` is generated
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
+//@error-in-other-file: aborted execution
+// Enable MIR inlining to ensure that `TerminatorKind::UnwindTerminate` is generated
 // instead of just `UnwindAction::Terminate`.
 
 #![feature(c_unwind)]
@@ -12,7 +17,6 @@ impl Drop for Foo {
 
 #[inline(always)]
 fn has_cleanup() {
-    //~^ ERROR: panic in a function that cannot unwind
     let _f = Foo;
     panic!();
 }
diff --git a/src/tools/miri/tests/fail/terminate-terminator.stderr b/src/tools/miri/tests/fail/terminate-terminator.stderr
index 4f73b599a3f..e9277ebdbfd 100644
--- a/src/tools/miri/tests/fail/terminate-terminator.stderr
+++ b/src/tools/miri/tests/fail/terminate-terminator.stderr
@@ -3,27 +3,41 @@ warning: You have explicitly enabled MIR optimizations, overriding Miri's defaul
 thread 'main' panicked at $DIR/terminate-terminator.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `has_cleanup`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL | / fn has_cleanup() {
-LL | |
 LL | |     let _f = Foo;
 LL | |     panic!();
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `has_cleanup` at $DIR/terminate-terminator.rs:LL:CC
+   | |_^
 note: inside `panic_abort`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL |     has_cleanup();
-   |     ^^^^^^^^^^^^^
+   | ^
 note: inside `main`
   --> $DIR/terminate-terminator.rs:LL:CC
    |
 LL |     panic_abort();
-   |     ^^^^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.rs b/src/tools/miri/tests/fail/unwind-action-terminate.rs
index 876b9a9ab0a..77844844483 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.rs
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.rs
@@ -1,7 +1,11 @@
+//@error-in-other-file: aborted execution
+//@normalize-stderr-test: "unsafe \{ libc::abort\(\) \}|crate::intrinsics::abort\(\);" -> "ABORT();"
+//@normalize-stderr-test: "\| +\^+" -> "| ^"
+//@normalize-stderr-test: "\n  +[0-9]+:[^\n]+" -> "$1"
+//@normalize-stderr-test: "\n at [^\n]+" -> "$1"
 #![feature(c_unwind)]
 
 extern "C" fn panic_abort() {
-    //~^ ERROR: panic in a function that cannot unwind
     panic!()
 }
 
diff --git a/src/tools/miri/tests/fail/unwind-action-terminate.stderr b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
index daa4a808df9..cf94dbb9909 100644
--- a/src/tools/miri/tests/fail/unwind-action-terminate.stderr
+++ b/src/tools/miri/tests/fail/unwind-action-terminate.stderr
@@ -1,21 +1,35 @@
 thread 'main' panicked at $DIR/unwind-action-terminate.rs:LL:CC:
 explicit panic
 note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace
-error: abnormal termination: panic in a function that cannot unwind
+thread 'main' panicked at RUSTLIB/core/src/panicking.rs:LL:CC:
+panic in a function that cannot unwind
+stack backtrace:
+thread caused non-unwinding panic. aborting.
+error: abnormal termination: the program aborted execution
+  --> RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   |
+LL |     ABORT();
+   | ^ the program aborted execution
+   |
+   = note: inside `std::sys::PLATFORM::abort_internal` at RUSTLIB/std/src/sys/PLATFORM/mod.rs:LL:CC
+   = note: inside `std::panicking::rust_panic_with_hook` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside closure at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `std::sys_common::backtrace::__rust_end_short_backtrace::<[closure@std::panicking::begin_panic_handler::{closure#0}], !>` at RUSTLIB/std/src/sys_common/backtrace.rs:LL:CC
+   = note: inside `std::panicking::begin_panic_handler` at RUSTLIB/std/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_nounwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+   = note: inside `core::panicking::panic_cannot_unwind` at RUSTLIB/core/src/panicking.rs:LL:CC
+note: inside `panic_abort`
   --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL | / extern "C" fn panic_abort() {
-LL | |
 LL | |     panic!()
 LL | | }
-   | |_^ panic in a function that cannot unwind
-   |
-   = note: inside `panic_abort` at $DIR/unwind-action-terminate.rs:LL:CC
+   | |_^
 note: inside `main`
   --> $DIR/unwind-action-terminate.rs:LL:CC
    |
 LL |     panic_abort();
-   |     ^^^^^^^^^^^^^
+   | ^
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
 
diff --git a/src/tools/miri/tests/fail/zst2.stderr b/src/tools/miri/tests/fail/zst2.stderr
index 63f40ed2067..49954b1fd14 100644
--- a/src/tools/miri/tests/fail/zst2.stderr
+++ b/src/tools/miri/tests/fail/zst2.stderr
@@ -6,7 +6,17 @@ LL |     unsafe { *x = zst_val };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/zst2.rs:LL:CC
+   |
+LL |     let mut x_box = Box::new(1u8);
+   |                     ^^^^^^^^^^^^^
+help: ALLOC was deallocated here:
+  --> $DIR/zst2.rs:LL:CC
+   |
+LL |     drop(x_box);
+   |     ^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/zst2.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/fail/zst3.stderr b/src/tools/miri/tests/fail/zst3.stderr
index c9accf2c8fb..b62aef675d2 100644
--- a/src/tools/miri/tests/fail/zst3.stderr
+++ b/src/tools/miri/tests/fail/zst3.stderr
@@ -6,7 +6,12 @@ LL |     unsafe { *(x as *mut [u8; 0]) = zst_val };
    |
    = help: this indicates a bug in the program: it performed an invalid operation, and caused Undefined Behavior
    = help: see https://doc.rust-lang.org/nightly/reference/behavior-considered-undefined.html for further information
-   = note: BACKTRACE:
+help: ALLOC was allocated here:
+  --> $DIR/zst3.rs:LL:CC
+   |
+LL |     let mut x_box = Box::new(1u8);
+   |                     ^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
    = note: inside `main` at $DIR/zst3.rs:LL:CC
 
 note: some details are omitted, run with `MIRIFLAGS=-Zmiri-backtrace=full` for a verbose backtrace
diff --git a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
index dcfebd0f82b..d410a875b1b 100644
--- a/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
+++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
@@ -11,7 +11,7 @@ pub fn main() {
         {
             let x = 0;
             let ptr = &raw mut x;
-            Call(*ptr, after_call, myfun())
+            Call(*ptr = myfun(), after_call)
         }
 
         after_call = {
diff --git a/src/tools/rust-analyzer/Cargo.lock b/src/tools/rust-analyzer/Cargo.lock
index a2b263cf2d8..49e96236c51 100644
--- a/src/tools/rust-analyzer/Cargo.lock
+++ b/src/tools/rust-analyzer/Cargo.lock
@@ -999,23 +999,23 @@ checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
 
 [[package]]
 name = "lsp-server"
-version = "0.7.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "3711e4d6f491dc9edc0f1df80e204f38206775ac92c1241e89b79229a850bc00"
+version = "0.7.3"
 dependencies = [
  "crossbeam-channel",
  "log",
+ "lsp-types",
  "serde",
  "serde_json",
 ]
 
 [[package]]
 name = "lsp-server"
-version = "0.7.2"
+version = "0.7.3"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "72417faa455bfb4e5bf14b157d8e2ca2ed74b4e89b8cf42ea2d864825ae5c8a2"
 dependencies = [
  "crossbeam-channel",
  "log",
- "lsp-types",
  "serde",
  "serde_json",
 ]
@@ -1555,7 +1555,7 @@ dependencies = [
  "ide-ssr",
  "itertools",
  "load-cargo",
- "lsp-server 0.7.1",
+ "lsp-server 0.7.3 (registry+https://github.com/rust-lang/crates.io-index)",
  "lsp-types",
  "mbe",
  "mimalloc",
diff --git a/src/tools/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/Cargo.toml
index f6a50bfa6b2..5eb59d6db11 100644
--- a/src/tools/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/Cargo.toml
@@ -86,7 +86,7 @@ proc-macro-test = { path = "./crates/proc-macro-test" }
 # In-tree crates that are published separately and follow semver. See lib/README.md
 line-index = { version = "0.1.0-pre.1" }
 la-arena = { version = "0.3.1" }
-lsp-server = { version = "0.7.1" }
+lsp-server = { version = "0.7.3" }
 
 # non-local crates
 smallvec = { version = "1.10.0", features = [
@@ -97,7 +97,8 @@ smallvec = { version = "1.10.0", features = [
 smol_str = "0.2.0"
 nohash-hasher = "0.2.0"
 text-size = "1.1.0"
-serde = { version = "1.0.156", features = ["derive"] }
+# See https://github.com/serde-rs/serde/issues/2538#issuecomment-1684517372 for why we pin serde
+serde = { version = "1.0.156, < 1.0.172", features = ["derive"] }
 serde_json = "1.0.96"
 triomphe = { version = "0.1.8", default-features = false, features = ["std"] }
 # can't upgrade due to dashmap depending on 0.12.3 currently
diff --git a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
index 323ee4260e4..aaac0fc3790 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/fixture.rs
@@ -130,6 +130,7 @@ impl ChangeFixture {
         let mut default_crate_root: Option<FileId> = None;
         let mut default_target_data_layout: Option<String> = None;
         let mut default_cfg = CfgOptions::default();
+        let mut default_env = Env::new_for_test_fixture();
 
         let mut file_set = FileSet::default();
         let mut current_source_root_kind = SourceRootKind::Local;
@@ -200,6 +201,7 @@ impl ChangeFixture {
                 assert!(default_crate_root.is_none());
                 default_crate_root = Some(file_id);
                 default_cfg = meta.cfg;
+                default_env.extend(meta.env.iter().map(|(x, y)| (x.to_owned(), y.to_owned())));
                 default_target_data_layout = meta.target_data_layout;
             }
 
@@ -220,7 +222,7 @@ impl ChangeFixture {
                 None,
                 default_cfg,
                 Default::default(),
-                Env::new_for_test_fixture(),
+                default_env,
                 false,
                 CrateOrigin::Local { repo: None, name: None },
                 default_target_data_layout
diff --git a/src/tools/rust-analyzer/crates/base-db/src/input.rs b/src/tools/rust-analyzer/crates/base-db/src/input.rs
index c47799f1320..b75c7079be7 100644
--- a/src/tools/rust-analyzer/crates/base-db/src/input.rs
+++ b/src/tools/rust-analyzer/crates/base-db/src/input.rs
@@ -686,6 +686,12 @@ impl fmt::Display for Edition {
     }
 }
 
+impl Extend<(String, String)> for Env {
+    fn extend<T: IntoIterator<Item = (String, String)>>(&mut self, iter: T) {
+        self.entries.extend(iter);
+    }
+}
+
 impl FromIterator<(String, String)> for Env {
     fn from_iter<T: IntoIterator<Item = (String, String)>>(iter: T) -> Self {
         Env { entries: FromIterator::from_iter(iter) }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
index fae07111806..a5db75a91eb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/attr.rs
@@ -431,12 +431,10 @@ impl AttrsWithOwner {
                         .item_tree(db)
                         .raw_attrs(AttrOwner::ModItem(definition_tree_id.value.into()))
                         .clone(),
-                    ModuleOrigin::BlockExpr { block } => RawAttrs::from_attrs_owner(
-                        db.upcast(),
-                        InFile::new(block.file_id, block.to_node(db.upcast()))
-                            .as_ref()
-                            .map(|it| it as &dyn ast::HasAttrs),
-                    ),
+                    ModuleOrigin::BlockExpr { id, .. } => {
+                        let tree = db.block_item_tree_query(id);
+                        tree.raw_attrs(AttrOwner::TopLevel).clone()
+                    }
                 }
             }
             AttrDefId::FieldId(it) => {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
index 3853a6ab3a5..7071fcb9394 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/lower.rs
@@ -505,6 +505,9 @@ impl ExprCollector<'_> {
                 let mut args = Vec::new();
                 let mut arg_types = Vec::new();
                 if let Some(pl) = e.param_list() {
+                    let num_params = pl.params().count();
+                    args.reserve_exact(num_params);
+                    arg_types.reserve_exact(num_params);
                     for param in pl.params() {
                         let pat = this.collect_pat_top(param.pat());
                         let type_ref =
@@ -1100,7 +1103,9 @@ impl ExprCollector<'_> {
                 ast::Stmt::ExprStmt(es) => matches!(es.expr(), Some(ast::Expr::MacroExpr(_))),
                 _ => false,
             });
-            statement_has_item || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
+            statement_has_item
+                || matches!(block.tail_expr(), Some(ast::Expr::MacroExpr(_)))
+                || (block.may_carry_attributes() && block.attrs().next().is_some())
         };
 
         let block_id = if block_has_items {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
index 4e015a7fbbb..44eeed9e3fb 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/body/tests/block.rs
@@ -38,9 +38,9 @@ fn outer() {
 "#,
         expect![[r#"
             block scope
-            CrateStruct: t
-            PlainStruct: t v
-            SelfStruct: t
+            CrateStruct: ti
+            PlainStruct: ti vi
+            SelfStruct: ti
             Struct: v
             SuperStruct: _
 
@@ -66,7 +66,7 @@ fn outer() {
 "#,
         expect![[r#"
             block scope
-            imported: t v
+            imported: ti vi
             name: v
 
             crate
@@ -92,9 +92,9 @@ fn outer() {
 "#,
         expect![[r#"
             block scope
-            inner1: t
+            inner1: ti
             inner2: v
-            outer: v
+            outer: vi
 
             block scope
             inner: v
@@ -121,7 +121,7 @@ struct Struct {}
 "#,
         expect![[r#"
             block scope
-            Struct: t
+            Struct: ti
 
             crate
             Struct: t
@@ -153,7 +153,7 @@ fn outer() {
 "#,
         expect![[r#"
             block scope
-            ResolveMe: t
+            ResolveMe: ti
 
             block scope
             m2: t
@@ -214,7 +214,7 @@ fn f() {
 "#,
         expect![[r#"
             block scope
-            ResolveMe: t
+            ResolveMe: ti
 
             block scope
             h: v
@@ -292,7 +292,7 @@ pub mod cov_mark {
             nested: v
 
             crate
-            cov_mark: t
+            cov_mark: ti
             f: v
         "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/data.rs b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
index 91db68058b0..68defa3858f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/data.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/data.rs
@@ -487,7 +487,7 @@ impl ExternCrateDeclData {
             db.crate_def_map(loc.container.krate())
                 .extern_prelude()
                 .find(|&(prelude_name, ..)| *prelude_name == name)
-                .map(|(_, root)| root.krate())
+                .map(|(_, (root, _))| root.krate())
         };
 
         Arc::new(Self {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/db.rs b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
index e34a6768f28..31c1a713031 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/db.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/db.rs
@@ -82,6 +82,9 @@ pub trait DefDatabase: InternDatabase + ExpandDatabase + Upcast<dyn ExpandDataba
     #[salsa::invoke(ItemTree::file_item_tree_query)]
     fn file_item_tree(&self, file_id: HirFileId) -> Arc<ItemTree>;
 
+    #[salsa::invoke(ItemTree::block_item_tree_query)]
+    fn block_item_tree_query(&self, block_id: BlockId) -> Arc<ItemTree>;
+
     #[salsa::invoke(crate_def_map_wait)]
     #[salsa::transparent]
     fn crate_def_map(&self, krate: CrateId) -> Arc<DefMap>;
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
index df2af4c89b0..b60e7909105 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/find_path.rs
@@ -11,7 +11,7 @@ use crate::{
     nameres::DefMap,
     path::{ModPath, PathKind},
     visibility::Visibility,
-    ModuleDefId, ModuleId,
+    CrateRootModuleId, ModuleDefId, ModuleId,
 };
 
 /// Find a path that can be used to refer to a certain item. This can depend on
@@ -81,7 +81,7 @@ fn find_path_inner(
     }
 
     let def_map = from.def_map(db);
-    let crate_root = def_map.crate_root().into();
+    let crate_root = def_map.crate_root();
     // - if the item is a module, jump straight to module search
     if let ItemInNs::Types(ModuleDefId::ModuleId(module_id)) = item {
         let mut visited_modules = FxHashSet::default();
@@ -149,7 +149,7 @@ fn find_path_for_module(
     db: &dyn DefDatabase,
     def_map: &DefMap,
     visited_modules: &mut FxHashSet<ModuleId>,
-    crate_root: ModuleId,
+    crate_root: CrateRootModuleId,
     from: ModuleId,
     module_id: ModuleId,
     max_len: usize,
@@ -183,7 +183,7 @@ fn find_path_for_module(
 
     // - if the item is the crate root of a dependency crate, return the name from the extern prelude
     let root_def_map = crate_root.def_map(db);
-    for (name, def_id) in root_def_map.extern_prelude() {
+    for (name, (def_id, _extern_crate)) in root_def_map.extern_prelude() {
         if module_id == def_id {
             let name = scope_name.unwrap_or_else(|| name.clone());
 
@@ -192,7 +192,7 @@ fn find_path_for_module(
                     def_map[local_id]
                         .scope
                         .type_(&name)
-                        .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id))
+                        .filter(|&(id, _)| id != ModuleDefId::ModuleId(def_id.into()))
                 })
                 .is_some();
             let kind = if name_already_occupied_in_type_ns {
@@ -224,6 +224,7 @@ fn find_path_for_module(
     )
 }
 
+// FIXME: Do we still need this now that we record import origins, and hence aliases?
 fn find_in_scope(
     db: &dyn DefDatabase,
     def_map: &DefMap,
@@ -244,7 +245,7 @@ fn find_in_prelude(
     item: ItemInNs,
     from: ModuleId,
 ) -> Option<ModPath> {
-    let prelude_module = root_def_map.prelude()?;
+    let (prelude_module, _) = root_def_map.prelude()?;
     // Preludes in block DefMaps are ignored, only the crate DefMap is searched
     let prelude_def_map = prelude_module.def_map(db);
     let prelude_scope = &prelude_def_map[prelude_module.local_id].scope;
@@ -293,7 +294,7 @@ fn calculate_best_path(
     db: &dyn DefDatabase,
     def_map: &DefMap,
     visited_modules: &mut FxHashSet<ModuleId>,
-    crate_root: ModuleId,
+    crate_root: CrateRootModuleId,
     max_len: usize,
     item: ItemInNs,
     from: ModuleId,
@@ -346,6 +347,11 @@ fn calculate_best_path(
         let extern_paths = crate_graph[from.krate].dependencies.iter().filter_map(|dep| {
             let import_map = db.import_map(dep.crate_id);
             import_map.import_info_for(item).and_then(|info| {
+                if info.is_doc_hidden {
+                    // the item or import is `#[doc(hidden)]`, so skip it as it is in an external crate
+                    return None;
+                }
+
                 // Determine best path for containing module and append last segment from `info`.
                 // FIXME: we should guide this to look up the path locally, or from the same crate again?
                 let mut path = find_path_for_module(
@@ -1293,4 +1299,65 @@ pub mod prelude {
             "None",
         );
     }
+
+    #[test]
+    fn different_crate_renamed_through_dep() {
+        check_found_path(
+            r#"
+//- /main.rs crate:main deps:intermediate
+$0
+//- /intermediate.rs crate:intermediate deps:std
+pub extern crate std as std_renamed;
+//- /std.rs crate:std
+pub struct S;
+    "#,
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+            "intermediate::std_renamed::S",
+        );
+    }
+
+    #[test]
+    fn different_crate_doc_hidden() {
+        check_found_path(
+            r#"
+//- /main.rs crate:main deps:intermediate
+$0
+//- /intermediate.rs crate:intermediate deps:std
+#[doc(hidden)]
+pub extern crate std;
+pub extern crate std as longer;
+//- /std.rs crate:std
+pub struct S;
+    "#,
+            "intermediate::longer::S",
+            "intermediate::longer::S",
+            "intermediate::longer::S",
+            "intermediate::longer::S",
+        );
+    }
+
+    #[test]
+    fn respect_doc_hidden() {
+        check_found_path(
+            r#"
+//- /main.rs crate:main deps:std,lazy_static
+$0
+//- /lazy_static.rs crate:lazy_static deps:core
+#[doc(hidden)]
+pub use core::ops::Deref as __Deref;
+//- /std.rs crate:std deps:core
+pub use core::ops;
+//- /core.rs crate:core
+pub mod ops {
+    pub trait Deref {}
+}
+    "#,
+            "std::ops::Deref",
+            "std::ops::Deref",
+            "std::ops::Deref",
+            "std::ops::Deref",
+        );
+    }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
index d7d44e41388..1e2535a8a99 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/generics.rs
@@ -21,10 +21,11 @@ use crate::{
     db::DefDatabase,
     dyn_map::{keys, DynMap},
     expander::Expander,
+    item_tree::{AttrOwner, ItemTree},
     lower::LowerCtx,
     nameres::{DefMap, MacroSubNs},
     src::{HasChildSource, HasSource},
-    type_ref::{LifetimeRef, TypeBound, TypeRef},
+    type_ref::{ConstRef, LifetimeRef, TypeBound, TypeRef},
     AdtId, ConstParamId, GenericDefId, HasModule, LifetimeParamId, LocalLifetimeParamId,
     LocalTypeOrConstParamId, Lookup, TypeOrConstParamId, TypeParamId,
 };
@@ -48,7 +49,7 @@ pub struct LifetimeParamData {
 pub struct ConstParamData {
     pub name: Name,
     pub ty: Interned<TypeRef>,
-    pub has_default: bool,
+    pub default: Option<ConstRef>,
 }
 
 #[derive(Copy, Clone, PartialEq, Eq, Debug, Hash)]
@@ -75,7 +76,7 @@ impl TypeOrConstParamData {
     pub fn has_default(&self) -> bool {
         match self {
             TypeOrConstParamData::TypeParamData(it) => it.default.is_some(),
-            TypeOrConstParamData::ConstParamData(it) => it.has_default,
+            TypeOrConstParamData::ConstParamData(it) => it.default.is_some(),
         }
     }
 
@@ -154,12 +155,58 @@ impl GenericParams {
         def: GenericDefId,
     ) -> Interned<GenericParams> {
         let _p = profile::span("generic_params_query");
+
+        let krate = def.module(db).krate;
+        let cfg_options = db.crate_graph();
+        let cfg_options = &cfg_options[krate].cfg_options;
+
+        // Returns the generic parameters that are enabled under the current `#[cfg]` options
+        let enabled_params = |params: &Interned<GenericParams>, item_tree: &ItemTree| {
+            let enabled = |param| item_tree.attrs(db, krate, param).is_cfg_enabled(cfg_options);
+
+            // In the common case, no parameters will by disabled by `#[cfg]` attributes.
+            // Therefore, make a first pass to check if all parameters are enabled and, if so,
+            // clone the `Interned<GenericParams>` instead of recreating an identical copy.
+            let all_type_or_consts_enabled =
+                params.type_or_consts.iter().all(|(idx, _)| enabled(idx.into()));
+            let all_lifetimes_enabled = params.lifetimes.iter().all(|(idx, _)| enabled(idx.into()));
+
+            if all_type_or_consts_enabled && all_lifetimes_enabled {
+                params.clone()
+            } else {
+                Interned::new(GenericParams {
+                    type_or_consts: all_type_or_consts_enabled
+                        .then(|| params.type_or_consts.clone())
+                        .unwrap_or_else(|| {
+                            params
+                                .type_or_consts
+                                .iter()
+                                .filter_map(|(idx, param)| {
+                                    enabled(idx.into()).then(|| param.clone())
+                                })
+                                .collect()
+                        }),
+                    lifetimes: all_lifetimes_enabled
+                        .then(|| params.lifetimes.clone())
+                        .unwrap_or_else(|| {
+                            params
+                                .lifetimes
+                                .iter()
+                                .filter_map(|(idx, param)| {
+                                    enabled(idx.into()).then(|| param.clone())
+                                })
+                                .collect()
+                        }),
+                    where_predicates: params.where_predicates.clone(),
+                })
+            }
+        };
         macro_rules! id_to_generics {
             ($id:ident) => {{
                 let id = $id.lookup(db).id;
                 let tree = id.item_tree(db);
                 let item = &tree[id.value];
-                item.generic_params.clone()
+                enabled_params(&item.generic_params, &tree)
             }};
         }
 
@@ -169,7 +216,8 @@ impl GenericParams {
                 let tree = loc.id.item_tree(db);
                 let item = &tree[loc.id.value];
 
-                let mut generic_params = GenericParams::clone(&item.explicit_generic_params);
+                let enabled_params = enabled_params(&item.explicit_generic_params, &tree);
+                let mut generic_params = GenericParams::clone(&enabled_params);
 
                 let module = loc.container.module(db);
                 let func_data = db.function_data(id);
@@ -198,9 +246,14 @@ impl GenericParams {
         }
     }
 
-    pub(crate) fn fill(&mut self, lower_ctx: &LowerCtx<'_>, node: &dyn HasGenericParams) {
+    pub(crate) fn fill(
+        &mut self,
+        lower_ctx: &LowerCtx<'_>,
+        node: &dyn HasGenericParams,
+        add_param_attrs: impl FnMut(AttrOwner, ast::GenericParam),
+    ) {
         if let Some(params) = node.generic_param_list() {
-            self.fill_params(lower_ctx, params)
+            self.fill_params(lower_ctx, params, add_param_attrs)
         }
         if let Some(where_clause) = node.where_clause() {
             self.fill_where_predicates(lower_ctx, where_clause);
@@ -218,7 +271,12 @@ impl GenericParams {
         }
     }
 
-    fn fill_params(&mut self, lower_ctx: &LowerCtx<'_>, params: ast::GenericParamList) {
+    fn fill_params(
+        &mut self,
+        lower_ctx: &LowerCtx<'_>,
+        params: ast::GenericParamList,
+        mut add_param_attrs: impl FnMut(AttrOwner, ast::GenericParam),
+    ) {
         for type_or_const_param in params.type_or_const_params() {
             match type_or_const_param {
                 ast::TypeOrConstParam::Type(type_param) => {
@@ -232,13 +290,14 @@ impl GenericParams {
                         default,
                         provenance: TypeParamProvenance::TypeParamList,
                     };
-                    self.type_or_consts.alloc(param.into());
+                    let idx = self.type_or_consts.alloc(param.into());
                     let type_ref = TypeRef::Path(name.into());
                     self.fill_bounds(
                         lower_ctx,
                         type_param.type_bound_list(),
                         Either::Left(type_ref),
                     );
+                    add_param_attrs(idx.into(), ast::GenericParam::TypeParam(type_param));
                 }
                 ast::TypeOrConstParam::Const(const_param) => {
                     let name = const_param.name().map_or_else(Name::missing, |it| it.as_name());
@@ -248,9 +307,10 @@ impl GenericParams {
                     let param = ConstParamData {
                         name,
                         ty: Interned::new(ty),
-                        has_default: const_param.default_val().is_some(),
+                        default: ConstRef::from_const_param(lower_ctx, &const_param),
                     };
-                    self.type_or_consts.alloc(param.into());
+                    let idx = self.type_or_consts.alloc(param.into());
+                    add_param_attrs(idx.into(), ast::GenericParam::ConstParam(const_param));
                 }
             }
         }
@@ -258,13 +318,14 @@ impl GenericParams {
             let name =
                 lifetime_param.lifetime().map_or_else(Name::missing, |lt| Name::new_lifetime(&lt));
             let param = LifetimeParamData { name: name.clone() };
-            self.lifetimes.alloc(param);
+            let idx = self.lifetimes.alloc(param);
             let lifetime_ref = LifetimeRef::new_name(name);
             self.fill_bounds(
                 lower_ctx,
                 lifetime_param.type_bound_list(),
                 Either::Right(lifetime_ref),
             );
+            add_param_attrs(idx.into(), ast::GenericParam::LifetimeParam(lifetime_param));
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
index 57f023ef35d..75adf21abdc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/type_ref.rs
@@ -393,6 +393,17 @@ impl ConstRef {
         Self::Scalar(LiteralConstRef::Unknown)
     }
 
+    pub(crate) fn from_const_param(
+        lower_ctx: &LowerCtx<'_>,
+        param: &ast::ConstParam,
+    ) -> Option<Self> {
+        let default = param.default_val();
+        match default {
+            Some(_) => Some(Self::from_const_arg(lower_ctx, default)),
+            None => None,
+        }
+    }
+
     pub fn display<'a>(&'a self, db: &'a dyn ExpandDatabase) -> impl fmt::Display + 'a {
         struct Display<'a>(&'a dyn ExpandDatabase, &'a ConstRef);
         impl fmt::Display for Display<'_> {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
index 4b2e5041a12..6038caaf8fc 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/import_map.rs
@@ -11,6 +11,7 @@ use itertools::Itertools;
 use rustc_hash::{FxHashMap, FxHashSet, FxHasher};
 use triomphe::Arc;
 
+use crate::item_scope::ImportOrExternCrate;
 use crate::{
     db::DefDatabase, item_scope::ItemInNs, nameres::DefMap, visibility::Visibility, AssocItemId,
     ModuleDefId, ModuleId, TraitId,
@@ -29,6 +30,8 @@ pub struct ImportInfo {
     pub container: ModuleId,
     /// Whether the import is a trait associated item or not.
     pub is_trait_assoc_item: bool,
+    /// Whether this item is annotated with `#[doc(hidden)]`.
+    pub is_doc_hidden: bool,
 }
 
 /// A map from publicly exported items to its name.
@@ -109,23 +112,41 @@ fn collect_import_map(db: &dyn DefDatabase, krate: CrateId) -> FxIndexMap<ItemIn
         });
 
         for (name, per_ns) in visible_items {
-            for item in per_ns.iter_items() {
+            for (item, import) in per_ns.iter_items() {
+                // FIXME: Not yet used, but will be once we handle doc(hidden) import sources
+                let attr_id = if let Some(import) = import {
+                    match import {
+                        ImportOrExternCrate::ExternCrate(id) => Some(id.into()),
+                        ImportOrExternCrate::Import(id) => Some(id.import.into()),
+                    }
+                } else {
+                    match item {
+                        ItemInNs::Types(id) | ItemInNs::Values(id) => id.try_into().ok(),
+                        ItemInNs::Macros(id) => Some(id.into()),
+                    }
+                };
+                let is_doc_hidden =
+                    attr_id.map_or(false, |attr_id| db.attrs(attr_id).has_doc_hidden());
+
                 let import_info = ImportInfo {
                     name: name.clone(),
                     container: module,
                     is_trait_assoc_item: false,
+                    is_doc_hidden,
                 };
 
                 match depth_map.entry(item) {
-                    Entry::Vacant(entry) => {
-                        entry.insert(depth);
-                    }
+                    Entry::Vacant(entry) => _ = entry.insert((depth, is_doc_hidden)),
                     Entry::Occupied(mut entry) => {
-                        if depth < *entry.get() {
-                            entry.insert(depth);
-                        } else {
+                        let &(occ_depth, occ_is_doc_hidden) = entry.get();
+                        // Prefer the one that is not doc(hidden),
+                        // Otherwise, if both have the same doc(hidden)-ness and the new path is shorter, prefer that one.
+                        let overwrite_entry = occ_is_doc_hidden && !is_doc_hidden
+                            || occ_is_doc_hidden == is_doc_hidden && depth < occ_depth;
+                        if !overwrite_entry {
                             continue;
                         }
+                        entry.insert((depth, is_doc_hidden));
                     }
                 }
 
@@ -162,10 +183,10 @@ fn collect_trait_assoc_items(
     trait_import_info: &ImportInfo,
 ) {
     let _p = profile::span("collect_trait_assoc_items");
-    for (assoc_item_name, item) in &db.trait_data(tr).items {
+    for &(ref assoc_item_name, item) in &db.trait_data(tr).items {
         let module_def_id = match item {
-            AssocItemId::FunctionId(f) => ModuleDefId::from(*f),
-            AssocItemId::ConstId(c) => ModuleDefId::from(*c),
+            AssocItemId::FunctionId(f) => ModuleDefId::from(f),
+            AssocItemId::ConstId(c) => ModuleDefId::from(c),
             // cannot use associated type aliases directly: need a `<Struct as Trait>::TypeAlias`
             // qualifier, ergo no need to store it for imports in import_map
             AssocItemId::TypeAliasId(_) => {
@@ -183,6 +204,7 @@ fn collect_trait_assoc_items(
             container: trait_import_info.container,
             name: assoc_item_name.clone(),
             is_trait_assoc_item: true,
+            is_doc_hidden: db.attrs(item.into()).has_doc_hidden(),
         };
         map.insert(assoc_item, assoc_item_info);
     }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
index 873accafb43..7c11fb9d136 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_scope.rs
@@ -6,6 +6,7 @@ use std::collections::hash_map::Entry;
 use base_db::CrateId;
 use hir_expand::{attrs::AttrId, db::ExpandDatabase, name::Name, AstId, MacroCallId};
 use itertools::Itertools;
+use la_arena::Idx;
 use once_cell::sync::Lazy;
 use profile::Count;
 use rustc_hash::{FxHashMap, FxHashSet};
@@ -15,16 +16,10 @@ use syntax::ast;
 
 use crate::{
     db::DefDatabase, per_ns::PerNs, visibility::Visibility, AdtId, BuiltinType, ConstId,
-    ExternCrateId, HasModule, ImplId, LocalModuleId, MacroId, ModuleDefId, ModuleId, TraitId,
-    UseId,
+    ExternCrateId, HasModule, ImplId, LocalModuleId, Lookup, MacroId, ModuleDefId, ModuleId,
+    TraitId, UseId,
 };
 
-#[derive(Copy, Clone, Debug)]
-pub(crate) enum ImportType {
-    Glob,
-    Named,
-}
-
 #[derive(Debug, Default)]
 pub struct PerNsGlobImports {
     types: FxHashSet<(LocalModuleId, Name)>,
@@ -32,15 +27,50 @@ pub struct PerNsGlobImports {
     macros: FxHashSet<(LocalModuleId, Name)>,
 }
 
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ImportOrExternCrate {
+    Import(ImportId),
+    ExternCrate(ExternCrateId),
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub(crate) enum ImportType {
+    Import(ImportId),
+    Glob(UseId),
+    ExternCrate(ExternCrateId),
+}
+
+impl ImportOrExternCrate {
+    pub fn into_import(self) -> Option<ImportId> {
+        match self {
+            ImportOrExternCrate::Import(it) => Some(it),
+            _ => None,
+        }
+    }
+}
+
+#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
+pub enum ImportOrDef {
+    Import(ImportId),
+    ExternCrate(ExternCrateId),
+    Def(ModuleDefId),
+}
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Ord, PartialOrd)]
+pub struct ImportId {
+    pub import: UseId,
+    pub idx: Idx<ast::UseTree>,
+}
+
 #[derive(Debug, Default, PartialEq, Eq)]
 pub struct ItemScope {
     _c: Count<Self>,
 
     /// Defs visible in this scope. This includes `declarations`, but also
-    /// imports.
-    types: FxHashMap<Name, (ModuleDefId, Visibility)>,
-    values: FxHashMap<Name, (ModuleDefId, Visibility)>,
-    macros: FxHashMap<Name, (MacroId, Visibility)>,
+    /// imports. The imports belong to this module and can be resolved by using them on
+    /// the `use_imports_*` fields.
+    types: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
+    values: FxHashMap<Name, (ModuleDefId, Visibility, Option<ImportId>)>,
+    macros: FxHashMap<Name, (MacroId, Visibility, Option<ImportId>)>,
     unresolved: FxHashSet<Name>,
 
     /// The defs declared in this scope. Each def has a single scope where it is
@@ -50,7 +80,14 @@ pub struct ItemScope {
     impls: Vec<ImplId>,
     unnamed_consts: Vec<ConstId>,
     /// Traits imported via `use Trait as _;`.
-    unnamed_trait_imports: FxHashMap<TraitId, Visibility>,
+    unnamed_trait_imports: FxHashMap<TraitId, (Visibility, Option<ImportId>)>,
+
+    // the resolutions of the imports of this scope
+    use_imports_types: FxHashMap<ImportOrExternCrate, ImportOrDef>,
+    use_imports_values: FxHashMap<ImportId, ImportOrDef>,
+    use_imports_macros: FxHashMap<ImportId, ImportOrDef>,
+
+    use_decls: Vec<UseId>,
     extern_crate_decls: Vec<ExternCrateId>,
     /// Macros visible in current module in legacy textual scope
     ///
@@ -82,7 +119,7 @@ struct DeriveMacroInvocation {
 pub(crate) static BUILTIN_SCOPE: Lazy<FxHashMap<Name, PerNs>> = Lazy::new(|| {
     BuiltinType::ALL
         .iter()
-        .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public)))
+        .map(|(name, ty)| (name.clone(), PerNs::types((*ty).into(), Visibility::Public, None)))
         .collect()
 });
 
@@ -105,11 +142,77 @@ impl ItemScope {
             .chain(self.values.keys())
             .chain(self.macros.keys())
             .chain(self.unresolved.iter())
-            .sorted()
             .unique()
+            .sorted()
             .map(move |name| (name, self.get(name)))
     }
 
+    pub fn imports(&self) -> impl Iterator<Item = ImportId> + '_ {
+        self.use_imports_types
+            .keys()
+            .copied()
+            .filter_map(ImportOrExternCrate::into_import)
+            .chain(self.use_imports_values.keys().copied())
+            .chain(self.use_imports_macros.keys().copied())
+            .unique()
+            .sorted()
+    }
+
+    pub fn fully_resolve_import(&self, db: &dyn DefDatabase, mut import: ImportId) -> PerNs {
+        let mut res = PerNs::none();
+
+        let mut def_map;
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_macros.get(&import) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(ModuleDefId::MacroId(def)) => {
+                    res.macros = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_types.get(&ImportOrExternCrate::Import(import)) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(def) => {
+                    res.types = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        let mut scope = self;
+        while let Some(&m) = scope.use_imports_values.get(&import) {
+            match m {
+                ImportOrDef::Import(i) => {
+                    let module_id = i.import.lookup(db).container;
+                    def_map = module_id.def_map(db);
+                    scope = &def_map[module_id.local_id].scope;
+                    import = i;
+                }
+                ImportOrDef::Def(def) => {
+                    res.values = Some((def, Visibility::Public, None));
+                    break;
+                }
+                _ => break,
+            }
+        }
+        res
+    }
+
     pub fn declarations(&self) -> impl Iterator<Item = ModuleDefId> + '_ {
         self.declarations.iter().copied()
     }
@@ -121,8 +224,7 @@ impl ItemScope {
     }
 
     pub fn use_decls(&self) -> impl Iterator<Item = UseId> + ExactSizeIterator + '_ {
-        // FIXME: to be implemented
-        std::iter::empty()
+        self.use_decls.iter().copied()
     }
 
     pub fn impls(&self) -> impl Iterator<Item = ImplId> + ExactSizeIterator + '_ {
@@ -132,13 +234,13 @@ impl ItemScope {
     pub fn values(
         &self,
     ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
-        self.values.values().copied()
+        self.values.values().copied().map(|(a, b, _)| (a, b))
     }
 
-    pub fn types(
+    pub(crate) fn types(
         &self,
     ) -> impl Iterator<Item = (ModuleDefId, Visibility)> + ExactSizeIterator + '_ {
-        self.types.values().copied()
+        self.types.values().copied().map(|(def, vis, _)| (def, vis))
     }
 
     pub fn unnamed_consts(&self) -> impl Iterator<Item = ConstId> + '_ {
@@ -165,33 +267,55 @@ impl ItemScope {
     }
 
     pub(crate) fn type_(&self, name: &Name) -> Option<(ModuleDefId, Visibility)> {
-        self.types.get(name).copied()
+        self.types.get(name).copied().map(|(a, b, _)| (a, b))
     }
 
     /// XXX: this is O(N) rather than O(1), try to not introduce new usages.
     pub(crate) fn name_of(&self, item: ItemInNs) -> Option<(&Name, Visibility)> {
-        let (def, mut iter) = match item {
-            ItemInNs::Macros(def) => {
-                return self.macros.iter().find_map(|(name, &(other_def, vis))| {
-                    (other_def == def).then_some((name, vis))
-                });
-            }
-            ItemInNs::Types(def) => (def, self.types.iter()),
-            ItemInNs::Values(def) => (def, self.values.iter()),
-        };
-        iter.find_map(|(name, &(other_def, vis))| (other_def == def).then_some((name, vis)))
+        match item {
+            ItemInNs::Macros(def) => self
+                .macros
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+            ItemInNs::Types(def) => self
+                .types
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+
+            ItemInNs::Values(def) => self
+                .values
+                .iter()
+                .find_map(|(name, &(other_def, vis, _))| (other_def == def).then_some((name, vis))),
+        }
     }
 
     pub(crate) fn traits(&self) -> impl Iterator<Item = TraitId> + '_ {
         self.types
             .values()
-            .filter_map(|&(def, _)| match def {
+            .filter_map(|&(def, _, _)| match def {
                 ModuleDefId::TraitId(t) => Some(t),
                 _ => None,
             })
             .chain(self.unnamed_trait_imports.keys().copied())
     }
 
+    pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
+        self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
+            self.unnamed_trait_imports.iter().map(|(tr, (vis, i))| {
+                (
+                    None,
+                    PerNs::types(
+                        ModuleDefId::TraitId(*tr),
+                        *vis,
+                        i.map(ImportOrExternCrate::Import),
+                    ),
+                )
+            }),
+        )
+    }
+}
+
+impl ItemScope {
     pub(crate) fn declare(&mut self, def: ModuleDefId) {
         self.declarations.push(def)
     }
@@ -277,12 +401,14 @@ impl ItemScope {
         })
     }
 
+    // FIXME: This is only used in collection, we should move the relevant parts of it out of ItemScope
     pub(crate) fn unnamed_trait_vis(&self, tr: TraitId) -> Option<Visibility> {
-        self.unnamed_trait_imports.get(&tr).copied()
+        self.unnamed_trait_imports.get(&tr).copied().map(|(a, _)| a)
     }
 
     pub(crate) fn push_unnamed_trait(&mut self, tr: TraitId, vis: Visibility) {
-        self.unnamed_trait_imports.insert(tr, vis);
+        // FIXME: import
+        self.unnamed_trait_imports.insert(tr, (vis, None));
     }
 
     pub(crate) fn push_res_with_import(
@@ -290,51 +416,187 @@ impl ItemScope {
         glob_imports: &mut PerNsGlobImports,
         lookup: (LocalModuleId, Name),
         def: PerNs,
-        def_import_type: ImportType,
+        import: Option<ImportType>,
     ) -> bool {
         let mut changed = false;
 
-        macro_rules! check_changed {
-            (
-                $changed:ident,
-                ( $this:ident / $def:ident ) . $field:ident,
-                $glob_imports:ident [ $lookup:ident ],
-                $def_import_type:ident
-            ) => {{
-                if let Some(fld) = $def.$field {
-                    let existing = $this.$field.entry($lookup.1.clone());
-                    match existing {
-                        Entry::Vacant(entry) => {
-                            match $def_import_type {
-                                ImportType::Glob => {
-                                    $glob_imports.$field.insert($lookup.clone());
+        // FIXME: Document and simplify this
+
+        if let Some(mut fld) = def.types {
+            let existing = self.types.entry(lookup.1.clone());
+            match existing {
+                Entry::Vacant(entry) => {
+                    match import {
+                        Some(ImportType::Glob(_)) => {
+                            glob_imports.types.insert(lookup.clone());
+                        }
+                        _ => _ = glob_imports.types.remove(&lookup),
+                    }
+                    let import = match import {
+                        Some(ImportType::ExternCrate(extern_crate)) => {
+                            Some(ImportOrExternCrate::ExternCrate(extern_crate))
+                        }
+                        Some(ImportType::Import(import)) => {
+                            Some(ImportOrExternCrate::Import(import))
+                        }
+                        None | Some(ImportType::Glob(_)) => None,
+                    };
+                    let prev = std::mem::replace(&mut fld.2, import);
+                    if let Some(import) = import {
+                        self.use_imports_types.insert(
+                            import,
+                            match prev {
+                                Some(ImportOrExternCrate::Import(import)) => {
+                                    ImportOrDef::Import(import)
                                 }
-                                ImportType::Named => {
-                                    $glob_imports.$field.remove(&$lookup);
+                                Some(ImportOrExternCrate::ExternCrate(import)) => {
+                                    ImportOrDef::ExternCrate(import)
                                 }
+                                None => ImportOrDef::Def(fld.0),
+                            },
+                        );
+                    }
+                    entry.insert(fld);
+                    changed = true;
+                }
+                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                    if glob_imports.types.remove(&lookup) {
+                        let import = match import {
+                            Some(ImportType::ExternCrate(extern_crate)) => {
+                                Some(ImportOrExternCrate::ExternCrate(extern_crate))
+                            }
+                            Some(ImportType::Import(import)) => {
+                                Some(ImportOrExternCrate::Import(import))
                             }
+                            None | Some(ImportType::Glob(_)) => None,
+                        };
+                        let prev = std::mem::replace(&mut fld.2, import);
+                        if let Some(import) = import {
+                            self.use_imports_types.insert(
+                                import,
+                                match prev {
+                                    Some(ImportOrExternCrate::Import(import)) => {
+                                        ImportOrDef::Import(import)
+                                    }
+                                    Some(ImportOrExternCrate::ExternCrate(import)) => {
+                                        ImportOrDef::ExternCrate(import)
+                                    }
+                                    None => ImportOrDef::Def(fld.0),
+                                },
+                            );
+                        }
+                        cov_mark::hit!(import_shadowed);
+                        entry.insert(fld);
+                        changed = true;
+                    }
+                }
+                _ => {}
+            }
+        }
 
-                            entry.insert(fld);
-                            $changed = true;
+        if let Some(mut fld) = def.values {
+            let existing = self.values.entry(lookup.1.clone());
+            match existing {
+                Entry::Vacant(entry) => {
+                    match import {
+                        Some(ImportType::Glob(_)) => {
+                            glob_imports.values.insert(lookup.clone());
                         }
-                        Entry::Occupied(mut entry)
-                            if matches!($def_import_type, ImportType::Named) =>
-                        {
-                            if $glob_imports.$field.remove(&$lookup) {
-                                cov_mark::hit!(import_shadowed);
-                                entry.insert(fld);
-                                $changed = true;
-                            }
+                        _ => _ = glob_imports.values.remove(&lookup),
+                    }
+                    let import = match import {
+                        Some(ImportType::Import(import)) => Some(import),
+                        _ => None,
+                    };
+                    let prev = std::mem::replace(&mut fld.2, import);
+                    if let Some(import) = import {
+                        self.use_imports_values.insert(
+                            import,
+                            match prev {
+                                Some(import) => ImportOrDef::Import(import),
+                                None => ImportOrDef::Def(fld.0),
+                            },
+                        );
+                    }
+                    entry.insert(fld);
+                    changed = true;
+                }
+                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                    if glob_imports.values.remove(&lookup) {
+                        cov_mark::hit!(import_shadowed);
+                        let import = match import {
+                            Some(ImportType::Import(import)) => Some(import),
+                            _ => None,
+                        };
+                        let prev = std::mem::replace(&mut fld.2, import);
+                        if let Some(import) = import {
+                            self.use_imports_values.insert(
+                                import,
+                                match prev {
+                                    Some(import) => ImportOrDef::Import(import),
+                                    None => ImportOrDef::Def(fld.0),
+                                },
+                            );
                         }
-                        _ => {}
+                        entry.insert(fld);
+                        changed = true;
                     }
                 }
-            }};
+                _ => {}
+            }
         }
 
-        check_changed!(changed, (self / def).types, glob_imports[lookup], def_import_type);
-        check_changed!(changed, (self / def).values, glob_imports[lookup], def_import_type);
-        check_changed!(changed, (self / def).macros, glob_imports[lookup], def_import_type);
+        if let Some(mut fld) = def.macros {
+            let existing = self.macros.entry(lookup.1.clone());
+            match existing {
+                Entry::Vacant(entry) => {
+                    match import {
+                        Some(ImportType::Glob(_)) => {
+                            glob_imports.macros.insert(lookup.clone());
+                        }
+                        _ => _ = glob_imports.macros.remove(&lookup),
+                    }
+                    let import = match import {
+                        Some(ImportType::Import(import)) => Some(import),
+                        _ => None,
+                    };
+                    let prev = std::mem::replace(&mut fld.2, import);
+                    if let Some(import) = import {
+                        self.use_imports_macros.insert(
+                            import,
+                            match prev {
+                                Some(import) => ImportOrDef::Import(import),
+                                None => ImportOrDef::Def(fld.0.into()),
+                            },
+                        );
+                    }
+                    entry.insert(fld);
+                    changed = true;
+                }
+                Entry::Occupied(mut entry) if !matches!(import, Some(ImportType::Glob(..))) => {
+                    if glob_imports.macros.remove(&lookup) {
+                        cov_mark::hit!(import_shadowed);
+                        let import = match import {
+                            Some(ImportType::Import(import)) => Some(import),
+                            _ => None,
+                        };
+                        let prev = std::mem::replace(&mut fld.2, import);
+                        if let Some(import) = import {
+                            self.use_imports_macros.insert(
+                                import,
+                                match prev {
+                                    Some(import) => ImportOrDef::Import(import),
+                                    None => ImportOrDef::Def(fld.0.into()),
+                                },
+                            );
+                        }
+                        entry.insert(fld);
+                        changed = true;
+                    }
+                }
+                _ => {}
+            }
+        }
 
         if def.is_none() && self.unresolved.insert(lookup.1) {
             changed = true;
@@ -343,27 +605,18 @@ impl ItemScope {
         changed
     }
 
-    pub(crate) fn resolutions(&self) -> impl Iterator<Item = (Option<Name>, PerNs)> + '_ {
-        self.entries().map(|(name, res)| (Some(name.clone()), res)).chain(
-            self.unnamed_trait_imports
-                .iter()
-                .map(|(tr, vis)| (None, PerNs::types(ModuleDefId::TraitId(*tr), *vis))),
-        )
-    }
-
     /// Marks everything that is not a procedural macro as private to `this_module`.
     pub(crate) fn censor_non_proc_macros(&mut self, this_module: ModuleId) {
         self.types
             .values_mut()
-            .chain(self.values.values_mut())
+            .map(|(def, vis, _)| (def, vis))
+            .chain(self.values.values_mut().map(|(def, vis, _)| (def, vis)))
             .map(|(_, v)| v)
-            .chain(self.unnamed_trait_imports.values_mut())
+            .chain(self.unnamed_trait_imports.values_mut().map(|(vis, _)| vis))
             .for_each(|vis| *vis = Visibility::Module(this_module));
 
-        for (mac, vis) in self.macros.values_mut() {
-            if let MacroId::ProcMacroId(_) = mac {
-                // FIXME: Technically this is insufficient since reexports of proc macros are also
-                // forbidden. Practically nobody does that.
+        for (mac, vis, import) in self.macros.values_mut() {
+            if matches!(mac, MacroId::ProcMacroId(_) if import.is_none()) {
                 continue;
             }
 
@@ -382,14 +635,25 @@ impl ItemScope {
                 name.map_or("_".to_string(), |name| name.display(db).to_string())
             );
 
-            if def.types.is_some() {
+            if let Some((.., i)) = def.types {
                 buf.push_str(" t");
+                match i {
+                    Some(ImportOrExternCrate::Import(_)) => buf.push('i'),
+                    Some(ImportOrExternCrate::ExternCrate(_)) => buf.push('e'),
+                    None => (),
+                }
             }
-            if def.values.is_some() {
+            if let Some((.., i)) = def.values {
                 buf.push_str(" v");
+                if i.is_some() {
+                    buf.push('i');
+                }
             }
-            if def.macros.is_some() {
+            if let Some((.., i)) = def.macros {
                 buf.push_str(" m");
+                if i.is_some() {
+                    buf.push('i');
+                }
             }
             if def.is_none() {
                 buf.push_str(" _");
@@ -415,10 +679,17 @@ impl ItemScope {
             attr_macros,
             derive_macros,
             extern_crate_decls,
+            use_decls,
+            use_imports_values,
+            use_imports_types,
+            use_imports_macros,
         } = self;
         types.shrink_to_fit();
         values.shrink_to_fit();
         macros.shrink_to_fit();
+        use_imports_types.shrink_to_fit();
+        use_imports_values.shrink_to_fit();
+        use_imports_macros.shrink_to_fit();
         unresolved.shrink_to_fit();
         declarations.shrink_to_fit();
         impls.shrink_to_fit();
@@ -428,32 +699,44 @@ impl ItemScope {
         attr_macros.shrink_to_fit();
         derive_macros.shrink_to_fit();
         extern_crate_decls.shrink_to_fit();
+        use_decls.shrink_to_fit();
     }
 }
 
 impl PerNs {
-    pub(crate) fn from_def(def: ModuleDefId, v: Visibility, has_constructor: bool) -> PerNs {
+    pub(crate) fn from_def(
+        def: ModuleDefId,
+        v: Visibility,
+        has_constructor: bool,
+        import: Option<ImportOrExternCrate>,
+    ) -> PerNs {
         match def {
-            ModuleDefId::ModuleId(_) => PerNs::types(def, v),
-            ModuleDefId::FunctionId(_) => PerNs::values(def, v),
+            ModuleDefId::ModuleId(_) => PerNs::types(def, v, import),
+            ModuleDefId::FunctionId(_) => {
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+            }
             ModuleDefId::AdtId(adt) => match adt {
-                AdtId::UnionId(_) => PerNs::types(def, v),
-                AdtId::EnumId(_) => PerNs::types(def, v),
+                AdtId::UnionId(_) => PerNs::types(def, v, import),
+                AdtId::EnumId(_) => PerNs::types(def, v, import),
                 AdtId::StructId(_) => {
                     if has_constructor {
-                        PerNs::both(def, def, v)
+                        PerNs::both(def, def, v, import)
                     } else {
-                        PerNs::types(def, v)
+                        PerNs::types(def, v, import)
                     }
                 }
             },
-            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v),
-            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => PerNs::values(def, v),
-            ModuleDefId::TraitId(_) => PerNs::types(def, v),
-            ModuleDefId::TraitAliasId(_) => PerNs::types(def, v),
-            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v),
-            ModuleDefId::BuiltinType(_) => PerNs::types(def, v),
-            ModuleDefId::MacroId(mac) => PerNs::macros(mac, v),
+            ModuleDefId::EnumVariantId(_) => PerNs::both(def, def, v, import),
+            ModuleDefId::ConstId(_) | ModuleDefId::StaticId(_) => {
+                PerNs::values(def, v, import.and_then(ImportOrExternCrate::into_import))
+            }
+            ModuleDefId::TraitId(_) => PerNs::types(def, v, import),
+            ModuleDefId::TraitAliasId(_) => PerNs::types(def, v, import),
+            ModuleDefId::TypeAliasId(_) => PerNs::types(def, v, import),
+            ModuleDefId::BuiltinType(_) => PerNs::types(def, v, import),
+            ModuleDefId::MacroId(mac) => {
+                PerNs::macros(mac, v, import.and_then(ImportOrExternCrate::into_import))
+            }
         }
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
index c9b0f75f1a8..3e1922750b9 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree.rs
@@ -64,11 +64,11 @@ use triomphe::Arc;
 use crate::{
     attr::Attrs,
     db::DefDatabase,
-    generics::GenericParams,
+    generics::{GenericParams, LifetimeParamData, TypeOrConstParamData},
     path::{path, AssociatedTypeBinding, GenericArgs, ImportAlias, ModPath, Path, PathKind},
     type_ref::{Mutability, TraitRef, TypeBound, TypeRef},
     visibility::RawVisibility,
-    BlockId,
+    BlockId, Lookup,
 };
 
 #[derive(Copy, Clone, Eq, PartialEq)]
@@ -143,6 +143,16 @@ impl ItemTree {
         Arc::new(item_tree)
     }
 
+    pub(crate) fn block_item_tree_query(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
+        let loc = block.lookup(db);
+        let block = loc.ast_id.to_node(db.upcast());
+
+        let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
+        let mut item_tree = ctx.lower_block(&block);
+        item_tree.shrink_to_fit();
+        Arc::new(item_tree)
+    }
+
     /// Returns an iterator over all items located at the top level of the `HirFileId` this
     /// `ItemTree` was created from.
     pub fn top_level_items(&self) -> &[ModItem] {
@@ -178,13 +188,6 @@ impl ItemTree {
         self.data.get_or_insert_with(Box::default)
     }
 
-    fn block_item_tree(db: &dyn DefDatabase, block: BlockId) -> Arc<ItemTree> {
-        let loc = db.lookup_intern_block(block);
-        let block = loc.ast_id.to_node(db.upcast());
-        let ctx = lower::Ctx::new(db, loc.ast_id.file_id);
-        Arc::new(ctx.lower_block(&block))
-    }
-
     fn shrink_to_fit(&mut self) {
         if let Some(data) = &mut self.data {
             let ItemTreeData {
@@ -296,10 +299,12 @@ pub enum AttrOwner {
     Variant(Idx<Variant>),
     Field(Idx<Field>),
     Param(Idx<Param>),
+    TypeOrConstParamData(Idx<TypeOrConstParamData>),
+    LifetimeParamData(Idx<LifetimeParamData>),
 }
 
 macro_rules! from_attrs {
-    ( $( $var:ident($t:ty) ),+ ) => {
+    ( $( $var:ident($t:ty) ),+ $(,)? ) => {
         $(
             impl From<$t> for AttrOwner {
                 fn from(t: $t) -> AttrOwner {
@@ -310,7 +315,14 @@ macro_rules! from_attrs {
     };
 }
 
-from_attrs!(ModItem(ModItem), Variant(Idx<Variant>), Field(Idx<Field>), Param(Idx<Param>));
+from_attrs!(
+    ModItem(ModItem),
+    Variant(Idx<Variant>),
+    Field(Idx<Field>),
+    Param(Idx<Param>),
+    TypeOrConstParamData(Idx<TypeOrConstParamData>),
+    LifetimeParamData(Idx<LifetimeParamData>),
+);
 
 /// Trait implemented by all item nodes in the item tree.
 pub trait ItemTreeNode: Clone {
@@ -373,7 +385,7 @@ impl TreeId {
 
     pub(crate) fn item_tree(&self, db: &dyn DefDatabase) -> Arc<ItemTree> {
         match self.block {
-            Some(block) => ItemTree::block_item_tree(db, block),
+            Some(block) => db.block_item_tree_query(block),
             None => db.file_item_tree(self.file),
         }
     }
@@ -761,6 +773,19 @@ impl Use {
             lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree");
         source_map[index].clone()
     }
+    /// Maps a `UseTree` contained in this import back to its AST node.
+    pub fn use_tree_source_map(
+        &self,
+        db: &dyn DefDatabase,
+        file_id: HirFileId,
+    ) -> Arena<ast::UseTree> {
+        // Re-lower the AST item and get the source map.
+        // Note: The AST unwraps are fine, since if they fail we should have never obtained `index`.
+        let ast = InFile::new(file_id, self.ast_id).to_node(db.upcast());
+        let ast_use_tree = ast.use_tree().expect("missing `use_tree`");
+        let hygiene = Hygiene::new(db.upcast(), file_id);
+        lower::lower_use_tree(db, &hygiene, ast_use_tree).expect("failed to lower use tree").1
+    }
 }
 
 #[derive(Clone, Copy, Debug, Eq, PartialEq)]
@@ -785,7 +810,7 @@ impl UseTree {
     fn expand_impl(
         &self,
         prefix: Option<ModPath>,
-        cb: &mut dyn FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
+        cb: &mut impl FnMut(Idx<ast::UseTree>, ModPath, ImportKind, Option<ImportAlias>),
     ) {
         fn concat_mod_paths(
             prefix: Option<ModPath>,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
index 7b898e62dba..e4702c113b8 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/lower.rs
@@ -77,6 +77,9 @@ impl<'a> Ctx<'a> {
     }
 
     pub(super) fn lower_block(mut self, block: &ast::BlockExpr) -> ItemTree {
+        self.tree
+            .attrs
+            .insert(AttrOwner::TopLevel, RawAttrs::new(self.db.upcast(), block, self.hygiene()));
         self.tree.top_level = block
             .statements()
             .filter_map(|stmt| match stmt {
@@ -602,7 +605,21 @@ impl<'a> Ctx<'a> {
             generics.fill_bounds(&self.body_ctx, bounds, Either::Left(self_param));
         }
 
-        generics.fill(&self.body_ctx, node);
+        let add_param_attrs = |item, param| {
+            let attrs = RawAttrs::new(self.db.upcast(), &param, self.body_ctx.hygiene());
+            // This is identical to the body of `Ctx::add_attrs()` but we can't call that here
+            // because it requires `&mut self` and the call to `generics.fill()` below also
+            // references `self`.
+            match self.tree.attrs.entry(item) {
+                Entry::Occupied(mut entry) => {
+                    *entry.get_mut() = entry.get().merge(attrs);
+                }
+                Entry::Vacant(entry) => {
+                    entry.insert(attrs);
+                }
+            }
+        };
+        generics.fill(&self.body_ctx, node, add_param_attrs);
 
         generics.shrink_to_fit();
         Interned::new(generics)
@@ -763,7 +780,7 @@ impl UseTreeLowering<'_> {
     }
 }
 
-pub(super) fn lower_use_tree(
+pub(crate) fn lower_use_tree(
     db: &dyn DefDatabase,
     hygiene: &Hygiene,
     tree: ast::UseTree,
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
index da30830fe45..4b852dd613e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/pretty.rs
@@ -16,7 +16,7 @@ pub(super) fn print_item_tree(db: &dyn ExpandDatabase, tree: &ItemTree) -> Strin
     let mut p = Printer { db, tree, buf: String::new(), indent_level: 0, needs_indent: true };
 
     if let Some(attrs) = tree.attrs.get(&AttrOwner::TopLevel) {
-        p.print_attrs(attrs, true);
+        p.print_attrs(attrs, true, "\n");
     }
     p.blank();
 
@@ -84,22 +84,23 @@ impl Printer<'_> {
         }
     }
 
-    fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool) {
+    fn print_attrs(&mut self, attrs: &RawAttrs, inner: bool, separated_by: &str) {
         let inner = if inner { "!" } else { "" };
         for attr in &**attrs {
-            wln!(
+            w!(
                 self,
-                "#{}[{}{}]",
+                "#{}[{}{}]{}",
                 inner,
                 attr.path.display(self.db),
                 attr.input.as_ref().map(|it| it.to_string()).unwrap_or_default(),
+                separated_by,
             );
         }
     }
 
-    fn print_attrs_of(&mut self, of: impl Into<AttrOwner>) {
+    fn print_attrs_of(&mut self, of: impl Into<AttrOwner>, separated_by: &str) {
         if let Some(attrs) = self.tree.attrs.get(&of.into()) {
-            self.print_attrs(attrs, false);
+            self.print_attrs(attrs, false, separated_by);
         }
     }
 
@@ -118,7 +119,7 @@ impl Printer<'_> {
                 self.indented(|this| {
                     for field in fields.clone() {
                         let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
-                        this.print_attrs_of(field);
+                        this.print_attrs_of(field, "\n");
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db));
                         this.print_type_ref(type_ref);
@@ -132,7 +133,7 @@ impl Printer<'_> {
                 self.indented(|this| {
                     for field in fields.clone() {
                         let Field { visibility, name, type_ref, ast_id: _ } = &this.tree[field];
-                        this.print_attrs_of(field);
+                        this.print_attrs_of(field, "\n");
                         this.print_visibility(*visibility);
                         w!(this, "{}: ", name.display(self.db));
                         this.print_type_ref(type_ref);
@@ -195,7 +196,7 @@ impl Printer<'_> {
     }
 
     fn print_mod_item(&mut self, item: ModItem) {
-        self.print_attrs_of(item);
+        self.print_attrs_of(item, "\n");
 
         match item {
             ModItem::Use(it) => {
@@ -261,7 +262,7 @@ impl Printer<'_> {
                 if !params.is_empty() {
                     self.indented(|this| {
                         for param in params.clone() {
-                            this.print_attrs_of(param);
+                            this.print_attrs_of(param, "\n");
                             match &this.tree[param] {
                                 Param::Normal(ty) => {
                                     if flags.contains(FnFlags::HAS_SELF_PARAM) {
@@ -319,7 +320,7 @@ impl Printer<'_> {
                 self.indented(|this| {
                     for variant in variants.clone() {
                         let Variant { name, fields, ast_id: _ } = &this.tree[variant];
-                        this.print_attrs_of(variant);
+                        this.print_attrs_of(variant, "\n");
                         w!(this, "{}", name.display(self.db));
                         this.print_fields(fields);
                         wln!(this, ",");
@@ -484,11 +485,12 @@ impl Printer<'_> {
 
         w!(self, "<");
         let mut first = true;
-        for (_, lt) in params.lifetimes.iter() {
+        for (idx, lt) in params.lifetimes.iter() {
             if !first {
                 w!(self, ", ");
             }
             first = false;
+            self.print_attrs_of(idx, " ");
             w!(self, "{}", lt.name.display(self.db));
         }
         for (idx, x) in params.type_or_consts.iter() {
@@ -496,6 +498,7 @@ impl Printer<'_> {
                 w!(self, ", ");
             }
             first = false;
+            self.print_attrs_of(idx, " ");
             match x {
                 TypeOrConstParamData::TypeParamData(ty) => match &ty.name {
                     Some(name) => w!(self, "{}", name.display(self.db)),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
index 5ded4b6b273..4180f817209 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/item_tree/tests.rs
@@ -358,3 +358,15 @@ trait Tr<'a, T: 'a>: Super where Self: for<'a> Tr<'a, T> {}
         "#]],
     )
 }
+
+#[test]
+fn generics_with_attributes() {
+    check(
+        r#"
+struct S<#[cfg(never)] T>;
+        "#,
+        expect![[r#"
+            pub(self) struct S<#[cfg(never)] T>;
+        "#]],
+    )
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
index 1901db8a0f9..3f87fe62b83 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/lib.rs
@@ -109,6 +109,17 @@ impl CrateRootModuleId {
     }
 }
 
+impl PartialEq<ModuleId> for CrateRootModuleId {
+    fn eq(&self, other: &ModuleId) -> bool {
+        other.block.is_none() && other.local_id == DefMap::ROOT && self.krate == other.krate
+    }
+}
+impl PartialEq<CrateRootModuleId> for ModuleId {
+    fn eq(&self, other: &CrateRootModuleId) -> bool {
+        other == self
+    }
+}
+
 impl From<CrateRootModuleId> for ModuleId {
     fn from(CrateRootModuleId { krate }: CrateRootModuleId) -> Self {
         ModuleId { krate, block: None, local_id: DefMap::ROOT }
@@ -854,14 +865,36 @@ impl_from!(
     ConstId,
     FunctionId,
     TraitId,
+    TraitAliasId,
     TypeAliasId,
     MacroId(Macro2Id, MacroRulesId, ProcMacroId),
     ImplId,
     GenericParamId,
-    ExternCrateId
+    ExternCrateId,
+    UseId
     for AttrDefId
 );
 
+impl TryFrom<ModuleDefId> for AttrDefId {
+    type Error = ();
+
+    fn try_from(value: ModuleDefId) -> Result<Self, Self::Error> {
+        match value {
+            ModuleDefId::ModuleId(it) => Ok(it.into()),
+            ModuleDefId::FunctionId(it) => Ok(it.into()),
+            ModuleDefId::AdtId(it) => Ok(it.into()),
+            ModuleDefId::EnumVariantId(it) => Ok(it.into()),
+            ModuleDefId::ConstId(it) => Ok(it.into()),
+            ModuleDefId::StaticId(it) => Ok(it.into()),
+            ModuleDefId::TraitId(it) => Ok(it.into()),
+            ModuleDefId::TypeAliasId(it) => Ok(it.into()),
+            ModuleDefId::TraitAliasId(id) => Ok(id.into()),
+            ModuleDefId::MacroId(id) => Ok(id.into()),
+            ModuleDefId::BuiltinType(_) => Err(()),
+        }
+    }
+}
+
 impl From<ItemContainerId> for AttrDefId {
     fn from(acid: ItemContainerId) -> Self {
         match acid {
@@ -872,6 +905,15 @@ impl From<ItemContainerId> for AttrDefId {
         }
     }
 }
+impl From<AssocItemId> for AttrDefId {
+    fn from(assoc: AssocItemId) -> Self {
+        match assoc {
+            AssocItemId::FunctionId(it) => AttrDefId::FunctionId(it),
+            AssocItemId::ConstId(it) => AttrDefId::ConstId(it),
+            AssocItemId::TypeAliasId(it) => AttrDefId::TypeAliasId(it),
+        }
+    }
+}
 
 #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
 pub enum VariantId {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
index 1250cbb742c..b232651db96 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/builtin_fn_macro.rs
@@ -238,7 +238,7 @@ fn main() {
     /* error: expected expression */;
     /* error: expected expression, expected COMMA */;
     /* error: expected expression */::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(), ::core::fmt::Display::fmt), ]);
-    /* error: expected expression, expected expression */;
+    /* error: expected expression, expected R_PAREN */;
     ::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(5), ::core::fmt::Display::fmt), ]);
 }
 "##]],
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
index d8e4a4dcc7c..97554f93f1c 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mbe/regression.rs
@@ -909,3 +909,68 @@ macro_rules! with_std {
 "##]],
     )
 }
+
+#[test]
+fn eager_regression_15403() {
+    check(
+        r#"
+#[rustc_builtin_macro]
+#[macro_export]
+macro_rules! format_args {}
+
+fn main() {
+    format_args /* +errors */ !("{}", line.1.);
+}
+
+"#,
+        expect![[r##"
+#[rustc_builtin_macro]
+#[macro_export]
+macro_rules! format_args {}
+
+fn main() {
+    /* error: expected field name or number *//* parse error: expected field name or number */
+::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(line.1.), ::core::fmt::Display::fmt), ]);
+}
+
+"##]],
+    );
+}
+
+#[test]
+fn eager_regression_154032() {
+    check(
+        r#"
+#[rustc_builtin_macro]
+#[macro_export]
+macro_rules! format_args {}
+
+fn main() {
+    format_args /* +errors */ !("{}", &[0 2]);
+}
+
+"#,
+        expect![[r##"
+#[rustc_builtin_macro]
+#[macro_export]
+macro_rules! format_args {}
+
+fn main() {
+    /* error: expected COMMA, expected R_BRACK, expected COMMA, expected COMMA, expected expression, expected R_PAREN *//* parse error: expected COMMA */
+/* parse error: expected R_BRACK */
+/* parse error: expected COMMA */
+/* parse error: expected COMMA */
+/* parse error: expected expression */
+/* parse error: expected R_PAREN */
+/* parse error: expected R_PAREN */
+/* parse error: expected expression, item or let statement */
+/* parse error: expected expression, item or let statement */
+/* parse error: expected expression, item or let statement */
+/* parse error: expected expression, item or let statement */
+/* parse error: expected expression, item or let statement */
+::core::fmt::Arguments::new_v1(&["", ], &[::core::fmt::ArgumentV1::new(&(&[0 2]), ::core::fmt::Display::fmt), ]);
+}
+
+"##]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
index 7a87e61c693..8adced4e082 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/macro_expansion_tests/mod.rs
@@ -131,7 +131,7 @@ pub fn identity_when_valid(_attr: TokenStream, item: TokenStream) -> TokenStream
             .as_call_id_with_errors(&db, krate, |path| {
                 resolver
                     .resolve_path_as_macro(&db, &path, Some(MacroSubNs::Bang))
-                    .map(|it| macro_id_to_def_id(&db, it))
+                    .map(|(it, _)| macro_id_to_def_id(&db, it))
             })
             .unwrap();
         let macro_call_id = res.value.unwrap();
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
index 86818ce26dd..f2110410980 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres.rs
@@ -60,7 +60,7 @@ mod tests;
 use std::{cmp::Ord, ops::Deref};
 
 use base_db::{CrateId, Edition, FileId, ProcMacroKind};
-use hir_expand::{name::Name, HirFileId, InFile, MacroCallId, MacroDefId};
+use hir_expand::{ast_id_map::FileAstId, name::Name, HirFileId, InFile, MacroCallId, MacroDefId};
 use itertools::Itertools;
 use la_arena::Arena;
 use profile::Count;
@@ -77,8 +77,8 @@ use crate::{
     path::ModPath,
     per_ns::PerNs,
     visibility::Visibility,
-    AstId, BlockId, BlockLoc, CrateRootModuleId, FunctionId, LocalModuleId, Lookup, MacroExpander,
-    MacroId, ModuleId, ProcMacroId,
+    AstId, BlockId, BlockLoc, CrateRootModuleId, ExternCrateId, FunctionId, LocalModuleId, Lookup,
+    MacroExpander, MacroId, ModuleId, ProcMacroId, UseId,
 };
 
 /// Contains the results of (early) name resolution.
@@ -105,10 +105,11 @@ pub struct DefMap {
     /// The prelude is empty for non-block DefMaps (unless `#[prelude_import]` was used,
     /// but that attribute is nightly and when used in a block, it affects resolution globally
     /// so we aren't handling this correctly anyways).
-    prelude: Option<ModuleId>,
+    prelude: Option<(ModuleId, Option<UseId>)>,
     /// `macro_use` prelude that contains macros from `#[macro_use]`'d external crates. Note that
     /// this contains all kinds of macro, not just `macro_rules!` macro.
-    macro_use_prelude: FxHashMap<Name, MacroId>,
+    /// ExternCrateId being None implies it being imported from the general prelude import.
+    macro_use_prelude: FxHashMap<Name, (MacroId, Option<ExternCrateId>)>,
 
     /// Tracks which custom derives are in scope for an item, to allow resolution of derive helper
     /// attributes.
@@ -125,7 +126,7 @@ pub struct DefMap {
 #[derive(Clone, Debug, PartialEq, Eq)]
 struct DefMapCrateData {
     /// The extern prelude which contains all root modules of external crates that are in scope.
-    extern_prelude: FxHashMap<Name, CrateRootModuleId>,
+    extern_prelude: FxHashMap<Name, (CrateRootModuleId, Option<ExternCrateId>)>,
 
     /// Side table for resolving derive helpers.
     exported_derives: FxHashMap<MacroDefId, Box<[Name]>>,
@@ -217,16 +218,17 @@ pub enum ModuleOrigin {
     /// Note that non-inline modules, by definition, live inside non-macro file.
     File {
         is_mod_rs: bool,
-        declaration: AstId<ast::Module>,
+        declaration: FileAstId<ast::Module>,
         declaration_tree_id: ItemTreeId<Mod>,
         definition: FileId,
     },
     Inline {
         definition_tree_id: ItemTreeId<Mod>,
-        definition: AstId<ast::Module>,
+        definition: FileAstId<ast::Module>,
     },
     /// Pseudo-module introduced by a block scope (contains only inner items).
     BlockExpr {
+        id: BlockId,
         block: AstId<ast::BlockExpr>,
     },
 }
@@ -234,8 +236,12 @@ pub enum ModuleOrigin {
 impl ModuleOrigin {
     pub fn declaration(&self) -> Option<AstId<ast::Module>> {
         match self {
-            ModuleOrigin::File { declaration: module, .. }
-            | ModuleOrigin::Inline { definition: module, .. } => Some(*module),
+            &ModuleOrigin::File { declaration, declaration_tree_id, .. } => {
+                Some(AstId::new(declaration_tree_id.file_id(), declaration))
+            }
+            &ModuleOrigin::Inline { definition, definition_tree_id } => {
+                Some(AstId::new(definition_tree_id.file_id(), definition))
+            }
             ModuleOrigin::CrateRoot { .. } | ModuleOrigin::BlockExpr { .. } => None,
         }
     }
@@ -260,16 +266,17 @@ impl ModuleOrigin {
     /// That is, a file or a `mod foo {}` with items.
     fn definition_source(&self, db: &dyn DefDatabase) -> InFile<ModuleSource> {
         match self {
-            ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
-                let file_id = *definition;
-                let sf = db.parse(file_id).tree();
-                InFile::new(file_id.into(), ModuleSource::SourceFile(sf))
+            &ModuleOrigin::File { definition, .. } | &ModuleOrigin::CrateRoot { definition } => {
+                let sf = db.parse(definition).tree();
+                InFile::new(definition.into(), ModuleSource::SourceFile(sf))
             }
-            ModuleOrigin::Inline { definition, .. } => InFile::new(
-                definition.file_id,
-                ModuleSource::Module(definition.to_node(db.upcast())),
+            &ModuleOrigin::Inline { definition, definition_tree_id } => InFile::new(
+                definition_tree_id.file_id(),
+                ModuleSource::Module(
+                    AstId::new(definition_tree_id.file_id(), definition).to_node(db.upcast()),
+                ),
             ),
-            ModuleOrigin::BlockExpr { block } => {
+            ModuleOrigin::BlockExpr { block, .. } => {
                 InFile::new(block.file_id, ModuleSource::BlockExpr(block.to_node(db.upcast())))
             }
         }
@@ -314,9 +321,7 @@ impl DefMap {
     }
 
     pub(crate) fn block_def_map_query(db: &dyn DefDatabase, block_id: BlockId) -> Arc<DefMap> {
-        let block: BlockLoc = db.lookup_intern_block(block_id);
-
-        let tree_id = TreeId::new(block.ast_id.file_id, Some(block_id));
+        let block: BlockLoc = block_id.lookup(db);
 
         let parent_map = block.module.def_map(db);
         let krate = block.module.krate;
@@ -325,8 +330,10 @@ impl DefMap {
         // modules declared by blocks with items. At the moment, we don't use
         // this visibility for anything outside IDE, so that's probably OK.
         let visibility = Visibility::Module(ModuleId { krate, local_id, block: None });
-        let module_data =
-            ModuleData::new(ModuleOrigin::BlockExpr { block: block.ast_id }, visibility);
+        let module_data = ModuleData::new(
+            ModuleOrigin::BlockExpr { block: block.ast_id, id: block_id },
+            visibility,
+        );
 
         let mut def_map = DefMap::empty(krate, parent_map.data.edition, module_data);
         def_map.data = parent_map.data.clone();
@@ -338,7 +345,8 @@ impl DefMap {
             },
         });
 
-        let def_map = collector::collect_defs(db, def_map, tree_id);
+        let def_map =
+            collector::collect_defs(db, def_map, TreeId::new(block.ast_id.file_id, Some(block_id)));
         Arc::new(def_map)
     }
 
@@ -427,15 +435,19 @@ impl DefMap {
         self.block.map(|block| block.block)
     }
 
-    pub(crate) fn prelude(&self) -> Option<ModuleId> {
+    pub(crate) fn prelude(&self) -> Option<(ModuleId, Option<UseId>)> {
         self.prelude
     }
 
-    pub(crate) fn extern_prelude(&self) -> impl Iterator<Item = (&Name, ModuleId)> + '_ {
-        self.data.extern_prelude.iter().map(|(name, &def)| (name, def.into()))
+    pub(crate) fn extern_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (CrateRootModuleId, Option<ExternCrateId>))> + '_ {
+        self.data.extern_prelude.iter().map(|(name, &def)| (name, def))
     }
 
-    pub(crate) fn macro_use_prelude(&self) -> impl Iterator<Item = (&Name, MacroId)> + '_ {
+    pub(crate) fn macro_use_prelude(
+        &self,
+    ) -> impl Iterator<Item = (&Name, (MacroId, Option<ExternCrateId>))> + '_ {
         self.macro_use_prelude.iter().map(|(name, &def)| (name, def))
     }
 
@@ -638,8 +650,8 @@ impl ModuleData {
             ModuleOrigin::File { definition, .. } | ModuleOrigin::CrateRoot { definition } => {
                 definition.into()
             }
-            ModuleOrigin::Inline { definition, .. } => definition.file_id,
-            ModuleOrigin::BlockExpr { block } => block.file_id,
+            ModuleOrigin::Inline { definition_tree_id, .. } => definition_tree_id.file_id(),
+            ModuleOrigin::BlockExpr { block, .. } => block.file_id,
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
index eef54fc492e..e9e71a8747f 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/collector.rs
@@ -33,7 +33,7 @@ use crate::{
     attr_macro_as_call_id,
     db::DefDatabase,
     derive_macro_as_call_id,
-    item_scope::{ImportType, PerNsGlobImports},
+    item_scope::{ImportId, ImportOrExternCrate, ImportType, PerNsGlobImports},
     item_tree::{
         self, ExternCrate, Fields, FileItemTreeId, ImportKind, ItemTree, ItemTreeId, ItemTreeNode,
         MacroCall, MacroDef, MacroRules, Mod, ModItem, ModKind, TreeId,
@@ -52,10 +52,10 @@ use crate::{
     tt,
     visibility::{RawVisibility, Visibility},
     AdtId, AstId, AstIdWithPath, ConstLoc, CrateRootModuleId, EnumLoc, EnumVariantId,
-    ExternBlockLoc, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern, ItemContainerId,
-    LocalModuleId, Macro2Id, Macro2Loc, MacroExpander, MacroId, MacroRulesId, MacroRulesLoc,
-    ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc, StructLoc, TraitAliasLoc,
-    TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseLoc,
+    ExternBlockLoc, ExternCrateId, ExternCrateLoc, FunctionId, FunctionLoc, ImplLoc, Intern,
+    ItemContainerId, LocalModuleId, Lookup, Macro2Id, Macro2Loc, MacroExpander, MacroId,
+    MacroRulesId, MacroRulesLoc, ModuleDefId, ModuleId, ProcMacroId, ProcMacroLoc, StaticLoc,
+    StructLoc, TraitAliasLoc, TraitLoc, TypeAliasLoc, UnionLoc, UnresolvedMacro, UseId, UseLoc,
 };
 
 static GLOB_RECURSION_LIMIT: Limit = Limit::new(100);
@@ -146,8 +146,8 @@ impl PartialResolvedImport {
 
 #[derive(Clone, Debug, Eq, PartialEq)]
 enum ImportSource {
-    Use { id: ItemTreeId<item_tree::Use>, use_tree: Idx<ast::UseTree> },
-    ExternCrate(ItemTreeId<item_tree::ExternCrate>),
+    Use { use_tree: Idx<ast::UseTree>, id: UseId, is_prelude: bool, kind: ImportKind },
+    ExternCrate { id: ExternCrateId },
 }
 
 #[derive(Debug, Eq, PartialEq)]
@@ -155,54 +155,41 @@ struct Import {
     path: ModPath,
     alias: Option<ImportAlias>,
     visibility: RawVisibility,
-    kind: ImportKind,
     source: ImportSource,
-    is_prelude: bool,
-    is_macro_use: bool,
 }
 
 impl Import {
     fn from_use(
-        db: &dyn DefDatabase,
-        krate: CrateId,
         tree: &ItemTree,
-        id: ItemTreeId<item_tree::Use>,
+        item_tree_id: ItemTreeId<item_tree::Use>,
+        id: UseId,
+        is_prelude: bool,
         mut cb: impl FnMut(Self),
     ) {
-        let it = &tree[id.value];
-        let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
+        let it = &tree[item_tree_id.value];
         let visibility = &tree[it.visibility];
-        let is_prelude = attrs.by_key("prelude_import").exists();
         it.use_tree.expand(|idx, path, kind, alias| {
             cb(Self {
                 path,
                 alias,
                 visibility: visibility.clone(),
-                kind,
-                is_prelude,
-                is_macro_use: false,
-                source: ImportSource::Use { id, use_tree: idx },
+                source: ImportSource::Use { use_tree: idx, id, is_prelude, kind },
             });
         });
     }
 
     fn from_extern_crate(
-        db: &dyn DefDatabase,
-        krate: CrateId,
         tree: &ItemTree,
-        id: ItemTreeId<item_tree::ExternCrate>,
+        item_tree_id: ItemTreeId<item_tree::ExternCrate>,
+        id: ExternCrateId,
     ) -> Self {
-        let it = &tree[id.value];
-        let attrs = &tree.attrs(db, krate, ModItem::from(id.value).into());
+        let it = &tree[item_tree_id.value];
         let visibility = &tree[it.visibility];
         Self {
             path: ModPath::from_segments(PathKind::Plain, iter::once(it.name.clone())),
             alias: it.alias.clone(),
             visibility: visibility.clone(),
-            kind: ImportKind::Plain,
-            is_prelude: false,
-            is_macro_use: attrs.by_key("macro_use").exists(),
-            source: ImportSource::ExternCrate(id),
+            source: ImportSource::ExternCrate { id },
         }
     }
 }
@@ -235,7 +222,7 @@ struct DefCollector<'a> {
     db: &'a dyn DefDatabase,
     def_map: DefMap,
     deps: FxHashMap<Name, Dependency>,
-    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility)>>,
+    glob_imports: FxHashMap<LocalModuleId, Vec<(LocalModuleId, Visibility, UseId)>>,
     unresolved_imports: Vec<ImportDirective>,
     indeterminate_imports: Vec<ImportDirective>,
     unresolved_macros: Vec<MacroDirective>,
@@ -280,7 +267,7 @@ impl DefCollector<'_> {
             if dep.is_prelude() {
                 crate_data
                     .extern_prelude
-                    .insert(name.clone(), CrateRootModuleId { krate: dep.crate_id });
+                    .insert(name.clone(), (CrateRootModuleId { krate: dep.crate_id }, None));
             }
         }
 
@@ -556,8 +543,12 @@ impl DefCollector<'_> {
             self.def_map.resolve_path(self.db, DefMap::ROOT, &path, BuiltinShadowMode::Other, None);
 
         match per_ns.types {
-            Some((ModuleDefId::ModuleId(m), _)) => {
-                self.def_map.prelude = Some(m);
+            Some((ModuleDefId::ModuleId(m), _, import)) => {
+                // FIXME: This should specifically look for a glob import somehow and record that here
+                self.def_map.prelude = Some((
+                    m,
+                    import.and_then(ImportOrExternCrate::into_import).map(|it| it.import),
+                ));
             }
             types => {
                 tracing::debug!(
@@ -657,9 +648,9 @@ impl DefCollector<'_> {
             self.def_map.modules[module_id].scope.declare(macro_.into());
             self.update(
                 module_id,
-                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+                &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
                 Visibility::Public,
-                ImportType::Named,
+                None,
             );
         }
     }
@@ -693,9 +684,9 @@ impl DefCollector<'_> {
         self.def_map.modules[module_id].scope.declare(macro_.into());
         self.update(
             module_id,
-            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
             vis,
-            ImportType::Named,
+            None,
         );
     }
 
@@ -708,9 +699,9 @@ impl DefCollector<'_> {
         self.def_map.modules[module_id].scope.declare(macro_.into());
         self.update(
             module_id,
-            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public))],
+            &[(Some(name), PerNs::macros(macro_.into(), Visibility::Public, None))],
             Visibility::Public,
-            ImportType::Named,
+            None,
         );
     }
 
@@ -720,21 +711,29 @@ impl DefCollector<'_> {
     /// Exported macros are just all macros in the root module scope.
     /// Note that it contains not only all `#[macro_export]` macros, but also all aliases
     /// created by `use` in the root module, ignoring the visibility of `use`.
-    fn import_macros_from_extern_crate(&mut self, krate: CrateId, names: Option<Vec<Name>>) {
+    fn import_macros_from_extern_crate(
+        &mut self,
+        krate: CrateId,
+        names: Option<Vec<Name>>,
+        extern_crate: Option<ExternCrateId>,
+    ) {
         let def_map = self.db.crate_def_map(krate);
         // `#[macro_use]` brings macros into macro_use prelude. Yes, even non-`macro_rules!`
         // macros.
         let root_scope = &def_map[DefMap::ROOT].scope;
-        if let Some(names) = names {
-            for name in names {
-                // FIXME: Report diagnostic on 404.
-                if let Some(def) = root_scope.get(&name).take_macros() {
-                    self.def_map.macro_use_prelude.insert(name, def);
+        match names {
+            Some(names) => {
+                for name in names {
+                    // FIXME: Report diagnostic on 404.
+                    if let Some(def) = root_scope.get(&name).take_macros() {
+                        self.def_map.macro_use_prelude.insert(name, (def, extern_crate));
+                    }
                 }
             }
-        } else {
-            for (name, def) in root_scope.macros() {
-                self.def_map.macro_use_prelude.insert(name.clone(), def);
+            None => {
+                for (name, def) in root_scope.macros() {
+                    self.def_map.macro_use_prelude.insert(name.clone(), (def, extern_crate));
+                }
             }
         }
     }
@@ -771,48 +770,53 @@ impl DefCollector<'_> {
         let _p = profile::span("resolve_import")
             .detail(|| format!("{}", import.path.display(self.db.upcast())));
         tracing::debug!("resolving import: {:?} ({:?})", import, self.def_map.data.edition);
-        if matches!(import.source, ImportSource::ExternCrate { .. }) {
-            let name = import
-                .path
-                .as_ident()
-                .expect("extern crate should have been desugared to one-element path");
-
-            let res = self.resolve_extern_crate(name);
-
-            match res {
-                Some(res) => {
-                    PartialResolvedImport::Resolved(PerNs::types(res.into(), Visibility::Public))
+        match import.source {
+            ImportSource::ExternCrate { .. } => {
+                let name = import
+                    .path
+                    .as_ident()
+                    .expect("extern crate should have been desugared to one-element path");
+
+                let res = self.resolve_extern_crate(name);
+
+                match res {
+                    Some(res) => PartialResolvedImport::Resolved(PerNs::types(
+                        res.into(),
+                        Visibility::Public,
+                        None,
+                    )),
+                    None => PartialResolvedImport::Unresolved,
                 }
-                None => PartialResolvedImport::Unresolved,
             }
-        } else {
-            let res = self.def_map.resolve_path_fp_with_macro(
-                self.db,
-                ResolveMode::Import,
-                module_id,
-                &import.path,
-                BuiltinShadowMode::Module,
-                None, // An import may resolve to any kind of macro.
-            );
+            ImportSource::Use { .. } => {
+                let res = self.def_map.resolve_path_fp_with_macro(
+                    self.db,
+                    ResolveMode::Import,
+                    module_id,
+                    &import.path,
+                    BuiltinShadowMode::Module,
+                    None, // An import may resolve to any kind of macro.
+                );
 
-            let def = res.resolved_def;
-            if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
-                return PartialResolvedImport::Unresolved;
-            }
+                let def = res.resolved_def;
+                if res.reached_fixedpoint == ReachedFixedPoint::No || def.is_none() {
+                    return PartialResolvedImport::Unresolved;
+                }
 
-            if let Some(krate) = res.krate {
-                if krate != self.def_map.krate {
-                    return PartialResolvedImport::Resolved(
-                        def.filter_visibility(|v| matches!(v, Visibility::Public)),
-                    );
+                if let Some(krate) = res.krate {
+                    if krate != self.def_map.krate {
+                        return PartialResolvedImport::Resolved(
+                            def.filter_visibility(|v| matches!(v, Visibility::Public)),
+                        );
+                    }
                 }
-            }
 
-            // Check whether all namespaces are resolved.
-            if def.is_full() {
-                PartialResolvedImport::Resolved(def)
-            } else {
-                PartialResolvedImport::Indeterminate(def)
+                // Check whether all namespaces are resolved.
+                if def.is_full() {
+                    PartialResolvedImport::Resolved(def)
+                } else {
+                    PartialResolvedImport::Indeterminate(def)
+                }
             }
         }
     }
@@ -837,8 +841,9 @@ impl DefCollector<'_> {
             .resolve_visibility(self.db, module_id, &directive.import.visibility, false)
             .unwrap_or(Visibility::Public);
 
-        match import.kind {
-            ImportKind::Plain | ImportKind::TypeOnly => {
+        match import.source {
+            ImportSource::ExternCrate { .. }
+            | ImportSource::Use { kind: ImportKind::Plain | ImportKind::TypeOnly, .. } => {
                 let name = match &import.alias {
                     Some(ImportAlias::Alias(name)) => Some(name),
                     Some(ImportAlias::Underscore) => None,
@@ -851,40 +856,44 @@ impl DefCollector<'_> {
                     },
                 };
 
-                if import.kind == ImportKind::TypeOnly {
-                    def.values = None;
-                    def.macros = None;
-                }
-
-                tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
-
-                // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
-                if matches!(import.source, ImportSource::ExternCrate { .. })
-                    && self.def_map.block.is_none()
-                    && module_id == DefMap::ROOT
-                {
-                    if let (Some(ModuleDefId::ModuleId(def)), Some(name)) = (def.take_types(), name)
-                    {
-                        if let Ok(def) = def.try_into() {
-                            Arc::get_mut(&mut self.def_map.data)
-                                .unwrap()
-                                .extern_prelude
-                                .insert(name.clone(), def);
+                let imp = match import.source {
+                    // extern crates in the crate root are special-cased to insert entries into the extern prelude: rust-lang/rust#54658
+                    ImportSource::ExternCrate { id, .. } => {
+                        if self.def_map.block.is_none() && module_id == DefMap::ROOT {
+                            if let (Some(ModuleDefId::ModuleId(def)), Some(name)) =
+                                (def.take_types(), name)
+                            {
+                                if let Ok(def) = def.try_into() {
+                                    Arc::get_mut(&mut self.def_map.data)
+                                        .unwrap()
+                                        .extern_prelude
+                                        .insert(name.clone(), (def, Some(id)));
+                                }
+                            }
                         }
+                        ImportType::ExternCrate(id)
                     }
-                }
+                    ImportSource::Use { kind, id, use_tree, .. } => {
+                        if kind == ImportKind::TypeOnly {
+                            def.values = None;
+                            def.macros = None;
+                        }
+                        ImportType::Import(ImportId { import: id, idx: use_tree })
+                    }
+                };
+                tracing::debug!("resolved import {:?} ({:?}) to {:?}", name, import, def);
 
-                self.update(module_id, &[(name.cloned(), def)], vis, ImportType::Named);
+                self.update(module_id, &[(name.cloned(), def)], vis, Some(imp));
             }
-            ImportKind::Glob => {
+            ImportSource::Use { kind: ImportKind::Glob, id, .. } => {
                 tracing::debug!("glob import: {:?}", import);
                 match def.take_types() {
                     Some(ModuleDefId::ModuleId(m)) => {
-                        if import.is_prelude {
+                        if let ImportSource::Use { id, is_prelude: true, .. } = import.source {
                             // Note: This dodgily overrides the injected prelude. The rustc
                             // implementation seems to work the same though.
                             cov_mark::hit!(std_prelude);
-                            self.def_map.prelude = Some(m);
+                            self.def_map.prelude = Some((m, Some(id)));
                         } else if m.krate != self.def_map.krate {
                             cov_mark::hit!(glob_across_crates);
                             // glob import from other crate => we can just import everything once
@@ -901,7 +910,7 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, ImportType::Glob);
+                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
                         } else {
                             // glob import from same crate => we do an initial
                             // import, and then need to propagate any further
@@ -933,11 +942,11 @@ impl DefCollector<'_> {
                                 .filter(|(_, res)| !res.is_none())
                                 .collect::<Vec<_>>();
 
-                            self.update(module_id, &items, vis, ImportType::Glob);
+                            self.update(module_id, &items, vis, Some(ImportType::Glob(id)));
                             // record the glob import in case we add further items
                             let glob = self.glob_imports.entry(m.local_id).or_default();
-                            if !glob.iter().any(|(mid, _)| *mid == module_id) {
-                                glob.push((module_id, vis));
+                            if !glob.iter().any(|(mid, _, _)| *mid == module_id) {
+                                glob.push((module_id, vis, id));
                             }
                         }
                     }
@@ -959,11 +968,11 @@ impl DefCollector<'_> {
                             .map(|(local_id, variant_data)| {
                                 let name = variant_data.name.clone();
                                 let variant = EnumVariantId { parent: e, local_id };
-                                let res = PerNs::both(variant.into(), variant.into(), vis);
+                                let res = PerNs::both(variant.into(), variant.into(), vis, None);
                                 (Some(name), res)
                             })
                             .collect::<Vec<_>>();
-                        self.update(module_id, &resolutions, vis, ImportType::Glob);
+                        self.update(module_id, &resolutions, vis, Some(ImportType::Glob(id)));
                     }
                     Some(d) => {
                         tracing::debug!("glob import {:?} from non-module/enum {:?}", import, d);
@@ -983,10 +992,10 @@ impl DefCollector<'_> {
         resolutions: &[(Option<Name>, PerNs)],
         // Visibility this import will have
         vis: Visibility,
-        import_type: ImportType,
+        import: Option<ImportType>,
     ) {
         self.db.unwind_if_cancelled();
-        self.update_recursive(module_id, resolutions, vis, import_type, 0)
+        self.update_recursive(module_id, resolutions, vis, import, 0)
     }
 
     fn update_recursive(
@@ -997,7 +1006,7 @@ impl DefCollector<'_> {
         // All resolutions are imported with this visibility; the visibilities in
         // the `PerNs` values are ignored and overwritten
         vis: Visibility,
-        import_type: ImportType,
+        import: Option<ImportType>,
         depth: usize,
     ) {
         if GLOB_RECURSION_LIMIT.check(depth).is_err() {
@@ -1014,7 +1023,7 @@ impl DefCollector<'_> {
                         &mut self.from_glob_import,
                         (module_id, name.clone()),
                         res.with_visibility(vis),
-                        import_type,
+                        import,
                     );
                 }
                 None => {
@@ -1059,7 +1068,7 @@ impl DefCollector<'_> {
             .get(&module_id)
             .into_iter()
             .flatten()
-            .filter(|(glob_importing_module, _)| {
+            .filter(|(glob_importing_module, _, _)| {
                 // we know all resolutions have the same visibility (`vis`), so we
                 // just need to check that once
                 vis.is_visible_from_def_map(self.db, &self.def_map, *glob_importing_module)
@@ -1067,12 +1076,12 @@ impl DefCollector<'_> {
             .cloned()
             .collect::<Vec<_>>();
 
-        for (glob_importing_module, glob_import_vis) in glob_imports {
+        for (glob_importing_module, glob_import_vis, use_) in glob_imports {
             self.update_recursive(
                 glob_importing_module,
                 resolutions,
                 glob_import_vis,
-                ImportType::Glob,
+                Some(ImportType::Glob(use_)),
                 depth + 1,
             );
         }
@@ -1460,31 +1469,34 @@ impl DefCollector<'_> {
         // heuristic, but it works in practice.
         let mut diagnosed_extern_crates = FxHashSet::default();
         for directive in &self.unresolved_imports {
-            if let ImportSource::ExternCrate(krate) = directive.import.source {
-                let item_tree = krate.item_tree(self.db);
-                let extern_crate = &item_tree[krate.value];
+            if let ImportSource::ExternCrate { id } = directive.import.source {
+                let item_tree_id = id.lookup(self.db).id;
+                let item_tree = item_tree_id.item_tree(self.db);
+                let extern_crate = &item_tree[item_tree_id.value];
 
                 diagnosed_extern_crates.insert(extern_crate.name.clone());
 
                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_extern_crate(
                     directive.module_id,
-                    InFile::new(krate.file_id(), extern_crate.ast_id),
+                    InFile::new(item_tree_id.file_id(), extern_crate.ast_id),
                 ));
             }
         }
 
         for directive in &self.unresolved_imports {
-            if let ImportSource::Use { id: import, use_tree } = directive.import.source {
+            if let ImportSource::Use { use_tree, id, is_prelude: _, kind: _ } =
+                directive.import.source
+            {
                 if matches!(
                     (directive.import.path.segments().first(), &directive.import.path.kind),
                     (Some(krate), PathKind::Plain | PathKind::Abs) if diagnosed_extern_crates.contains(krate)
                 ) {
                     continue;
                 }
-
+                let item_tree_id = id.lookup(self.db).id;
                 self.def_map.diagnostics.push(DefDiagnostic::unresolved_import(
                     directive.module_id,
-                    import,
+                    item_tree_id,
                     use_tree,
                 ));
             }
@@ -1519,72 +1531,66 @@ impl ModCollector<'_, '_> {
         self.def_collector.mod_dirs.insert(self.module_id, self.mod_dir.clone());
 
         // Prelude module is always considered to be `#[macro_use]`.
-        if let Some(prelude_module) = self.def_collector.def_map.prelude {
+        if let Some((prelude_module, _use)) = self.def_collector.def_map.prelude {
             if prelude_module.krate != krate && is_crate_root {
                 cov_mark::hit!(prelude_is_macro_use);
-                self.def_collector.import_macros_from_extern_crate(prelude_module.krate, None);
-            }
-        }
-
-        // This should be processed eagerly instead of deferred to resolving.
-        // `#[macro_use] extern crate` is hoisted to imports macros before collecting
-        // any other items.
-        //
-        // If we're not at the crate root, `macro_use`d extern crates are an error so let's just
-        // ignore them.
-        if is_crate_root {
-            for &item in items {
-                if let ModItem::ExternCrate(id) = item {
-                    self.process_macro_use_extern_crate(id);
-                }
+                self.def_collector.import_macros_from_extern_crate(
+                    prelude_module.krate,
+                    None,
+                    None,
+                );
             }
         }
+        let db = self.def_collector.db;
+        let module_id = self.module_id;
+        let update_def =
+            |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
+                def_collector.def_map.modules[module_id].scope.declare(id);
+                def_collector.update(
+                    module_id,
+                    &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor, None))],
+                    vis,
+                    None,
+                )
+            };
+        let resolve_vis = |def_map: &DefMap, visibility| {
+            def_map
+                .resolve_visibility(db, module_id, visibility, false)
+                .unwrap_or(Visibility::Public)
+        };
 
-        for &item in items {
-            let attrs = self.item_tree.attrs(self.def_collector.db, krate, item.into());
+        let mut process_mod_item = |item: ModItem| {
+            let attrs = self.item_tree.attrs(db, krate, item.into());
             if let Some(cfg) = attrs.cfg() {
                 if !self.is_cfg_enabled(&cfg) {
                     self.emit_unconfigured_diagnostic(item, &cfg);
-                    continue;
+                    return;
                 }
             }
 
             if let Err(()) = self.resolve_attributes(&attrs, item, container) {
                 // Do not process the item. It has at least one non-builtin attribute, so the
                 // fixed-point algorithm is required to resolve the rest of them.
-                continue;
+                return;
             }
 
-            let db = self.def_collector.db;
-            let module = self.def_collector.def_map.module_id(self.module_id);
+            let module = self.def_collector.def_map.module_id(module_id);
             let def_map = &mut self.def_collector.def_map;
-            let update_def =
-                |def_collector: &mut DefCollector<'_>, id, name: &Name, vis, has_constructor| {
-                    def_collector.def_map.modules[self.module_id].scope.declare(id);
-                    def_collector.update(
-                        self.module_id,
-                        &[(Some(name.clone()), PerNs::from_def(id, vis, has_constructor))],
-                        vis,
-                        ImportType::Named,
-                    )
-                };
-            let resolve_vis = |def_map: &DefMap, visibility| {
-                def_map
-                    .resolve_visibility(db, self.module_id, visibility, false)
-                    .unwrap_or(Visibility::Public)
-            };
 
             match item {
                 ModItem::Mod(m) => self.collect_module(m, &attrs),
-                ModItem::Use(import_id) => {
-                    let _import_id =
-                        UseLoc { container: module, id: ItemTreeId::new(self.tree_id, import_id) }
-                            .intern(db);
+                ModItem::Use(item_tree_id) => {
+                    let id = UseLoc {
+                        container: module,
+                        id: ItemTreeId::new(self.tree_id, item_tree_id),
+                    }
+                    .intern(db);
+                    let is_prelude = attrs.by_key("prelude_import").exists();
                     Import::from_use(
-                        db,
-                        krate,
                         self.item_tree,
-                        ItemTreeId::new(self.tree_id, import_id),
+                        ItemTreeId::new(self.tree_id, item_tree_id),
+                        id,
+                        is_prelude,
                         |import| {
                             self.def_collector.unresolved_imports.push(ImportDirective {
                                 module_id: self.module_id,
@@ -1594,22 +1600,29 @@ impl ModCollector<'_, '_> {
                         },
                     )
                 }
-                ModItem::ExternCrate(import_id) => {
-                    let extern_crate_id = ExternCrateLoc {
+                ModItem::ExternCrate(item_tree_id) => {
+                    let id = ExternCrateLoc {
                         container: module,
-                        id: ItemTreeId::new(self.tree_id, import_id),
+                        id: ItemTreeId::new(self.tree_id, item_tree_id),
                     }
                     .intern(db);
+                    if is_crate_root {
+                        self.process_macro_use_extern_crate(
+                            item_tree_id,
+                            id,
+                            attrs.by_key("macro_use").attrs(),
+                        );
+                    }
+
                     self.def_collector.def_map.modules[self.module_id]
                         .scope
-                        .define_extern_crate_decl(extern_crate_id);
+                        .define_extern_crate_decl(id);
                     self.def_collector.unresolved_imports.push(ImportDirective {
                         module_id: self.module_id,
                         import: Import::from_extern_crate(
-                            db,
-                            krate,
                             self.item_tree,
-                            ItemTreeId::new(self.tree_id, import_id),
+                            ItemTreeId::new(self.tree_id, item_tree_id),
+                            id,
                         ),
                         status: PartialResolvedImport::Unresolved,
                     })
@@ -1768,21 +1781,34 @@ impl ModCollector<'_, '_> {
                     );
                 }
             }
+        };
+
+        // extern crates should be processed eagerly instead of deferred to resolving.
+        // `#[macro_use] extern crate` is hoisted to imports macros before collecting
+        // any other items.
+        if is_crate_root {
+            items
+                .iter()
+                .filter(|it| matches!(it, ModItem::ExternCrate(..)))
+                .copied()
+                .for_each(&mut process_mod_item);
+            items
+                .iter()
+                .filter(|it| !matches!(it, ModItem::ExternCrate(..)))
+                .copied()
+                .for_each(process_mod_item);
+        } else {
+            items.iter().copied().for_each(process_mod_item);
         }
     }
 
-    fn process_macro_use_extern_crate(&mut self, extern_crate: FileItemTreeId<ExternCrate>) {
+    fn process_macro_use_extern_crate<'a>(
+        &mut self,
+        extern_crate: FileItemTreeId<ExternCrate>,
+        extern_crate_id: ExternCrateId,
+        macro_use_attrs: impl Iterator<Item = &'a Attr>,
+    ) {
         let db = self.def_collector.db;
-        let attrs = self.item_tree.attrs(
-            db,
-            self.def_collector.def_map.krate,
-            ModItem::from(extern_crate).into(),
-        );
-        if let Some(cfg) = attrs.cfg() {
-            if !self.is_cfg_enabled(&cfg) {
-                return;
-            }
-        }
 
         let target_crate =
             match self.def_collector.resolve_extern_crate(&self.item_tree[extern_crate].name) {
@@ -1798,11 +1824,11 @@ impl ModCollector<'_, '_> {
 
         let mut single_imports = Vec::new();
         let hygiene = Hygiene::new_unhygienic();
-        for attr in attrs.by_key("macro_use").attrs() {
+        for attr in macro_use_attrs {
             let Some(paths) = attr.parse_path_comma_token_tree(db.upcast(), &hygiene) else {
                 // `#[macro_use]` (without any paths) found, forget collected names and just import
                 // all visible macros.
-                self.def_collector.import_macros_from_extern_crate(target_crate, None);
+                self.def_collector.import_macros_from_extern_crate(target_crate, None, Some(extern_crate_id));
                 return;
             };
             for path in paths {
@@ -1812,7 +1838,11 @@ impl ModCollector<'_, '_> {
             }
         }
 
-        self.def_collector.import_macros_from_extern_crate(target_crate, Some(single_imports));
+        self.def_collector.import_macros_from_extern_crate(
+            target_crate,
+            Some(single_imports),
+            Some(extern_crate_id),
+        );
     }
 
     fn collect_module(&mut self, module_id: FileItemTreeId<Mod>, attrs: &Attrs) {
@@ -1824,7 +1854,7 @@ impl ModCollector<'_, '_> {
             ModKind::Inline { items } => {
                 let module_id = self.push_child_module(
                     module.name.clone(),
-                    AstId::new(self.file_id(), module.ast_id),
+                    module.ast_id,
                     None,
                     &self.item_tree[module.visibility],
                     module_id,
@@ -1862,7 +1892,7 @@ impl ModCollector<'_, '_> {
                         if is_enabled {
                             let module_id = self.push_child_module(
                                 module.name.clone(),
-                                ast_id,
+                                ast_id.value,
                                 Some((file_id, is_mod_rs)),
                                 &self.item_tree[module.visibility],
                                 module_id,
@@ -1889,7 +1919,7 @@ impl ModCollector<'_, '_> {
                     Err(candidates) => {
                         self.push_child_module(
                             module.name.clone(),
-                            ast_id,
+                            ast_id.value,
                             None,
                             &self.item_tree[module.visibility],
                             module_id,
@@ -1906,7 +1936,7 @@ impl ModCollector<'_, '_> {
     fn push_child_module(
         &mut self,
         name: Name,
-        declaration: AstId<ast::Module>,
+        declaration: FileAstId<ast::Module>,
         definition: Option<(FileId, bool)>,
         visibility: &crate::visibility::RawVisibility,
         mod_tree_id: FileItemTreeId<Mod>,
@@ -1948,9 +1978,9 @@ impl ModCollector<'_, '_> {
         def_map.modules[self.module_id].scope.declare(def);
         self.def_collector.update(
             self.module_id,
-            &[(Some(name), PerNs::from_def(def, vis, false))],
+            &[(Some(name), PerNs::from_def(def, vis, false, None))],
             vis,
-            ImportType::Named,
+            None,
         );
         res
     }
@@ -2198,7 +2228,7 @@ impl ModCollector<'_, '_> {
                             map[module].scope.get_legacy_macro(name)?.last().copied()
                         })
                         .or_else(|| def_map[self.module_id].scope.get(name).take_macros())
-                        .or_else(|| def_map.macro_use_prelude.get(name).copied())
+                        .or_else(|| Some(def_map.macro_use_prelude.get(name).copied()?.0))
                         .filter(|&id| {
                             sub_namespace_match(
                                 Some(MacroSubNs::from_id(db, id)),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
index de22ea10146..460a908b6db 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/path_resolution.rs
@@ -15,8 +15,9 @@ use hir_expand::name::Name;
 use triomphe::Arc;
 
 use crate::{
+    data::adt::VariantData,
     db::DefDatabase,
-    item_scope::BUILTIN_SCOPE,
+    item_scope::{ImportOrExternCrate, BUILTIN_SCOPE},
     nameres::{sub_namespace_match, BlockInfo, BuiltinShadowMode, DefMap, MacroSubNs},
     path::{ModPath, PathKind},
     per_ns::PerNs,
@@ -65,7 +66,7 @@ impl PerNs {
         db: &dyn DefDatabase,
         expected: Option<MacroSubNs>,
     ) -> Self {
-        self.macros = self.macros.filter(|&(id, _)| {
+        self.macros = self.macros.filter(|&(id, _, _)| {
             let this = MacroSubNs::from_id(db, id);
             sub_namespace_match(Some(this), expected)
         });
@@ -196,15 +197,15 @@ impl DefMap {
             PathKind::DollarCrate(krate) => {
                 if krate == self.krate {
                     cov_mark::hit!(macro_dollar_crate_self);
-                    PerNs::types(self.crate_root().into(), Visibility::Public)
+                    PerNs::types(self.crate_root().into(), Visibility::Public, None)
                 } else {
                     let def_map = db.crate_def_map(krate);
                     let module = def_map.module_id(Self::ROOT);
                     cov_mark::hit!(macro_dollar_crate_other);
-                    PerNs::types(module.into(), Visibility::Public)
+                    PerNs::types(module.into(), Visibility::Public, None)
                 }
             }
-            PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public),
+            PathKind::Crate => PerNs::types(self.crate_root().into(), Visibility::Public, None),
             // plain import or absolute path in 2015: crate-relative with
             // fallback to extern prelude (with the simplification in
             // rust-lang/rust#57745)
@@ -291,7 +292,7 @@ impl DefMap {
                     );
                 }
 
-                PerNs::types(module.into(), Visibility::Public)
+                PerNs::types(module.into(), Visibility::Public, None)
             }
             PathKind::Abs => {
                 // 2018-style absolute path -- only extern prelude
@@ -299,9 +300,13 @@ impl DefMap {
                     Some((_, segment)) => segment,
                     None => return ResolvePathResult::empty(ReachedFixedPoint::Yes),
                 };
-                if let Some(&def) = self.data.extern_prelude.get(segment) {
+                if let Some(&(def, extern_crate)) = self.data.extern_prelude.get(segment) {
                     tracing::debug!("absolute path {:?} resolved to crate {:?}", path, def);
-                    PerNs::types(def.into(), Visibility::Public)
+                    PerNs::types(
+                        def.into(),
+                        Visibility::Public,
+                        extern_crate.map(ImportOrExternCrate::ExternCrate),
+                    )
                 } else {
                     return ResolvePathResult::empty(ReachedFixedPoint::No); // extern crate declarations can add to the extern prelude
                 }
@@ -309,7 +314,7 @@ impl DefMap {
         };
 
         for (i, segment) in segments {
-            let (curr, vis) = match curr_per_ns.take_types_vis() {
+            let (curr, vis, imp) = match curr_per_ns.take_types_full() {
                 Some(r) => r,
                 None => {
                     // we still have path segments left, but the path so far
@@ -364,18 +369,20 @@ impl DefMap {
                         Some(local_id) => {
                             let variant = EnumVariantId { parent: e, local_id };
                             match &*enum_data.variants[local_id].variant_data {
-                                crate::data::adt::VariantData::Record(_) => {
-                                    PerNs::types(variant.into(), Visibility::Public)
-                                }
-                                crate::data::adt::VariantData::Tuple(_)
-                                | crate::data::adt::VariantData::Unit => {
-                                    PerNs::both(variant.into(), variant.into(), Visibility::Public)
+                                VariantData::Record(_) => {
+                                    PerNs::types(variant.into(), Visibility::Public, None)
                                 }
+                                VariantData::Tuple(_) | VariantData::Unit => PerNs::both(
+                                    variant.into(),
+                                    variant.into(),
+                                    Visibility::Public,
+                                    None,
+                                ),
                             }
                         }
                         None => {
                             return ResolvePathResult::with(
-                                PerNs::types(e.into(), vis),
+                                PerNs::types(e.into(), vis, imp),
                                 ReachedFixedPoint::Yes,
                                 Some(i),
                                 Some(self.krate),
@@ -393,7 +400,7 @@ impl DefMap {
                     );
 
                     return ResolvePathResult::with(
-                        PerNs::types(s, vis),
+                        PerNs::types(s, vis, imp),
                         ReachedFixedPoint::Yes,
                         Some(i),
                         Some(self.krate),
@@ -430,7 +437,7 @@ impl DefMap {
             .filter(|&id| {
                 sub_namespace_match(Some(MacroSubNs::from_id(db, id)), expected_macro_subns)
             })
-            .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public));
+            .map_or_else(PerNs::none, |m| PerNs::macros(m, Visibility::Public, None));
         let from_scope = self[module].scope.get(name).filter_macro(db, expected_macro_subns);
         let from_builtin = match self.block {
             Some(_) => {
@@ -449,18 +456,27 @@ impl DefMap {
 
         let extern_prelude = || {
             if self.block.is_some() {
-                // Don't resolve extern prelude in block `DefMap`s.
+                // Don't resolve extern prelude in block `DefMap`s, defer it to the crate def map so
+                // that blocks can properly shadow them
                 return PerNs::none();
             }
-            self.data
-                .extern_prelude
-                .get(name)
-                .map_or(PerNs::none(), |&it| PerNs::types(it.into(), Visibility::Public))
+            self.data.extern_prelude.get(name).map_or(PerNs::none(), |&(it, extern_crate)| {
+                PerNs::types(
+                    it.into(),
+                    Visibility::Public,
+                    extern_crate.map(ImportOrExternCrate::ExternCrate),
+                )
+            })
         };
         let macro_use_prelude = || {
-            self.macro_use_prelude
-                .get(name)
-                .map_or(PerNs::none(), |&it| PerNs::macros(it.into(), Visibility::Public))
+            self.macro_use_prelude.get(name).map_or(PerNs::none(), |&(it, _extern_crate)| {
+                PerNs::macros(
+                    it.into(),
+                    Visibility::Public,
+                    // FIXME?
+                    None, // extern_crate.map(ImportOrExternCrate::ExternCrate),
+                )
+            })
         };
         let prelude = || self.resolve_in_prelude(db, name);
 
@@ -488,18 +504,23 @@ impl DefMap {
                 // Don't resolve extern prelude in block `DefMap`s.
                 return PerNs::none();
             }
-            self.data
-                .extern_prelude
-                .get(name)
-                .copied()
-                .map_or(PerNs::none(), |it| PerNs::types(it.into(), Visibility::Public))
+            self.data.extern_prelude.get(name).copied().map_or(
+                PerNs::none(),
+                |(it, extern_crate)| {
+                    PerNs::types(
+                        it.into(),
+                        Visibility::Public,
+                        extern_crate.map(ImportOrExternCrate::ExternCrate),
+                    )
+                },
+            )
         };
 
         from_crate_root.or_else(from_extern_prelude)
     }
 
     fn resolve_in_prelude(&self, db: &dyn DefDatabase, name: &Name) -> PerNs {
-        if let Some(prelude) = self.prelude {
+        if let Some((prelude, _use)) = self.prelude {
             let keep;
             let def_map = if prelude.krate == self.krate {
                 self
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
index dd7c3c36306..e7cc44b04da 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests.rs
@@ -168,7 +168,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Foo: t v
+            Foo: ti vi
             foo: t
 
             crate::foo
@@ -194,8 +194,8 @@ pub enum Quux {};
 "#,
         expect![[r#"
             crate
-            Baz: t v
-            Quux: t
+            Baz: ti vi
+            Quux: ti
             foo: t
 
             crate::foo
@@ -225,11 +225,11 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: ti vi
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -274,7 +274,7 @@ use self::E::V;
         expect![[r#"
             crate
             E: t
-            V: t v
+            V: ti vi
         "#]],
     );
 }
@@ -307,7 +307,7 @@ pub struct FromLib;
 
             crate::foo
             Bar: _
-            FromLib: t v
+            FromLib: ti vi
         "#]],
     );
 }
@@ -328,7 +328,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t
+            Baz: ti
             foo: t
 
             crate::foo
@@ -352,7 +352,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: ti vi
         "#]],
     );
 }
@@ -375,13 +375,13 @@ pub struct Arc;
         expect![[r#"
             crate
             alloc: t
-            alloc_crate: t
+            alloc_crate: te
             sync: t
 
             crate::alloc
 
             crate::sync
-            Arc: t v
+            Arc: ti vi
         "#]],
     );
 }
@@ -404,13 +404,13 @@ pub struct Arc;
         expect![[r#"
             crate
             alloc: t
-            alloc_crate: t
+            alloc_crate: te
             sync: t
 
             crate::alloc
 
             crate::sync
-            Arc: t v
+            Arc: ti vi
         "#]],
     );
 }
@@ -426,7 +426,7 @@ extern crate self as bla;
 "#,
         expect![[r#"
             crate
-            bla: t
+            bla: te
         "#]],
     );
 }
@@ -447,7 +447,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: ti vi
         "#]],
     );
 }
@@ -465,7 +465,7 @@ pub struct Bar;
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             foo: v
         "#]],
     );
@@ -492,9 +492,9 @@ fn no_std_prelude() {
         }
     "#,
         expect![[r#"
-        crate
-        Rust: t v
-    "#]],
+            crate
+            Rust: ti vi
+        "#]],
     );
 }
 
@@ -516,9 +516,9 @@ fn edition_specific_preludes() {
         }
     "#,
         expect![[r#"
-        crate
-        Rust2018: t v
-    "#]],
+            crate
+            Rust2018: ti vi
+        "#]],
     );
     check(
         r#"
@@ -533,9 +533,9 @@ fn edition_specific_preludes() {
         }
     "#,
         expect![[r#"
-        crate
-        Rust2021: t v
-    "#]],
+            crate
+            Rust2021: ti vi
+        "#]],
     );
 }
 
@@ -563,8 +563,8 @@ pub mod prelude {
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Foo: t v
+            Bar: ti vi
+            Foo: ti vi
         "#]],
     );
 }
@@ -590,7 +590,7 @@ pub mod prelude {
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             Baz: _
             Foo: _
         "#]],
@@ -619,8 +619,8 @@ pub mod prelude {
         expect![[r#"
             crate
             Bar: _
-            Baz: t v
-            Foo: t v
+            Baz: ti vi
+            Foo: ti vi
         "#]],
     );
 }
@@ -643,7 +643,7 @@ mod b {
 "#,
         expect![[r#"
             crate
-            T: t v
+            T: ti vi
             a: t
             b: t
 
@@ -816,8 +816,8 @@ fn bar() {}
         expect![[r#"
             crate
             bar: v
-            baz: v
-            foo: t
+            baz: vi
+            foo: ti
         "#]],
     );
 }
@@ -836,7 +836,7 @@ use self::m::S::{self};
     "#,
         expect![[r#"
             crate
-            S: t
+            S: ti
             m: t
 
             crate::m
@@ -860,8 +860,8 @@ pub const settings: () = ();
         "#,
         expect![[r#"
             crate
-            Settings: t v
-            settings: v
+            Settings: ti vi
+            settings: vi
         "#]],
     )
 }
@@ -890,8 +890,8 @@ pub struct Struct;
         "#,
         expect![[r#"
             crate
-            Struct: t v
-            dep: t
+            Struct: ti vi
+            dep: te
         "#]],
     );
 }
@@ -917,13 +917,13 @@ use some_module::unknown_func;
             crate
             other_module: t
             some_module: t
-            unknown_func: v
+            unknown_func: vi
 
             crate::other_module
             some_submodule: t
 
             crate::other_module::some_submodule
-            unknown_func: v
+            unknown_func: vi
 
             crate::some_module
             unknown_func: v
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
index 88a3c76393f..1ca74b5da6b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/globs.rs
@@ -24,7 +24,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             Foo: t v
             bar: t
 
@@ -237,9 +237,9 @@ pub mod baz { pub struct Bar; }
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             bar: t
-            baz: t
+            baz: ti
             foo: t
 
             crate::bar
@@ -276,9 +276,9 @@ pub mod baz { pub struct Bar; }
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             bar: t
-            baz: t
+            baz: ti
             foo: t
 
             crate::bar
@@ -323,7 +323,7 @@ mod d {
             X: t v
 
             crate::b
-            foo: t
+            foo: ti
 
             crate::c
             foo: t
@@ -332,8 +332,8 @@ mod d {
             Y: t v
 
             crate::d
-            Y: t v
-            foo: t
+            Y: ti vi
+            foo: ti
         "#]],
     );
 }
@@ -355,7 +355,7 @@ use event::Event;
         "#,
         expect![[r#"
             crate
-            Event: t
+            Event: ti
             event: t
 
             crate::event
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
index 40d3a16540d..4a86f88e57a 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/incremental.rs
@@ -212,7 +212,7 @@ pub type Ty = ();
             }
 
             for (_, res) in module_data.scope.resolutions() {
-                match res.values.or(res.types).unwrap().0 {
+                match res.values.map(|(a, _, _)| a).or(res.types.map(|(a, _, _)| a)).unwrap() {
                     ModuleDefId::FunctionId(f) => _ = db.function_data(f),
                     ModuleDefId::AdtId(adt) => match adt {
                         AdtId::StructId(it) => _ = db.struct_data(it),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
index f4cca8d68d0..e64fa0b46f1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/macros.rs
@@ -203,8 +203,8 @@ macro_rules! bar {
         expect![[r#"
             crate
             Foo: t
-            bar: m
-            foo: m
+            bar: mi
+            foo: mi
         "#]],
     );
 }
@@ -251,7 +251,7 @@ mod priv_mod {
             Bar: t v
             Foo: t v
             bar: t
-            foo: t
+            foo: te
 
             crate::bar
             Baz: t v
@@ -318,9 +318,9 @@ macro_rules! baz3 { () => { struct OkBaz3; } }
             OkBaz1: t v
             OkBaz2: t v
             OkBaz3: t v
-            all: t
-            empty: t
-            multiple: t
+            all: te
+            empty: te
+            multiple: te
         "#]],
     );
 }
@@ -551,8 +551,8 @@ fn baz() {}
 "#,
         expect![[r#"
             crate
-            bar: t m
-            baz: t v m
+            bar: ti mi
+            baz: ti v mi
             foo: t m
         "#]],
     );
@@ -583,7 +583,7 @@ mod m {
             crate
             Alias: t v
             Direct: t v
-            foo: t
+            foo: te
         "#]],
     );
 }
@@ -628,9 +628,9 @@ mod m {
             m: t
 
             crate::m
-            alias1: m
-            alias2: m
-            alias3: m
+            alias1: mi
+            alias2: mi
+            alias3: mi
             not_found: _
         "#]],
     );
@@ -682,11 +682,11 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Baz: t v
+            Bar: ti vi
+            Baz: ti vi
             Foo: t v
-            FooSelf: t v
-            foo: t
+            FooSelf: ti vi
+            foo: te
             m: t
 
             crate::m
@@ -725,7 +725,7 @@ pub struct bar;
 "#,
         expect![[r#"
             crate
-            bar: t v
+            bar: ti vi
         "#]],
     );
 }
@@ -1340,7 +1340,7 @@ pub mod prelude {
             crate
             Ok: t v
             bar: m
-            dep: t
+            dep: te
             foo: m
             ok: v
         "#]],
@@ -1370,13 +1370,13 @@ macro_rules! mk_foo {
 }
     "#,
         expect![[r#"
-        crate
-        a: t
-        lib: t
+            crate
+            a: t
+            lib: te
 
-        crate::a
-        Ok: t v
-    "#]],
+            crate::a
+            Ok: t v
+        "#]],
     );
 }
 
@@ -1427,8 +1427,8 @@ pub mod prelude {
         expect![[r#"
             crate
             Ok: t v
-            bar: m
-            foo: m
+            bar: mi
+            foo: mi
             ok: v
         "#]],
     );
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
index 81bc0ff91e3..1327d9aa62e 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/mod_resolution.rs
@@ -80,18 +80,18 @@ pub trait Iterator;
             prelude: t
 
             crate::iter
-            Iterator: t
+            Iterator: ti
             traits: t
 
             crate::iter::traits
-            Iterator: t
+            Iterator: ti
             iterator: t
 
             crate::iter::traits::iterator
             Iterator: t
 
             crate::prelude
-            Iterator: t
+            Iterator: ti
         "#]],
     );
 }
@@ -109,7 +109,7 @@ pub struct Bar;
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             foo: t
 
             crate::foo
@@ -139,7 +139,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             r#async: t
 
             crate::r#async
@@ -176,8 +176,8 @@ pub struct Bar;
 "#,
         expect![[r#"
             crate
-            Bar: t v
-            Foo: t v
+            Bar: ti vi
+            Foo: ti vi
             r#async: t
 
             crate::r#async
@@ -207,7 +207,7 @@ pub struct Bar;
 "#,
         expect![[r#"
             crate
-            Bar: t v
+            Bar: ti vi
             foo: t
 
             crate::foo
@@ -236,7 +236,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -265,7 +265,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -292,7 +292,7 @@ use super::Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
         "#]],
     );
 }
@@ -626,7 +626,7 @@ pub struct Baz;
 "#,
         expect![[r#"
             crate
-            Baz: t v
+            Baz: ti vi
             foo: t
 
             crate::foo
@@ -660,7 +660,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -694,7 +694,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -728,7 +728,7 @@ pub struct Baz;
             foo: t
 
             crate::foo
-            Baz: t v
+            Baz: ti vi
             bar: t
 
             crate::foo::bar
@@ -868,7 +868,7 @@ pub mod hash { pub trait Hash {} }
 "#,
         expect![[r#"
             crate
-            Hash: t
+            Hash: ti
             core: t
 
             crate::core
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/primitives.rs b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/primitives.rs
index 215e8952d90..271eb1c79b1 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/primitives.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/nameres/tests/primitives.rs
@@ -14,10 +14,10 @@ pub use i32 as int;
         expect![[r#"
             crate
             foo: t
-            int: t
+            int: ti
 
             crate::foo
-            int: t
+            int: ti
         "#]],
     );
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
index 2bc1f8e926e..14890364d0b 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/per_ns.rs
@@ -3,13 +3,24 @@
 //!
 //! `PerNs` (per namespace) captures this.
 
-use crate::{item_scope::ItemInNs, visibility::Visibility, MacroId, ModuleDefId};
+use crate::{
+    item_scope::{ImportId, ImportOrExternCrate, ItemInNs},
+    visibility::Visibility,
+    MacroId, ModuleDefId,
+};
+
+#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
+pub enum Namespace {
+    Types,
+    Values,
+    Macros,
+}
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
 pub struct PerNs {
-    pub types: Option<(ModuleDefId, Visibility)>,
-    pub values: Option<(ModuleDefId, Visibility)>,
-    pub macros: Option<(MacroId, Visibility)>,
+    pub types: Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)>,
+    pub values: Option<(ModuleDefId, Visibility, Option<ImportId>)>,
+    pub macros: Option<(MacroId, Visibility, Option<ImportId>)>,
 }
 
 impl Default for PerNs {
@@ -23,20 +34,29 @@ impl PerNs {
         PerNs { types: None, values: None, macros: None }
     }
 
-    pub fn values(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: None, values: Some((t, v)), macros: None }
+    pub fn values(t: ModuleDefId, v: Visibility, i: Option<ImportId>) -> PerNs {
+        PerNs { types: None, values: Some((t, v, i)), macros: None }
     }
 
-    pub fn types(t: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((t, v)), values: None, macros: None }
+    pub fn types(t: ModuleDefId, v: Visibility, i: Option<ImportOrExternCrate>) -> PerNs {
+        PerNs { types: Some((t, v, i)), values: None, macros: None }
     }
 
-    pub fn both(types: ModuleDefId, values: ModuleDefId, v: Visibility) -> PerNs {
-        PerNs { types: Some((types, v)), values: Some((values, v)), macros: None }
+    pub fn both(
+        types: ModuleDefId,
+        values: ModuleDefId,
+        v: Visibility,
+        i: Option<ImportOrExternCrate>,
+    ) -> PerNs {
+        PerNs {
+            types: Some((types, v, i)),
+            values: Some((values, v, i.and_then(ImportOrExternCrate::into_import))),
+            macros: None,
+        }
     }
 
-    pub fn macros(macro_: MacroId, v: Visibility) -> PerNs {
-        PerNs { types: None, values: None, macros: Some((macro_, v)) }
+    pub fn macros(macro_: MacroId, v: Visibility, i: Option<ImportId>) -> PerNs {
+        PerNs { types: None, values: None, macros: Some((macro_, v, i)) }
     }
 
     pub fn is_none(&self) -> bool {
@@ -51,7 +71,7 @@ impl PerNs {
         self.types.map(|it| it.0)
     }
 
-    pub fn take_types_vis(self) -> Option<(ModuleDefId, Visibility)> {
+    pub fn take_types_full(self) -> Option<(ModuleDefId, Visibility, Option<ImportOrExternCrate>)> {
         self.types
     }
 
@@ -59,24 +79,32 @@ impl PerNs {
         self.values.map(|it| it.0)
     }
 
+    pub fn take_values_import(self) -> Option<(ModuleDefId, Option<ImportId>)> {
+        self.values.map(|it| (it.0, it.2))
+    }
+
     pub fn take_macros(self) -> Option<MacroId> {
         self.macros.map(|it| it.0)
     }
 
+    pub fn take_macros_import(self) -> Option<(MacroId, Option<ImportId>)> {
+        self.macros.map(|it| (it.0, it.2))
+    }
+
     pub fn filter_visibility(self, mut f: impl FnMut(Visibility) -> bool) -> PerNs {
         let _p = profile::span("PerNs::filter_visibility");
         PerNs {
-            types: self.types.filter(|(_, v)| f(*v)),
-            values: self.values.filter(|(_, v)| f(*v)),
-            macros: self.macros.filter(|(_, v)| f(*v)),
+            types: self.types.filter(|&(_, v, _)| f(v)),
+            values: self.values.filter(|&(_, v, _)| f(v)),
+            macros: self.macros.filter(|&(_, v, _)| f(v)),
         }
     }
 
     pub fn with_visibility(self, vis: Visibility) -> PerNs {
         PerNs {
-            types: self.types.map(|(it, _)| (it, vis)),
-            values: self.values.map(|(it, _)| (it, vis)),
-            macros: self.macros.map(|(it, _)| (it, vis)),
+            types: self.types.map(|(it, _, c)| (it, vis, c)),
+            values: self.values.map(|(it, _, c)| (it, vis, c)),
+            macros: self.macros.map(|(it, _, import)| (it, vis, import)),
         }
     }
 
@@ -96,12 +124,20 @@ impl PerNs {
         }
     }
 
-    pub fn iter_items(self) -> impl Iterator<Item = ItemInNs> {
+    pub fn iter_items(self) -> impl Iterator<Item = (ItemInNs, Option<ImportOrExternCrate>)> {
         let _p = profile::span("PerNs::iter_items");
         self.types
-            .map(|it| ItemInNs::Types(it.0))
+            .map(|it| (ItemInNs::Types(it.0), it.2))
             .into_iter()
-            .chain(self.values.map(|it| ItemInNs::Values(it.0)).into_iter())
-            .chain(self.macros.map(|it| ItemInNs::Macros(it.0)).into_iter())
+            .chain(
+                self.values
+                    .map(|it| (ItemInNs::Values(it.0), it.2.map(ImportOrExternCrate::Import)))
+                    .into_iter(),
+            )
+            .chain(
+                self.macros
+                    .map(|it| (ItemInNs::Macros(it.0), it.2.map(ImportOrExternCrate::Import)))
+                    .into_iter(),
+            )
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
index b112c1070d4..2f9187009e2 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/resolver.rs
@@ -12,20 +12,21 @@ use triomphe::Arc;
 use crate::{
     body::scope::{ExprScopes, ScopeId},
     builtin_type::BuiltinType,
+    data::ExternCrateDeclData,
     db::DefDatabase,
     generics::{GenericParams, TypeOrConstParamData},
     hir::{BindingId, ExprId, LabelId},
-    item_scope::{BuiltinShadowMode, BUILTIN_SCOPE},
+    item_scope::{BuiltinShadowMode, ImportId, ImportOrExternCrate, BUILTIN_SCOPE},
     lang_item::LangItemTarget,
     nameres::{DefMap, MacroSubNs},
     path::{ModPath, Path, PathKind},
     per_ns::PerNs,
     visibility::{RawVisibility, Visibility},
-    AdtId, AssocItemId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId,
-    EnumVariantId, ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId,
-    HasModule, ImplId, ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId,
-    MacroRulesId, ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId,
-    TypeAliasId, TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
+    AdtId, ConstId, ConstParamId, CrateRootModuleId, DefWithBodyId, EnumId, EnumVariantId,
+    ExternBlockId, ExternCrateId, FunctionId, GenericDefId, GenericParamId, HasModule, ImplId,
+    ItemContainerId, LifetimeParamId, LocalModuleId, Lookup, Macro2Id, MacroId, MacroRulesId,
+    ModuleDefId, ModuleId, ProcMacroId, StaticId, StructId, TraitAliasId, TraitId, TypeAliasId,
+    TypeOrConstParamId, TypeOwnerId, TypeParamId, UseId, VariantId,
 };
 
 #[derive(Debug, Clone)]
@@ -100,8 +101,8 @@ pub enum TypeNs {
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
 pub enum ResolveValueResult {
-    ValueNs(ValueNs),
-    Partial(TypeNs, usize),
+    ValueNs(ValueNs, Option<ImportId>),
+    Partial(TypeNs, usize, Option<ImportOrExternCrate>),
 }
 
 #[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
@@ -148,39 +149,11 @@ impl Resolver {
         self.resolve_module_path(db, path, BuiltinShadowMode::Module)
     }
 
-    // FIXME: This shouldn't exist
-    pub fn resolve_module_path_in_trait_assoc_items(
-        &self,
-        db: &dyn DefDatabase,
-        path: &ModPath,
-    ) -> Option<PerNs> {
-        let (item_map, module) = self.item_scope();
-        let (module_res, idx) =
-            item_map.resolve_path(db, module, path, BuiltinShadowMode::Module, None);
-        match module_res.take_types()? {
-            ModuleDefId::TraitId(it) => {
-                let idx = idx?;
-                let unresolved = &path.segments()[idx..];
-                let assoc = match unresolved {
-                    [it] => it,
-                    _ => return None,
-                };
-                let &(_, assoc) = db.trait_data(it).items.iter().find(|(n, _)| n == assoc)?;
-                Some(match assoc {
-                    AssocItemId::FunctionId(it) => PerNs::values(it.into(), Visibility::Public),
-                    AssocItemId::ConstId(it) => PerNs::values(it.into(), Visibility::Public),
-                    AssocItemId::TypeAliasId(it) => PerNs::types(it.into(), Visibility::Public),
-                })
-            }
-            _ => None,
-        }
-    }
-
     pub fn resolve_path_in_type_ns(
         &self,
         db: &dyn DefDatabase,
         path: &Path,
-    ) -> Option<(TypeNs, Option<usize>)> {
+    ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
         let path = match path {
             Path::Normal { mod_path, .. } => mod_path,
             Path::LangItem(l) => {
@@ -197,6 +170,7 @@ impl Resolver {
                         | LangItemTarget::Static(_) => return None,
                     },
                     None,
+                    None,
                 ))
             }
         };
@@ -213,17 +187,17 @@ impl Resolver {
                 Scope::ExprScope(_) => continue,
                 Scope::GenericParams { params, def } => {
                     if let Some(id) = params.find_type_by_name(first_name, *def) {
-                        return Some((TypeNs::GenericParam(id), remaining_idx()));
+                        return Some((TypeNs::GenericParam(id), remaining_idx(), None));
                     }
                 }
                 &Scope::ImplDefScope(impl_) => {
                     if first_name == &name![Self] {
-                        return Some((TypeNs::SelfType(impl_), remaining_idx()));
+                        return Some((TypeNs::SelfType(impl_), remaining_idx(), None));
                     }
                 }
                 &Scope::AdtScope(adt) => {
                     if first_name == &name![Self] {
-                        return Some((TypeNs::AdtSelfType(adt), remaining_idx()));
+                        return Some((TypeNs::AdtSelfType(adt), remaining_idx(), None));
                     }
                 }
                 Scope::BlockScope(m) => {
@@ -236,12 +210,24 @@ impl Resolver {
         self.module_scope.resolve_path_in_type_ns(db, path)
     }
 
+    pub fn resolve_path_in_type_ns_fully_with_imports(
+        &self,
+        db: &dyn DefDatabase,
+        path: &Path,
+    ) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
+        let (res, unresolved, imp) = self.resolve_path_in_type_ns(db, path)?;
+        if unresolved.is_some() {
+            return None;
+        }
+        Some((res, imp))
+    }
+
     pub fn resolve_path_in_type_ns_fully(
         &self,
         db: &dyn DefDatabase,
         path: &Path,
     ) -> Option<TypeNs> {
-        let (res, unresolved) = self.resolve_path_in_type_ns(db, path)?;
+        let (res, unresolved, _) = self.resolve_path_in_type_ns(db, path)?;
         if unresolved.is_some() {
             return None;
         }
@@ -263,7 +249,6 @@ impl Resolver {
             RawVisibility::Public => Some(Visibility::Public),
         }
     }
-
     pub fn resolve_path_in_value_ns(
         &self,
         db: &dyn DefDatabase,
@@ -272,17 +257,20 @@ impl Resolver {
         let path = match path {
             Path::Normal { mod_path, .. } => mod_path,
             Path::LangItem(l) => {
-                return Some(ResolveValueResult::ValueNs(match *l {
-                    LangItemTarget::Function(it) => ValueNs::FunctionId(it),
-                    LangItemTarget::Static(it) => ValueNs::StaticId(it),
-                    LangItemTarget::Struct(it) => ValueNs::StructId(it),
-                    LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
-                    LangItemTarget::Union(_)
-                    | LangItemTarget::ImplDef(_)
-                    | LangItemTarget::TypeAlias(_)
-                    | LangItemTarget::Trait(_)
-                    | LangItemTarget::EnumId(_) => return None,
-                }))
+                return Some(ResolveValueResult::ValueNs(
+                    match *l {
+                        LangItemTarget::Function(it) => ValueNs::FunctionId(it),
+                        LangItemTarget::Static(it) => ValueNs::StaticId(it),
+                        LangItemTarget::Struct(it) => ValueNs::StructId(it),
+                        LangItemTarget::EnumVariant(it) => ValueNs::EnumVariantId(it),
+                        LangItemTarget::Union(_)
+                        | LangItemTarget::ImplDef(_)
+                        | LangItemTarget::TypeAlias(_)
+                        | LangItemTarget::Trait(_)
+                        | LangItemTarget::EnumId(_) => return None,
+                    },
+                    None,
+                ))
             }
         };
         let n_segments = path.segments().len();
@@ -304,20 +292,24 @@ impl Resolver {
                             .find(|entry| entry.name() == first_name);
 
                         if let Some(e) = entry {
-                            return Some(ResolveValueResult::ValueNs(ValueNs::LocalBinding(
-                                e.binding(),
-                            )));
+                            return Some(ResolveValueResult::ValueNs(
+                                ValueNs::LocalBinding(e.binding()),
+                                None,
+                            ));
                         }
                     }
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_const_by_name(first_name, *def) {
                             let val = ValueNs::GenericParam(id);
-                            return Some(ResolveValueResult::ValueNs(val));
+                            return Some(ResolveValueResult::ValueNs(val, None));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         if first_name == &name![Self] {
-                            return Some(ResolveValueResult::ValueNs(ValueNs::ImplSelf(impl_)));
+                            return Some(ResolveValueResult::ValueNs(
+                                ValueNs::ImplSelf(impl_),
+                                None,
+                            ));
                         }
                     }
                     // bare `Self` doesn't work in the value namespace in a struct/enum definition
@@ -336,18 +328,22 @@ impl Resolver {
                     Scope::GenericParams { params, def } => {
                         if let Some(id) = params.find_type_by_name(first_name, *def) {
                             let ty = TypeNs::GenericParam(id);
-                            return Some(ResolveValueResult::Partial(ty, 1));
+                            return Some(ResolveValueResult::Partial(ty, 1, None));
                         }
                     }
                     &Scope::ImplDefScope(impl_) => {
                         if first_name == &name![Self] {
-                            return Some(ResolveValueResult::Partial(TypeNs::SelfType(impl_), 1));
+                            return Some(ResolveValueResult::Partial(
+                                TypeNs::SelfType(impl_),
+                                1,
+                                None,
+                            ));
                         }
                     }
                     Scope::AdtScope(adt) => {
                         if first_name == &name![Self] {
                             let ty = TypeNs::AdtSelfType(*adt);
-                            return Some(ResolveValueResult::Partial(ty, 1));
+                            return Some(ResolveValueResult::Partial(ty, 1, None));
                         }
                     }
                     Scope::BlockScope(m) => {
@@ -368,7 +364,7 @@ impl Resolver {
         // `use core::u16;`.
         if path.kind == PathKind::Plain && n_segments > 1 {
             if let Some(builtin) = BuiltinType::by_name(first_name) {
-                return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1));
+                return Some(ResolveValueResult::Partial(TypeNs::BuiltinType(builtin), 1, None));
             }
         }
 
@@ -381,7 +377,7 @@ impl Resolver {
         path: &Path,
     ) -> Option<ValueNs> {
         match self.resolve_path_in_value_ns(db, path)? {
-            ResolveValueResult::ValueNs(it) => Some(it),
+            ResolveValueResult::ValueNs(it, _) => Some(it),
             ResolveValueResult::Partial(..) => None,
         }
     }
@@ -391,12 +387,12 @@ impl Resolver {
         db: &dyn DefDatabase,
         path: &ModPath,
         expected_macro_kind: Option<MacroSubNs>,
-    ) -> Option<MacroId> {
+    ) -> Option<(MacroId, Option<ImportId>)> {
         let (item_map, module) = self.item_scope();
         item_map
             .resolve_path(db, module, path, BuiltinShadowMode::Other, expected_macro_kind)
             .0
-            .take_macros()
+            .take_macros_import()
     }
 
     /// Returns a set of names available in the current scope.
@@ -456,21 +452,22 @@ impl Resolver {
         def_map[module_id].scope.entries().for_each(|(name, def)| {
             res.add_per_ns(name, def);
         });
+
         def_map[module_id].scope.legacy_macros().for_each(|(name, macs)| {
             macs.iter().for_each(|&mac| {
                 res.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)));
             })
         });
-        def_map.macro_use_prelude().for_each(|(name, def)| {
+        def_map.macro_use_prelude().for_each(|(name, (def, _extern_crate))| {
             res.add(name, ScopeDef::ModuleDef(def.into()));
         });
-        def_map.extern_prelude().for_each(|(name, def)| {
-            res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def)));
+        def_map.extern_prelude().for_each(|(name, (def, _extern_crate))| {
+            res.add(name, ScopeDef::ModuleDef(ModuleDefId::ModuleId(def.into())));
         });
         BUILTIN_SCOPE.iter().for_each(|(name, &def)| {
             res.add_per_ns(name, def);
         });
-        if let Some(prelude) = def_map.prelude() {
+        if let Some((prelude, _use)) = def_map.prelude() {
             let prelude_def_map = prelude.def_map(db);
             for (name, def) in prelude_def_map[prelude.local_id].scope.entries() {
                 res.add_per_ns(name, def)
@@ -479,6 +476,23 @@ impl Resolver {
         res.map
     }
 
+    pub fn extern_crate_decls_in_scope<'a>(
+        &'a self,
+        db: &'a dyn DefDatabase,
+    ) -> impl Iterator<Item = Name> + 'a {
+        self.module_scope.def_map[self.module_scope.module_id]
+            .scope
+            .extern_crate_decls()
+            .map(|id| ExternCrateDeclData::extern_crate_decl_data_query(db, id).name.clone())
+    }
+
+    pub fn extern_crates_in_scope<'a>(&'a self) -> impl Iterator<Item = (Name, ModuleId)> + 'a {
+        self.module_scope
+            .def_map
+            .extern_prelude()
+            .map(|(name, module_id)| (name.clone(), module_id.0.into()))
+    }
+
     pub fn traits_in_scope(&self, db: &dyn DefDatabase) -> FxHashSet<TraitId> {
         // FIXME(trait_alias): Trait alias brings aliased traits in scope! Note that supertraits of
         // aliased traits are NOT brought in scope (unless also aliased).
@@ -501,7 +515,7 @@ impl Resolver {
         }
 
         // Fill in the prelude traits
-        if let Some(prelude) = self.module_scope.def_map.prelude() {
+        if let Some((prelude, _use)) = self.module_scope.def_map.prelude() {
             let prelude_def_map = prelude.def_map(db);
             traits.extend(prelude_def_map[prelude.local_id].scope.traits());
         }
@@ -804,11 +818,12 @@ impl ModuleItemMap {
             self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
         match idx {
             None => {
-                let value = to_value_ns(module_def)?;
-                Some(ResolveValueResult::ValueNs(value))
+                let (value, import) = to_value_ns(module_def)?;
+                Some(ResolveValueResult::ValueNs(value, import))
             }
             Some(idx) => {
-                let ty = match module_def.take_types()? {
+                let (def, _, import) = module_def.take_types_full()?;
+                let ty = match def {
                     ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
                     ModuleDefId::TraitId(it) => TypeNs::TraitId(it),
                     ModuleDefId::TraitAliasId(it) => TypeNs::TraitAliasId(it),
@@ -822,7 +837,7 @@ impl ModuleItemMap {
                     | ModuleDefId::MacroId(_)
                     | ModuleDefId::StaticId(_) => return None,
                 };
-                Some(ResolveValueResult::Partial(ty, idx))
+                Some(ResolveValueResult::Partial(ty, idx, import))
             }
         }
     }
@@ -831,16 +846,17 @@ impl ModuleItemMap {
         &self,
         db: &dyn DefDatabase,
         path: &ModPath,
-    ) -> Option<(TypeNs, Option<usize>)> {
+    ) -> Option<(TypeNs, Option<usize>, Option<ImportOrExternCrate>)> {
         let (module_def, idx) =
             self.def_map.resolve_path_locally(db, self.module_id, path, BuiltinShadowMode::Other);
-        let res = to_type_ns(module_def)?;
-        Some((res, idx))
+        let (res, import) = to_type_ns(module_def)?;
+        Some((res, idx, import))
     }
 }
 
-fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
-    let res = match per_ns.take_values()? {
+fn to_value_ns(per_ns: PerNs) -> Option<(ValueNs, Option<ImportId>)> {
+    let (def, import) = per_ns.take_values_import()?;
+    let res = match def {
         ModuleDefId::FunctionId(it) => ValueNs::FunctionId(it),
         ModuleDefId::AdtId(AdtId::StructId(it)) => ValueNs::StructId(it),
         ModuleDefId::EnumVariantId(it) => ValueNs::EnumVariantId(it),
@@ -855,11 +871,12 @@ fn to_value_ns(per_ns: PerNs) -> Option<ValueNs> {
         | ModuleDefId::MacroId(_)
         | ModuleDefId::ModuleId(_) => return None,
     };
-    Some(res)
+    Some((res, import))
 }
 
-fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
-    let res = match per_ns.take_types()? {
+fn to_type_ns(per_ns: PerNs) -> Option<(TypeNs, Option<ImportOrExternCrate>)> {
+    let (def, _, import) = per_ns.take_types_full()?;
+    let res = match def {
         ModuleDefId::AdtId(it) => TypeNs::AdtId(it),
         ModuleDefId::EnumVariantId(it) => TypeNs::EnumVariantId(it),
 
@@ -875,7 +892,7 @@ fn to_type_ns(per_ns: PerNs) -> Option<TypeNs> {
         | ModuleDefId::StaticId(_)
         | ModuleDefId::ModuleId(_) => return None,
     };
-    Some(res)
+    Some((res, import))
 }
 
 type FxIndexMap<K, V> = IndexMap<K, V, BuildHasherDefault<rustc_hash::FxHasher>>;
@@ -892,13 +909,13 @@ impl ScopeNames {
         }
     }
     fn add_per_ns(&mut self, name: &Name, def: PerNs) {
-        if let &Some((ty, _)) = &def.types {
+        if let &Some((ty, _, _)) = &def.types {
             self.add(name, ScopeDef::ModuleDef(ty))
         }
-        if let &Some((def, _)) = &def.values {
+        if let &Some((def, _, _)) = &def.values {
             self.add(name, ScopeDef::ModuleDef(def))
         }
-        if let &Some((mac, _)) = &def.macros {
+        if let &Some((mac, _, _)) = &def.macros {
             self.add(name, ScopeDef::ModuleDef(ModuleDefId::MacroId(mac)))
         }
         if def.is_none() {
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/src.rs b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
index 6047f770d4d..3770103cda5 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/src.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/src.rs
@@ -5,8 +5,8 @@ use la_arena::ArenaMap;
 use syntax::ast;
 
 use crate::{
-    db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Macro2Loc, MacroRulesLoc,
-    ProcMacroLoc,
+    db::DefDatabase, item_tree::ItemTreeNode, AssocItemLoc, ItemLoc, Lookup, Macro2Loc,
+    MacroRulesLoc, ProcMacroLoc, UseId,
 };
 
 pub trait HasSource {
@@ -83,3 +83,18 @@ pub trait HasChildSource<ChildId> {
     type Value;
     fn child_source(&self, db: &dyn DefDatabase) -> InFile<ArenaMap<ChildId, Self::Value>>;
 }
+
+impl HasChildSource<la_arena::Idx<ast::UseTree>> for UseId {
+    type Value = ast::UseTree;
+    fn child_source(
+        &self,
+        db: &dyn DefDatabase,
+    ) -> InFile<ArenaMap<la_arena::Idx<ast::UseTree>, Self::Value>> {
+        let loc = &self.lookup(db);
+        let use_ = &loc.id.item_tree(db)[loc.id.value];
+        InFile::new(
+            loc.id.file_id(),
+            use_.use_tree_source_map(db, loc.id.file_id()).into_iter().collect(),
+        )
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
index 4c918e55b92..0ec2422b30c 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/attrs.rs
@@ -342,14 +342,7 @@ fn inner_attributes(
             ast::Impl(it) => it.assoc_item_list()?.syntax().clone(),
             ast::Module(it) => it.item_list()?.syntax().clone(),
             ast::BlockExpr(it) => {
-                use syntax::SyntaxKind::{BLOCK_EXPR , EXPR_STMT};
-                // Block expressions accept outer and inner attributes, but only when they are the outer
-                // expression of an expression statement or the final expression of another block expression.
-                let may_carry_attributes = matches!(
-                    it.syntax().parent().map(|it| it.kind()),
-                     Some(BLOCK_EXPR | EXPR_STMT)
-                );
-                if !may_carry_attributes {
+                if !it.may_carry_attributes() {
                     return None
                 }
                 syntax.clone()
diff --git a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
index 1f1e20f49e3..4be55126b86 100644
--- a/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-expand/src/lib.rs
@@ -37,7 +37,7 @@ use either::Either;
 use syntax::{
     algo::{self, skip_trivia_token},
     ast::{self, AstNode, HasDocComments},
-    AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken,
+    AstPtr, Direction, SyntaxNode, SyntaxNodePtr, SyntaxToken, TextSize,
 };
 
 use crate::{
@@ -544,7 +544,7 @@ impl MacroCallKind {
         };
 
         let range = match kind {
-            MacroCallKind::FnLike { ast_id, .. } => ast_id.to_node(db).syntax().text_range(),
+            MacroCallKind::FnLike { ast_id, .. } => ast_id.to_ptr(db).text_range(),
             MacroCallKind::Derive { ast_id, derive_attr_index, .. } => {
                 // FIXME: should be the range of the macro name, not the whole derive
                 // FIXME: handle `cfg_attr`
@@ -642,6 +642,8 @@ impl ExpansionInfo {
         db: &dyn db::ExpandDatabase,
         item: Option<ast::Item>,
         token: InFile<&SyntaxToken>,
+        // FIXME: use this for range mapping, so that we can resolve inline format args
+        _relative_token_offset: Option<TextSize>,
     ) -> Option<impl Iterator<Item = InFile<SyntaxToken>> + '_> {
         assert_eq!(token.file_id, self.arg.file_id);
         let token_id_in_attr_input = if let Some(item) = item {
@@ -840,9 +842,6 @@ impl<N: AstIdNode> AstId<N> {
 pub type ErasedAstId = InFile<ErasedFileAstId>;
 
 impl ErasedAstId {
-    pub fn to_node(&self, db: &dyn db::ExpandDatabase) -> SyntaxNode {
-        self.to_ptr(db).to_node(&db.parse_or_expand(self.file_id))
-    }
     pub fn to_ptr(&self, db: &dyn db::ExpandDatabase) -> SyntaxNodePtr {
         db.ast_id_map(self.file_id).get_raw(self.value)
     }
@@ -1054,16 +1053,6 @@ impl InFile<SyntaxToken> {
             }
         }
     }
-
-    pub fn ancestors_with_macros(
-        self,
-        db: &dyn db::ExpandDatabase,
-    ) -> impl Iterator<Item = InFile<SyntaxNode>> + '_ {
-        self.value.parent().into_iter().flat_map({
-            let file_id = self.file_id;
-            move |parent| InFile::new(file_id, &parent).ancestors_with_macros(db)
-        })
-    }
 }
 
 #[derive(Debug, PartialEq, Eq, Clone, Copy, Hash)]
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
index eec57ba3f80..967e028bfb1 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/builder.rs
@@ -17,7 +17,8 @@ use smallvec::SmallVec;
 use crate::{
     consteval::unknown_const_as_generic, db::HirDatabase, infer::unify::InferenceTable, primitive,
     to_assoc_type_id, to_chalk_trait_id, utils::generics, Binders, BoundVar, CallableSig,
-    GenericArg, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt, TyKind,
+    GenericArg, GenericArgData, Interner, ProjectionTy, Substitution, TraitRef, Ty, TyDefId, TyExt,
+    TyKind,
 };
 
 #[derive(Debug, Clone, PartialEq, Eq)]
@@ -79,9 +80,9 @@ impl<D> TyBuilder<D> {
         let expected_kind = &self.param_kinds[self.vec.len()];
 
         let arg_kind = match arg.data(Interner) {
-            chalk_ir::GenericArgData::Ty(_) => ParamKind::Type,
-            chalk_ir::GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
-            chalk_ir::GenericArgData::Const(c) => {
+            GenericArgData::Ty(_) => ParamKind::Type,
+            GenericArgData::Lifetime(_) => panic!("Got lifetime in TyBuilder::push"),
+            GenericArgData::Const(c) => {
                 let c = c.data(Interner);
                 ParamKind::Const(c.ty.clone())
             }
@@ -139,8 +140,8 @@ impl<D> TyBuilder<D> {
 
     fn assert_match_kind(&self, a: &chalk_ir::GenericArg<Interner>, e: &ParamKind) {
         match (a.data(Interner), e) {
-            (chalk_ir::GenericArgData::Ty(_), ParamKind::Type)
-            | (chalk_ir::GenericArgData::Const(_), ParamKind::Const(_)) => (),
+            (GenericArgData::Ty(_), ParamKind::Type)
+            | (GenericArgData::Const(_), ParamKind::Const(_)) => (),
             _ => panic!("Mismatched kinds: {a:?}, {:?}, {:?}", self.vec, self.param_kinds),
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
index 1c0f7b08da8..0348680e5da 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval.rs
@@ -1,7 +1,7 @@
 //! Constant evaluation details
 
 use base_db::CrateId;
-use chalk_ir::{BoundVar, DebruijnIndex, GenericArgData};
+use chalk_ir::{cast::Cast, BoundVar, DebruijnIndex};
 use hir_def::{
     hir::Expr,
     path::Path,
@@ -120,7 +120,7 @@ pub fn unknown_const(ty: Ty) -> Const {
 }
 
 pub fn unknown_const_as_generic(ty: Ty) -> GenericArg {
-    GenericArgData::Const(unknown_const(ty)).intern(Interner)
+    unknown_const(ty).cast(Interner)
 }
 
 /// Interns a constant scalar with the given type
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
index 666955fa1c3..7ad3659a4f6 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/consteval/tests.rs
@@ -1203,6 +1203,27 @@ fn destructing_assignment() {
         "#,
         5,
     );
+    check_number(
+        r#"
+    const GOAL: u8 = {
+        let (mut a, mut b) = (2, 5);
+        (a, b) = (b, a);
+        a * 10 + b
+    };
+        "#,
+        52,
+    );
+    check_number(
+        r#"
+    struct Point { x: i32, y: i32 }
+    const GOAL: i32 = {
+        let mut p = Point { x: 5, y: 6 };
+        (p.x, _) = (p.y, p.x);
+        p.x * 10 + p.y
+    };
+        "#,
+        66,
+    );
 }
 
 #[test]
@@ -1433,6 +1454,30 @@ fn from_trait() {
 }
 
 #[test]
+fn closure_clone() {
+    check_number(
+        r#"
+//- minicore: clone, fn
+struct S(u8);
+
+impl Clone for S(u8) {
+    fn clone(&self) -> S {
+        S(self.0 + 5)
+    }
+}
+
+const GOAL: u8 = {
+    let s = S(3);
+    let cl = move || s;
+    let cl = cl.clone();
+    cl().0
+}
+    "#,
+        8,
+    );
+}
+
+#[test]
 fn builtin_derive_macro() {
     check_number(
         r#"
@@ -2396,14 +2441,14 @@ fn const_loop() {
 fn const_transfer_memory() {
     check_number(
         r#"
-    //- minicore: slice, index, coerce_unsized
+    //- minicore: slice, index, coerce_unsized, option
     const A1: &i32 = &1;
     const A2: &i32 = &10;
     const A3: [&i32; 3] = [&1, &2, &100];
-    const A4: (i32, &i32) = (1, &1000);
-    const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1;
+    const A4: (i32, &i32, Option<&i32>) = (1, &1000, Some(&10000));
+    const GOAL: i32 = *A1 + *A2 + *A3[2] + *A4.1 + *A4.2.unwrap_or(&5);
     "#,
-        1111,
+        11111,
     );
 }
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
index 9f9a56ffab0..cbca0e801d4 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/diagnostics/unsafe_check.rs
@@ -75,7 +75,7 @@ fn walk_unsafe(
         Expr::Path(path) => {
             let resolver = resolver_for_expr(db.upcast(), def, current);
             let value_or_partial = resolver.resolve_path_in_value_ns(db.upcast(), path);
-            if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id))) = value_or_partial {
+            if let Some(ResolveValueResult::ValueNs(ValueNs::StaticId(id), _)) = value_or_partial {
                 if db.static_data(id).mutable {
                     unsafe_expr_cb(UnsafeExpr { expr: current, inside_unsafe_block });
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
index 1b4ee4613d6..f6d6b00d740 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/display.rs
@@ -1809,6 +1809,25 @@ impl HirDisplay for Path {
             }
         }
 
+        // Convert trait's `Self` bound back to the surface syntax. Note there is no associated
+        // trait, so there can only be one path segment that `has_self_type`. The `Self` type
+        // itself can contain further qualified path through, which will be handled by recursive
+        // `hir_fmt`s.
+        //
+        // `trait_mod::Trait<Self = type_mod::Type, Args>::Assoc`
+        // =>
+        // `<type_mod::Type as trait_mod::Trait<Args>>::Assoc`
+        let trait_self_ty = self.segments().iter().find_map(|seg| {
+            let generic_args = seg.args_and_bindings?;
+            generic_args.has_self_type.then(|| &generic_args.args[0])
+        });
+        if let Some(ty) = trait_self_ty {
+            write!(f, "<")?;
+            ty.hir_fmt(f)?;
+            write!(f, " as ")?;
+            // Now format the path of the trait...
+        }
+
         for (seg_idx, segment) in self.segments().iter().enumerate() {
             if !matches!(self.kind(), PathKind::Plain) || seg_idx > 0 {
                 write!(f, "::")?;
@@ -1840,15 +1859,12 @@ impl HirDisplay for Path {
                     return Ok(());
                 }
 
-                write!(f, "<")?;
                 let mut first = true;
-                for arg in generic_args.args.iter() {
+                // Skip the `Self` bound if exists. It's handled outside the loop.
+                for arg in &generic_args.args[generic_args.has_self_type as usize..] {
                     if first {
                         first = false;
-                        if generic_args.has_self_type {
-                            // FIXME: Convert to `<Ty as Trait>` form.
-                            write!(f, "Self = ")?;
-                        }
+                        write!(f, "<")?;
                     } else {
                         write!(f, ", ")?;
                     }
@@ -1857,6 +1873,7 @@ impl HirDisplay for Path {
                 for binding in generic_args.bindings.iter() {
                     if first {
                         first = false;
+                        write!(f, "<")?;
                     } else {
                         write!(f, ", ")?;
                     }
@@ -1872,9 +1889,20 @@ impl HirDisplay for Path {
                         }
                     }
                 }
-                write!(f, ">")?;
+
+                // There may be no generic arguments to print, in case of a trait having only a
+                // single `Self` bound which is converted to `<Ty as Trait>::Assoc`.
+                if !first {
+                    write!(f, ">")?;
+                }
+
+                // Current position: `<Ty as Trait<Args>|`
+                if generic_args.has_self_type {
+                    write!(f, ">")?;
+                }
             }
         }
+
         Ok(())
     }
 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
index b4915dbf0f9..0fb4934444b 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer.rs
@@ -1017,7 +1017,7 @@ impl<'a> InferenceContext<'a> {
         let ctx = crate::lower::TyLoweringContext::new(self.db, &self.resolver, self.owner.into());
         let (resolution, unresolved) = if value_ns {
             match self.resolver.resolve_path_in_value_ns(self.db.upcast(), path) {
-                Some(ResolveValueResult::ValueNs(value)) => match value {
+                Some(ResolveValueResult::ValueNs(value, _)) => match value {
                     ValueNs::EnumVariantId(var) => {
                         let substs = ctx.substs_from_path(path, var.into(), true);
                         let ty = self.db.ty(var.parent.into());
@@ -1033,12 +1033,14 @@ impl<'a> InferenceContext<'a> {
                     ValueNs::ImplSelf(impl_id) => (TypeNs::SelfType(impl_id), None),
                     _ => return (self.err_ty(), None),
                 },
-                Some(ResolveValueResult::Partial(typens, unresolved)) => (typens, Some(unresolved)),
+                Some(ResolveValueResult::Partial(typens, unresolved, _)) => {
+                    (typens, Some(unresolved))
+                }
                 None => return (self.err_ty(), None),
             }
         } else {
             match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-                Some(it) => it,
+                Some((it, idx, _)) => (it, idx),
                 None => return (self.err_ty(), None),
             }
         };
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
index 1781f6c58f1..23efe616f4f 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/closure.rs
@@ -322,7 +322,7 @@ impl InferenceContext<'_> {
             Expr::Path(p) => {
                 let resolver = resolver_for_expr(self.db.upcast(), self.owner, tgt_expr);
                 if let Some(r) = resolver.resolve_path_in_value_ns(self.db.upcast(), p) {
-                    if let ResolveValueResult::ValueNs(v) = r {
+                    if let ResolveValueResult::ValueNs(v, _) = r {
                         if let ValueNs::LocalBinding(b) = v {
                             return Some(HirPlace { local: b, projections: vec![] });
                         }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
index 8cbdae62526..8b352141084 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/expr.rs
@@ -5,9 +5,7 @@ use std::{
     mem,
 };
 
-use chalk_ir::{
-    cast::Cast, fold::Shift, DebruijnIndex, GenericArgData, Mutability, TyVariableKind,
-};
+use chalk_ir::{cast::Cast, fold::Shift, DebruijnIndex, Mutability, TyVariableKind};
 use hir_def::{
     generics::TypeOrConstParamData,
     hir::{
@@ -750,7 +748,7 @@ impl InferenceContext<'_> {
                     self.resolve_associated_type_with_params(
                         self_ty,
                         self.resolve_ops_index_output(),
-                        &[GenericArgData::Ty(index_ty).intern(Interner)],
+                        &[index_ty.cast(Interner)],
                     )
                 } else {
                     self.err_ty()
@@ -1721,16 +1719,13 @@ impl InferenceContext<'_> {
         for (id, data) in def_generics.iter().skip(substs.len()) {
             match data {
                 TypeOrConstParamData::TypeParamData(_) => {
-                    substs.push(GenericArgData::Ty(self.table.new_type_var()).intern(Interner))
-                }
-                TypeOrConstParamData::ConstParamData(_) => {
-                    substs.push(
-                        GenericArgData::Const(self.table.new_const_var(
-                            self.db.const_param_ty(ConstParamId::from_unchecked(id)),
-                        ))
-                        .intern(Interner),
-                    )
+                    substs.push(self.table.new_type_var().cast(Interner))
                 }
+                TypeOrConstParamData::ConstParamData(_) => substs.push(
+                    self.table
+                        .new_const_var(self.db.const_param_ty(ConstParamId::from_unchecked(id)))
+                        .cast(Interner),
+                ),
             }
         }
         assert_eq!(substs.len(), total_len);
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
index 79d9e21e797..2a51c84db3a 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/path.rs
@@ -61,8 +61,8 @@ impl InferenceContext<'_> {
                 self.resolver.resolve_path_in_value_ns(self.db.upcast(), path)?;
 
             match value_or_partial {
-                ResolveValueResult::ValueNs(it) => (it, None),
-                ResolveValueResult::Partial(def, remaining_index) => self
+                ResolveValueResult::ValueNs(it, _) => (it, None),
+                ResolveValueResult::Partial(def, remaining_index, _) => self
                     .resolve_assoc_item(def, path, remaining_index, id)
                     .map(|(it, substs)| (it, Some(substs)))?,
             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
index 0fb71135b4d..0a68a9f3b58 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/infer/unify.rs
@@ -10,7 +10,6 @@ use chalk_solve::infer::ParameterEnaVariableExt;
 use either::Either;
 use ena::unify::UnifyKey;
 use hir_expand::name;
-use stdx::never;
 use triomphe::Arc;
 
 use super::{InferOk, InferResult, InferenceContext, TypeError};
@@ -92,15 +91,10 @@ pub(crate) fn unify(
     let vars = Substitution::from_iter(
         Interner,
         tys.binders.iter(Interner).map(|it| match &it.kind {
-            chalk_ir::VariableKind::Ty(_) => {
-                GenericArgData::Ty(table.new_type_var()).intern(Interner)
-            }
-            chalk_ir::VariableKind::Lifetime => {
-                GenericArgData::Ty(table.new_type_var()).intern(Interner)
-            } // FIXME: maybe wrong?
-            chalk_ir::VariableKind::Const(ty) => {
-                GenericArgData::Const(table.new_const_var(ty.clone())).intern(Interner)
-            }
+            chalk_ir::VariableKind::Ty(_) => table.new_type_var().cast(Interner),
+            // FIXME: maybe wrong?
+            chalk_ir::VariableKind::Lifetime => table.new_type_var().cast(Interner),
+            chalk_ir::VariableKind::Const(ty) => table.new_const_var(ty.clone()).cast(Interner),
         }),
     );
     let ty1_with_vars = vars.apply(tys.value.0.clone(), Interner);
@@ -111,10 +105,10 @@ pub(crate) fn unify(
     // default any type vars that weren't unified back to their original bound vars
     // (kind of hacky)
     let find_var = |iv| {
-        vars.iter(Interner).position(|v| match v.interned() {
-            chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
-            chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
-            chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
+        vars.iter(Interner).position(|v| match v.data(Interner) {
+            GenericArgData::Ty(ty) => ty.inference_var(Interner),
+            GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
+            GenericArgData::Const(c) => c.inference_var(Interner),
         } == Some(iv))
     };
     let fallback = |iv, kind, default, binder| match kind {
@@ -149,6 +143,9 @@ pub(crate) struct InferenceTable<'a> {
     var_unification_table: ChalkInferenceTable,
     type_variable_table: Vec<TypeVariableFlags>,
     pending_obligations: Vec<Canonicalized<InEnvironment<Goal>>>,
+    /// Double buffer used in [`Self::resolve_obligations_as_possible`] to cut down on
+    /// temporary allocations.
+    resolve_obligations_buffer: Vec<Canonicalized<InEnvironment<Goal>>>,
 }
 
 pub(crate) struct InferenceTableSnapshot {
@@ -165,6 +162,7 @@ impl<'a> InferenceTable<'a> {
             var_unification_table: ChalkInferenceTable::new(),
             type_variable_table: Vec::new(),
             pending_obligations: Vec::new(),
+            resolve_obligations_buffer: Vec::new(),
         }
     }
 
@@ -516,10 +514,10 @@ impl<'a> InferenceTable<'a> {
     pub(crate) fn resolve_obligations_as_possible(&mut self) {
         let _span = profile::span("resolve_obligations_as_possible");
         let mut changed = true;
-        let mut obligations = Vec::new();
-        while changed {
-            changed = false;
+        let mut obligations = mem::take(&mut self.resolve_obligations_buffer);
+        while mem::take(&mut changed) {
             mem::swap(&mut self.pending_obligations, &mut obligations);
+
             for canonicalized in obligations.drain(..) {
                 if !self.check_changed(&canonicalized) {
                     self.pending_obligations.push(canonicalized);
@@ -534,6 +532,8 @@ impl<'a> InferenceTable<'a> {
                 self.register_obligation_in_env(uncanonical);
             }
         }
+        self.resolve_obligations_buffer = obligations;
+        self.resolve_obligations_buffer.clear();
     }
 
     pub(crate) fn fudge_inference<T: TypeFoldable<Interner>>(
@@ -611,9 +611,9 @@ impl<'a> InferenceTable<'a> {
     fn check_changed(&mut self, canonicalized: &Canonicalized<InEnvironment<Goal>>) -> bool {
         canonicalized.free_vars.iter().any(|var| {
             let iv = match var.data(Interner) {
-                chalk_ir::GenericArgData::Ty(ty) => ty.inference_var(Interner),
-                chalk_ir::GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
-                chalk_ir::GenericArgData::Const(c) => c.inference_var(Interner),
+                GenericArgData::Ty(ty) => ty.inference_var(Interner),
+                GenericArgData::Lifetime(lt) => lt.inference_var(Interner),
+                GenericArgData::Const(c) => c.inference_var(Interner),
             }
             .expect("free var is not inference var");
             if self.var_unification_table.probe_var(iv).is_some() {
@@ -690,14 +690,10 @@ impl<'a> InferenceTable<'a> {
             .fill(|it| {
                 let arg = match it {
                     ParamKind::Type => self.new_type_var(),
-                    ParamKind::Const(ty) => {
-                        never!("Tuple with const parameter");
-                        return GenericArgData::Const(self.new_const_var(ty.clone()))
-                            .intern(Interner);
-                    }
+                    ParamKind::Const(_) => unreachable!("Tuple with const parameter"),
                 };
                 arg_tys.push(arg.clone());
-                GenericArgData::Ty(arg).intern(Interner)
+                arg.cast(Interner)
             })
             .build();
 
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
index b3ca2a22258..405bb001b5d 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lib.rs
@@ -52,12 +52,14 @@ use hir_expand::name;
 use la_arena::{Arena, Idx};
 use mir::{MirEvalError, VTableMap};
 use rustc_hash::FxHashSet;
+use syntax::ast::{make, ConstArg};
 use traits::FnTrait;
 use triomphe::Arc;
 use utils::Generics;
 
 use crate::{
-    consteval::unknown_const, db::HirDatabase, infer::unify::InferenceTable, utils::generics,
+    consteval::unknown_const, db::HirDatabase, display::HirDisplay, infer::unify::InferenceTable,
+    utils::generics,
 };
 
 pub use autoderef::autoderef;
@@ -719,3 +721,16 @@ where
     value.visit_with(&mut collector, DebruijnIndex::INNERMOST);
     collector.placeholders.into_iter().collect()
 }
+
+pub fn known_const_to_ast(konst: &Const, db: &dyn HirDatabase) -> Option<ConstArg> {
+    if let ConstValue::Concrete(c) = &konst.interned().value {
+        match c.interned {
+            ConstScalar::UnevaluatedConst(GeneralConstId::InTypeConstId(cid), _) => {
+                return Some(cid.source(db.upcast()));
+            }
+            ConstScalar::Unknown => return None,
+            _ => (),
+        }
+    }
+    Some(make::expr_const_value(konst.display(db).to_string().as_str()))
+}
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
index 2837f400bce..9a61f153599 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/lower.rs
@@ -58,10 +58,9 @@ use crate::{
         InTypeConstIdMetadata,
     },
     AliasEq, AliasTy, Binders, BoundVar, CallableSig, Const, ConstScalar, DebruijnIndex, DynTy,
-    FnPointer, FnSig, FnSubst, GenericArgData, ImplTraitId, Interner, ParamKind, PolyFnSig,
-    ProjectionTy, QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait,
-    ReturnTypeImplTraits, Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder,
-    TyKind, WhereClause,
+    FnPointer, FnSig, FnSubst, ImplTraitId, Interner, ParamKind, PolyFnSig, ProjectionTy,
+    QuantifiedWhereClause, QuantifiedWhereClauses, ReturnTypeImplTrait, ReturnTypeImplTraits,
+    Substitution, TraitEnvironment, TraitRef, TraitRefExt, Ty, TyBuilder, TyKind, WhereClause,
 };
 
 #[derive(Debug)]
@@ -213,6 +212,19 @@ impl<'a> TyLoweringContext<'a> {
         self.lower_ty_ext(type_ref).0
     }
 
+    pub fn lower_const(&self, const_ref: &ConstRef, const_type: Ty) -> Const {
+        const_or_path_to_chalk(
+            self.db,
+            self.resolver,
+            self.owner,
+            const_type,
+            const_ref,
+            self.type_param_mode,
+            || self.generics(),
+            self.in_binders,
+        )
+    }
+
     fn generics(&self) -> Generics {
         generics(
             self.db.upcast(),
@@ -242,17 +254,7 @@ impl<'a> TyLoweringContext<'a> {
             }
             TypeRef::Array(inner, len) => {
                 let inner_ty = self.lower_ty(inner);
-                let const_len = const_or_path_to_chalk(
-                    self.db,
-                    self.resolver,
-                    self.owner,
-                    TyBuilder::usize(),
-                    len,
-                    self.type_param_mode,
-                    || self.generics(),
-                    self.in_binders,
-                );
-
+                let const_len = self.lower_const(len, TyBuilder::usize());
                 TyKind::Array(inner_ty, const_len).intern(Interner)
             }
             TypeRef::Slice(inner) => {
@@ -391,11 +393,9 @@ impl<'a> TyLoweringContext<'a> {
                 let ty = {
                     let macro_call = macro_call.to_node(self.db.upcast());
                     let resolver = |path| {
-                        self.resolver.resolve_path_as_macro(
-                            self.db.upcast(),
-                            &path,
-                            Some(MacroSubNs::Bang),
-                        )
+                        self.resolver
+                            .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
+                            .map(|(it, _)| it)
                     };
                     match expander.enter_expand::<ast::Type>(self.db.upcast(), macro_call, resolver)
                     {
@@ -447,7 +447,7 @@ impl<'a> TyLoweringContext<'a> {
             return None;
         }
         let resolution = match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
-            Some((it, None)) => it,
+            Some((it, None, _)) => it,
             _ => return None,
         };
         match resolution {
@@ -627,7 +627,7 @@ impl<'a> TyLoweringContext<'a> {
             return self.lower_ty_relative_path(ty, res, path.segments());
         }
 
-        let (resolution, remaining_index) =
+        let (resolution, remaining_index, _) =
             match self.resolver.resolve_path_in_type_ns(self.db.upcast(), path) {
                 Some(it) => it,
                 None => return (TyKind::Error.intern(Interner), None),
@@ -847,18 +847,7 @@ impl<'a> TyLoweringContext<'a> {
                         arg,
                         &mut (),
                         |_, type_ref| self.lower_ty(type_ref),
-                        |_, c, ty| {
-                            const_or_path_to_chalk(
-                                self.db,
-                                self.resolver,
-                                self.owner,
-                                ty,
-                                c,
-                                self.type_param_mode,
-                                || self.generics(),
-                                self.in_binders,
-                            )
-                        },
+                        |_, const_ref, ty| self.lower_const(const_ref, ty),
                     ) {
                         had_explicit_args = true;
                         substs.push(x);
@@ -1604,24 +1593,35 @@ pub(crate) fn generic_defaults_query(
             .iter()
             .enumerate()
             .map(|(idx, (id, p))| {
-                let p = match p {
-                    TypeOrConstParamData::TypeParamData(p) => p,
-                    TypeOrConstParamData::ConstParamData(_) => {
-                        // FIXME: implement const generic defaults
-                        let val = unknown_const_as_generic(
-                            db.const_param_ty(ConstParamId::from_unchecked(id)),
+                match p {
+                    TypeOrConstParamData::TypeParamData(p) => {
+                        let mut ty = p
+                            .default
+                            .as_ref()
+                            .map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
+                        // Each default can only refer to previous parameters.
+                        // Type variable default referring to parameter coming
+                        // after it is forbidden (FIXME: report diagnostic)
+                        ty = fallback_bound_vars(ty, idx, parent_start_idx);
+                        crate::make_binders(db, &generic_params, ty.cast(Interner))
+                    }
+                    TypeOrConstParamData::ConstParamData(p) => {
+                        let mut val = p.default.as_ref().map_or_else(
+                            || {
+                                unknown_const_as_generic(
+                                    db.const_param_ty(ConstParamId::from_unchecked(id)),
+                                )
+                            },
+                            |c| {
+                                let c = ctx.lower_const(c, ctx.lower_ty(&p.ty));
+                                c.cast(Interner)
+                            },
                         );
-                        return make_binders(db, &generic_params, val);
+                        // Each default can only refer to previous parameters, see above.
+                        val = fallback_bound_vars(val, idx, parent_start_idx);
+                        make_binders(db, &generic_params, val)
                     }
-                };
-                let mut ty =
-                    p.default.as_ref().map_or(TyKind::Error.intern(Interner), |t| ctx.lower_ty(t));
-
-                // Each default can only refer to previous parameters.
-                // Type variable default referring to parameter coming
-                // after it is forbidden (FIXME: report diagnostic)
-                ty = fallback_bound_vars(ty, idx, parent_start_idx);
-                crate::make_binders(db, &generic_params, ty.cast(Interner))
+                }
             })
             // FIXME: use `Arc::from_iter` when it becomes available
             .collect::<Vec<_>>(),
@@ -1643,9 +1643,7 @@ pub(crate) fn generic_defaults_recover(
             .iter_id()
             .map(|id| {
                 let val = match id {
-                    Either::Left(_) => {
-                        GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner)
-                    }
+                    Either::Left(_) => TyKind::Error.intern(Interner).cast(Interner),
                     Either::Right(id) => unknown_const_as_generic(db.const_param_ty(id)),
                 };
                 crate::make_binders(db, &generic_params, val)
@@ -1991,16 +1989,9 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
         }
     };
     Some(match (arg, kind) {
-        (GenericArg::Type(type_ref), ParamKind::Type) => {
-            let ty = for_type(this, type_ref);
-            GenericArgData::Ty(ty).intern(Interner)
-        }
-        (GenericArg::Const(c), ParamKind::Const(c_ty)) => {
-            GenericArgData::Const(for_const(this, c, c_ty)).intern(Interner)
-        }
-        (GenericArg::Const(_), ParamKind::Type) => {
-            GenericArgData::Ty(TyKind::Error.intern(Interner)).intern(Interner)
-        }
+        (GenericArg::Type(type_ref), ParamKind::Type) => for_type(this, type_ref).cast(Interner),
+        (GenericArg::Const(c), ParamKind::Const(c_ty)) => for_const(this, c, c_ty).cast(Interner),
+        (GenericArg::Const(_), ParamKind::Type) => TyKind::Error.intern(Interner).cast(Interner),
         (GenericArg::Type(t), ParamKind::Const(c_ty)) => {
             // We want to recover simple idents, which parser detects them
             // as types. Maybe here is not the best place to do it, but
@@ -2010,9 +2001,7 @@ pub(crate) fn generic_arg_to_chalk<'a, T>(
                 if p.kind == PathKind::Plain {
                     if let [n] = p.segments() {
                         let c = ConstRef::Path(n.clone());
-                        return Some(
-                            GenericArgData::Const(for_const(this, &c, c_ty)).intern(Interner),
-                        );
+                        return Some(for_const(this, &c, c_ty).cast(Interner));
                     }
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
index 4723c25ed08..9be083d0117 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir.rs
@@ -368,7 +368,7 @@ pub enum TerminatorKind {
     ///
     /// Only permitted in cleanup blocks. `Resume` is not permitted with `-C unwind=abort` after
     /// deaggregation runs.
-    Resume,
+    UnwindResume,
 
     /// Indicates that the landing pad is finished and that the process should abort.
     ///
@@ -1057,7 +1057,7 @@ impl MirBody {
                     TerminatorKind::FalseEdge { .. }
                     | TerminatorKind::FalseUnwind { .. }
                     | TerminatorKind::Goto { .. }
-                    | TerminatorKind::Resume
+                    | TerminatorKind::UnwindResume
                     | TerminatorKind::GeneratorDrop
                     | TerminatorKind::Abort
                     | TerminatorKind::Return
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
index ad98e8fa181..c70d7f63fd8 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/borrowck.rs
@@ -160,7 +160,7 @@ fn moved_out_of_ref(db: &dyn HirDatabase, body: &MirBody) -> Vec<MovedOutOfRef>
                 TerminatorKind::FalseEdge { .. }
                 | TerminatorKind::FalseUnwind { .. }
                 | TerminatorKind::Goto { .. }
-                | TerminatorKind::Resume
+                | TerminatorKind::UnwindResume
                 | TerminatorKind::GeneratorDrop
                 | TerminatorKind::Abort
                 | TerminatorKind::Return
@@ -280,7 +280,7 @@ fn ever_initialized_map(
         let targets = match &terminator.kind {
             TerminatorKind::Goto { target } => vec![*target],
             TerminatorKind::SwitchInt { targets, .. } => targets.all_targets().to_vec(),
-            TerminatorKind::Resume
+            TerminatorKind::UnwindResume
             | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::Unreachable => vec![],
@@ -371,7 +371,7 @@ fn mutability_of_locals(
         };
         match &terminator.kind {
             TerminatorKind::Goto { .. }
-            | TerminatorKind::Resume
+            | TerminatorKind::UnwindResume
             | TerminatorKind::Abort
             | TerminatorKind::Return
             | TerminatorKind::Unreachable
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
index 9e30eed56f3..3944feb128c 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval.rs
@@ -10,7 +10,7 @@ use std::{
 };
 
 use base_db::{CrateId, FileId};
-use chalk_ir::Mutability;
+use chalk_ir::{cast::Cast, Mutability};
 use either::Either;
 use hir_def::{
     builtin_type::BuiltinType,
@@ -40,8 +40,8 @@ use crate::{
     name, static_lifetime,
     traits::FnTrait,
     utils::{detect_variant_from_bytes, ClosureSubst},
-    CallableDefId, ClosureId, Const, ConstScalar, FnDefId, GenericArgData, Interner, MemoryMap,
-    Substitution, TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
+    CallableDefId, ClosureId, Const, ConstScalar, FnDefId, Interner, MemoryMap, Substitution,
+    TraitEnvironment, Ty, TyBuilder, TyExt, TyKind,
 };
 
 use super::{
@@ -2007,7 +2007,28 @@ impl Evaluator<'_> {
                     }
                 }
                 AdtId::UnionId(_) => (),
-                AdtId::EnumId(_) => (),
+                AdtId::EnumId(e) => {
+                    if let Some((variant, layout)) = detect_variant_from_bytes(
+                        &layout,
+                        self.db,
+                        self.trait_env.clone(),
+                        self.read_memory(addr, layout.size.bytes_usize())?,
+                        e,
+                    ) {
+                        let ev = EnumVariantId { parent: e, local_id: variant };
+                        for (i, (_, ty)) in self.db.field_types(ev.into()).iter().enumerate() {
+                            let offset = layout.fields.offset(i).bytes_usize();
+                            let ty = ty.clone().substitute(Interner, subst);
+                            self.patch_addresses(
+                                patch_map,
+                                old_vtable,
+                                addr.offset(offset),
+                                &ty,
+                                locals,
+                            )?;
+                        }
+                    }
+                }
             },
             TyKind::Tuple(_, subst) => {
                 for (id, ty) in subst.iter(Interner).enumerate() {
@@ -2248,7 +2269,7 @@ impl Evaluator<'_> {
                     interval: args_for_target[0].interval.slice(0..self.ptr_size()),
                     ty: ty.clone(),
                 };
-                let ty = GenericArgData::Ty(ty.clone()).intern(Interner);
+                let ty = ty.clone().cast(Interner);
                 let generics_for_target = Substitution::from_iter(
                     Interner,
                     generic_args.iter(Interner).enumerate().map(|(i, it)| {
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
index b2e29fd34b5..52943e97ac0 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/shim.rs
@@ -136,7 +136,10 @@ impl Evaluator<'_> {
                     not_supported!("wrong generic arg kind for clone");
                 };
                 // Clone has special impls for tuples and function pointers
-                if matches!(self_ty.kind(Interner), TyKind::Function(_) | TyKind::Tuple(..)) {
+                if matches!(
+                    self_ty.kind(Interner),
+                    TyKind::Function(_) | TyKind::Tuple(..) | TyKind::Closure(..)
+                ) {
                     self.exec_clone(def, args, self_ty.clone(), locals, destination, span)?;
                     return Ok(true);
                 }
@@ -167,32 +170,26 @@ impl Evaluator<'_> {
                 return destination
                     .write_from_interval(self, Interval { addr, size: destination.size });
             }
+            TyKind::Closure(id, subst) => {
+                let [arg] = args else {
+                    not_supported!("wrong arg count for clone");
+                };
+                let addr = Address::from_bytes(arg.get(self)?)?;
+                let (closure_owner, _) = self.db.lookup_intern_closure((*id).into());
+                let infer = self.db.infer(closure_owner);
+                let (captures, _) = infer.closure_info(id);
+                let layout = self.layout(&self_ty)?;
+                let ty_iter = captures.iter().map(|c| c.ty(subst));
+                self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?;
+            }
             TyKind::Tuple(_, subst) => {
                 let [arg] = args else {
                     not_supported!("wrong arg count for clone");
                 };
                 let addr = Address::from_bytes(arg.get(self)?)?;
                 let layout = self.layout(&self_ty)?;
-                for (i, ty) in subst.iter(Interner).enumerate() {
-                    let ty = ty.assert_ty_ref(Interner);
-                    let size = self.layout(ty)?.size.bytes_usize();
-                    let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?;
-                    let arg = IntervalAndTy {
-                        interval: Interval { addr: tmp, size: self.ptr_size() },
-                        ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone())
-                            .intern(Interner),
-                    };
-                    let offset = layout.fields.offset(i).bytes_usize();
-                    self.write_memory(tmp, &addr.offset(offset).to_bytes())?;
-                    self.exec_clone(
-                        def,
-                        &[arg],
-                        ty.clone(),
-                        locals,
-                        destination.slice(offset..offset + size),
-                        span,
-                    )?;
-                }
+                let ty_iter = subst.iter(Interner).map(|ga| ga.assert_ty_ref(Interner).clone());
+                self.exec_clone_for_fields(ty_iter, layout, addr, def, locals, destination, span)?;
             }
             _ => {
                 self.exec_fn_with_args(
@@ -209,6 +206,37 @@ impl Evaluator<'_> {
         Ok(())
     }
 
+    fn exec_clone_for_fields(
+        &mut self,
+        ty_iter: impl Iterator<Item = Ty>,
+        layout: Arc<Layout>,
+        addr: Address,
+        def: FunctionId,
+        locals: &Locals,
+        destination: Interval,
+        span: MirSpan,
+    ) -> Result<()> {
+        for (i, ty) in ty_iter.enumerate() {
+            let size = self.layout(&ty)?.size.bytes_usize();
+            let tmp = self.heap_allocate(self.ptr_size(), self.ptr_size())?;
+            let arg = IntervalAndTy {
+                interval: Interval { addr: tmp, size: self.ptr_size() },
+                ty: TyKind::Ref(Mutability::Not, static_lifetime(), ty.clone()).intern(Interner),
+            };
+            let offset = layout.fields.offset(i).bytes_usize();
+            self.write_memory(tmp, &addr.offset(offset).to_bytes())?;
+            self.exec_clone(
+                def,
+                &[arg],
+                ty,
+                locals,
+                destination.slice(offset..offset + size),
+                span,
+            )?;
+        }
+        Ok(())
+    }
+
     fn exec_alloc_fn(
         &mut self,
         alloc_fn: &str,
@@ -473,6 +501,38 @@ impl Evaluator<'_> {
                 self.write_memory_using_ref(destination.addr, destination.size)?.fill(0);
                 Ok(())
             }
+            "getenv" => {
+                let [name] = args else {
+                    return Err(MirEvalError::TypeError("libc::write args are not provided"));
+                };
+                let mut name_buf = vec![];
+                let name = {
+                    let mut index = Address::from_bytes(name.get(self)?)?;
+                    loop {
+                        let byte = self.read_memory(index, 1)?[0];
+                        index = index.offset(1);
+                        if byte == 0 {
+                            break;
+                        }
+                        name_buf.push(byte);
+                    }
+                    String::from_utf8_lossy(&name_buf)
+                };
+                let value = self.db.crate_graph()[self.crate_id].env.get(&name);
+                match value {
+                    None => {
+                        // Write null as fail
+                        self.write_memory_using_ref(destination.addr, destination.size)?.fill(0);
+                    }
+                    Some(mut value) => {
+                        value.push('\0');
+                        let addr = self.heap_allocate(value.len(), 1)?;
+                        self.write_memory(addr, value.as_bytes())?;
+                        self.write_memory(destination.addr, &addr.to_bytes())?;
+                    }
+                }
+                Ok(())
+            }
             _ => not_supported!("unknown external function {as_str}"),
         }
     }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
index 46165cf3d69..ff30dc6dade 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/eval/tests.rs
@@ -730,6 +730,48 @@ fn main() {
 }
 
 #[test]
+fn posix_getenv() {
+    check_pass(
+        r#"
+//- /main.rs env:foo=bar
+
+type c_char = u8;
+
+extern "C" {
+    pub fn getenv(s: *const c_char) -> *mut c_char;
+}
+
+fn should_not_reach() {
+    _ // FIXME: replace this function with panic when that works
+}
+
+fn main() {
+    let result = getenv(b"foo\0" as *const _);
+    if *result != b'b' {
+        should_not_reach();
+    }
+    let result = (result as usize + 1) as *const c_char;
+    if *result != b'a' {
+        should_not_reach();
+    }
+    let result = (result as usize + 1) as *const c_char;
+    if *result != b'r' {
+        should_not_reach();
+    }
+    let result = (result as usize + 1) as *const c_char;
+    if *result != 0 {
+        should_not_reach();
+    }
+    let result = getenv(b"not found\0" as *const _);
+    if result as usize != 0 {
+        should_not_reach();
+    }
+}
+"#,
+    );
+}
+
+#[test]
 fn posix_tls() {
     check_pass(
         r#"
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
index 718df8331e2..51cf882d053 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower.rs
@@ -15,7 +15,7 @@ use hir_def::{
     path::Path,
     resolver::{resolver_for_expr, HasResolver, ResolveValueResult, ValueNs},
     AdtId, DefWithBodyId, EnumVariantId, GeneralConstId, HasModule, ItemContainerId, LocalFieldId,
-    TraitId, TypeOrConstParamId,
+    Lookup, TraitId, TypeOrConstParamId,
 };
 use hir_expand::name::Name;
 use la_arena::ArenaMap;
@@ -372,7 +372,7 @@ impl<'ctx> MirLowerCtx<'ctx> {
         match &self.body.exprs[expr_id] {
             Expr::Missing => {
                 if let DefWithBodyId::FunctionId(f) = self.owner {
-                    let assoc = self.db.lookup_intern_function(f);
+                    let assoc = f.lookup(self.db.upcast());
                     if let ItemContainerId::TraitId(t) = assoc.container {
                         let name = &self.db.function_data(f).name;
                         return Err(MirLowerError::TraitFunctionDefinition(t, name.clone()));
@@ -1244,6 +1244,41 @@ impl<'ctx> MirLowerCtx<'ctx> {
         }
     }
 
+    fn lower_destructing_assignment(
+        &mut self,
+        mut current: BasicBlockId,
+        lhs: ExprId,
+        rhs: Place,
+        span: MirSpan,
+    ) -> Result<Option<BasicBlockId>> {
+        match &self.body.exprs[lhs] {
+            Expr::Tuple { exprs, is_assignee_expr: _ } => {
+                for (i, expr) in exprs.iter().enumerate() {
+                    let Some(c) = self.lower_destructing_assignment(
+                        current,
+                        *expr,
+                        rhs.project(ProjectionElem::TupleOrClosureField(i)),
+                        span,
+                    )? else {
+                        return Ok(None);
+                    };
+                    current = c;
+                }
+                Ok(Some(current))
+            }
+            Expr::Underscore => Ok(Some(current)),
+            _ => {
+                let Some((lhs_place, current)) =
+                    self.lower_expr_as_place(current, lhs, false)?
+                else {
+                    return Ok(None);
+                };
+                self.push_assignment(current, lhs_place, Operand::Copy(rhs).into(), span);
+                Ok(Some(current))
+            }
+        }
+    }
+
     fn lower_assignment(
         &mut self,
         current: BasicBlockId,
@@ -1259,6 +1294,15 @@ impl<'ctx> MirLowerCtx<'ctx> {
         if matches!(&self.body.exprs[lhs], Expr::Underscore) {
             return Ok(Some(current));
         }
+        if matches!(
+            &self.body.exprs[lhs],
+            Expr::Tuple { .. } | Expr::RecordLit { .. } | Expr::Call { .. }
+        ) {
+            let temp = self.temp(self.expr_ty_after_adjustments(rhs), current, rhs.into())?;
+            let temp = Place::from(temp);
+            self.push_assignment(current, temp.clone(), rhs_op.into(), span);
+            return self.lower_destructing_assignment(current, lhs, temp, span);
+        }
         let Some((lhs_place, current)) =
             self.lower_expr_as_place(current, lhs, false)?
         else {
@@ -1308,14 +1352,14 @@ impl<'ctx> MirLowerCtx<'ctx> {
                     .resolve_path_in_value_ns(self.db.upcast(), c)
                     .ok_or_else(unresolved_name)?;
                 match pr {
-                    ResolveValueResult::ValueNs(v) => {
+                    ResolveValueResult::ValueNs(v, _) => {
                         if let ValueNs::ConstId(c) = v {
                             self.lower_const_to_operand(Substitution::empty(Interner), c.into(), ty)
                         } else {
                             not_supported!("bad path in range pattern");
                         }
                     }
-                    ResolveValueResult::Partial(_, _) => {
+                    ResolveValueResult::Partial(_, _, _) => {
                         not_supported!("associated constants in range pattern")
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
index 3354cbd76a0..1cdfd919742 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/lower/pattern_matching.rs
@@ -323,7 +323,7 @@ impl MirLowerCtx<'_> {
                                 break 'b (c, x.1);
                             }
                         }
-                        if let ResolveValueResult::ValueNs(v) = pr {
+                        if let ResolveValueResult::ValueNs(v, _) = pr {
                             if let ValueNs::ConstId(c) = v {
                                 break 'b (c, Substitution::empty(Interner));
                             }
diff --git a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
index c565228d91e..df16d0d8201 100644
--- a/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
+++ b/src/tools/rust-analyzer/crates/hir-ty/src/mir/monomorphization.rs
@@ -265,7 +265,7 @@ impl Filler<'_> {
                         self.fill_operand(discr)?;
                     }
                     TerminatorKind::Goto { .. }
-                    | TerminatorKind::Resume
+                    | TerminatorKind::UnwindResume
                     | TerminatorKind::Abort
                     | TerminatorKind::Return
                     | TerminatorKind::Unreachable
diff --git a/src/tools/rust-analyzer/crates/hir/src/attrs.rs b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
index 0f2fb2c8118..121e5a0a249 100644
--- a/src/tools/rust-analyzer/crates/hir/src/attrs.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/attrs.rs
@@ -3,18 +3,19 @@
 use hir_def::{
     attr::{AttrsWithOwner, Documentation},
     item_scope::ItemInNs,
-    path::ModPath,
-    resolver::HasResolver,
-    AttrDefId, GenericParamId, ModuleDefId,
+    path::{ModPath, Path},
+    per_ns::Namespace,
+    resolver::{HasResolver, Resolver, TypeNs},
+    AssocItemId, AttrDefId, GenericParamId, ModuleDefId,
 };
-use hir_expand::hygiene::Hygiene;
+use hir_expand::{hygiene::Hygiene, name::Name};
 use hir_ty::db::HirDatabase;
 use syntax::{ast, AstNode};
 
 use crate::{
-    Adt, AssocItem, Const, ConstParam, Enum, ExternCrateDecl, Field, Function, GenericParam, Impl,
-    LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait, TraitAlias, TypeAlias,
-    TypeParam, Union, Variant,
+    Adt, AsAssocItem, AssocItem, BuiltinType, Const, ConstParam, Enum, ExternCrateDecl, Field,
+    Function, GenericParam, Impl, LifetimeParam, Macro, Module, ModuleDef, Static, Struct, Trait,
+    TraitAlias, TypeAlias, TypeParam, Union, Variant, VariantDef,
 };
 
 pub trait HasAttrs {
@@ -25,14 +26,14 @@ pub trait HasAttrs {
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<Namespace>,
-    ) -> Option<ModuleDef>;
+    ) -> Option<DocLinkDef>;
 }
 
-#[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
-pub enum Namespace {
-    Types,
-    Values,
-    Macros,
+/// Subset of `ide_db::Definition` that doc links can resolve to.
+pub enum DocLinkDef {
+    ModuleDef(ModuleDef),
+    Field(Field),
+    SelfType(Trait),
 }
 
 macro_rules! impl_has_attrs {
@@ -46,9 +47,14 @@ macro_rules! impl_has_attrs {
                 let def = AttrDefId::$def_id(self.into());
                 db.attrs(def).docs()
             }
-            fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> {
+            fn resolve_doc_path(
+                self,
+                db: &dyn HirDatabase,
+                link: &str,
+                ns: Option<Namespace>
+            ) -> Option<DocLinkDef> {
                 let def = AttrDefId::$def_id(self.into());
-                resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
+                resolve_doc_path(db, def, link, ns)
             }
         }
     )*};
@@ -79,7 +85,12 @@ macro_rules! impl_has_attrs_enum {
             fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
                 $enum::$variant(self).docs(db)
             }
-            fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> {
+            fn resolve_doc_path(
+                self,
+                db: &dyn HirDatabase,
+                link: &str,
+                ns: Option<Namespace>
+            ) -> Option<DocLinkDef> {
                 $enum::$variant(self).resolve_doc_path(db, link, ns)
             }
         }
@@ -111,7 +122,7 @@ impl HasAttrs for AssocItem {
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<Namespace>,
-    ) -> Option<ModuleDef> {
+    ) -> Option<DocLinkDef> {
         match self {
             AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
             AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
@@ -147,9 +158,9 @@ impl HasAttrs for ExternCrateDecl {
         db: &dyn HirDatabase,
         link: &str,
         ns: Option<Namespace>,
-    ) -> Option<ModuleDef> {
+    ) -> Option<DocLinkDef> {
         let def = AttrDefId::ExternCrateId(self.into());
-        resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
+        resolve_doc_path(db, def, link, ns)
     }
 }
 
@@ -159,7 +170,7 @@ fn resolve_doc_path(
     def: AttrDefId,
     link: &str,
     ns: Option<Namespace>,
-) -> Option<ModuleDefId> {
+) -> Option<DocLinkDef> {
     let resolver = match def {
         AttrDefId::ModuleId(it) => it.resolver(db.upcast()),
         AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()),
@@ -184,8 +195,107 @@ fn resolve_doc_path(
         .resolver(db.upcast()),
     };
 
-    let modpath = {
-        // FIXME: this is not how we should get a mod path here
+    let mut modpath = modpath_from_str(db, link)?;
+
+    let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
+    if resolved.is_none() {
+        let last_name = modpath.pop_segment()?;
+        resolve_assoc_or_field(db, resolver, modpath, last_name, ns)
+    } else {
+        let def = match ns {
+            Some(Namespace::Types) => resolved.take_types(),
+            Some(Namespace::Values) => resolved.take_values(),
+            Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId),
+            None => resolved.iter_items().next().map(|(it, _)| match it {
+                ItemInNs::Types(it) => it,
+                ItemInNs::Values(it) => it,
+                ItemInNs::Macros(it) => ModuleDefId::MacroId(it),
+            }),
+        };
+        Some(DocLinkDef::ModuleDef(def?.into()))
+    }
+}
+
+fn resolve_assoc_or_field(
+    db: &dyn HirDatabase,
+    resolver: Resolver,
+    path: ModPath,
+    name: Name,
+    ns: Option<Namespace>,
+) -> Option<DocLinkDef> {
+    let path = Path::from_known_path_with_no_generic(path);
+    // FIXME: This does not handle `Self` on trait definitions, which we should resolve to the
+    // trait itself.
+    let base_def = resolver.resolve_path_in_type_ns_fully(db.upcast(), &path)?;
+
+    let ty = match base_def {
+        TypeNs::SelfType(id) => Impl::from(id).self_ty(db),
+        TypeNs::GenericParam(_) => {
+            // Even if this generic parameter has some trait bounds, rustdoc doesn't
+            // resolve `name` to trait items.
+            return None;
+        }
+        TypeNs::AdtId(id) | TypeNs::AdtSelfType(id) => Adt::from(id).ty(db),
+        TypeNs::EnumVariantId(id) => {
+            // Enum variants don't have path candidates.
+            let variant = Variant::from(id);
+            return resolve_field(db, variant.into(), name, ns);
+        }
+        TypeNs::TypeAliasId(id) => {
+            let alias = TypeAlias::from(id);
+            if alias.as_assoc_item(db).is_some() {
+                // We don't normalize associated type aliases, so we have nothing to
+                // resolve `name` to.
+                return None;
+            }
+            alias.ty(db)
+        }
+        TypeNs::BuiltinType(id) => BuiltinType::from(id).ty(db),
+        TypeNs::TraitId(id) => {
+            // Doc paths in this context may only resolve to an item of this trait
+            // (i.e. no items of its supertraits), so we need to handle them here
+            // independently of others.
+            return db.trait_data(id).items.iter().find(|it| it.0 == name).map(|(_, assoc_id)| {
+                let def = match *assoc_id {
+                    AssocItemId::FunctionId(it) => ModuleDef::Function(it.into()),
+                    AssocItemId::ConstId(it) => ModuleDef::Const(it.into()),
+                    AssocItemId::TypeAliasId(it) => ModuleDef::TypeAlias(it.into()),
+                };
+                DocLinkDef::ModuleDef(def)
+            });
+        }
+        TypeNs::TraitAliasId(_) => {
+            // XXX: Do these get resolved?
+            return None;
+        }
+    };
+
+    // FIXME: Resolve associated items here, e.g. `Option::map`. Note that associated items take
+    // precedence over fields.
+
+    let variant_def = match ty.as_adt()? {
+        Adt::Struct(it) => it.into(),
+        Adt::Union(it) => it.into(),
+        Adt::Enum(_) => return None,
+    };
+    resolve_field(db, variant_def, name, ns)
+}
+
+fn resolve_field(
+    db: &dyn HirDatabase,
+    def: VariantDef,
+    name: Name,
+    ns: Option<Namespace>,
+) -> Option<DocLinkDef> {
+    if let Some(Namespace::Types | Namespace::Macros) = ns {
+        return None;
+    }
+    def.fields(db).into_iter().find(|f| f.name(db) == name).map(DocLinkDef::Field)
+}
+
+fn modpath_from_str(db: &dyn HirDatabase, link: &str) -> Option<ModPath> {
+    // FIXME: this is not how we should get a mod path here.
+    let try_get_modpath = |link: &str| {
         let ast_path = ast::SourceFile::parse(&format!("type T = {link};"))
             .syntax_node()
             .descendants()
@@ -193,23 +303,20 @@ fn resolve_doc_path(
         if ast_path.syntax().text() != link {
             return None;
         }
-        ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())?
+        ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())
     };
 
-    let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
-    let resolved = if resolved.is_none() {
-        resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)?
-    } else {
-        resolved
-    };
-    match ns {
-        Some(Namespace::Types) => resolved.take_types(),
-        Some(Namespace::Values) => resolved.take_values(),
-        Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId),
-        None => resolved.iter_items().next().map(|it| match it {
-            ItemInNs::Types(it) => it,
-            ItemInNs::Values(it) => it,
-            ItemInNs::Macros(it) => ModuleDefId::MacroId(it),
-        }),
+    let full = try_get_modpath(link);
+    if full.is_some() {
+        return full;
     }
+
+    // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can
+    // resolve doc paths like `TupleStruct::0`.
+    // FIXME: Find a better way to handle these.
+    let (base, maybe_tuple_field) = link.rsplit_once("::")?;
+    let tuple_field = Name::new_tuple_field(maybe_tuple_field.parse().ok()?);
+    let mut modpath = try_get_modpath(base)?;
+    modpath.push_segment(tuple_field);
+    Some(modpath)
 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/display.rs b/src/tools/rust-analyzer/crates/hir/src/display.rs
index 9dfb98e459b..ac171026d5d 100644
--- a/src/tools/rust-analyzer/crates/hir/src/display.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/display.rs
@@ -8,7 +8,6 @@ use hir_def::{
     type_ref::{TypeBound, TypeRef},
     AdtId, GenericDefId,
 };
-use hir_expand::name;
 use hir_ty::{
     display::{
         write_bounds_like_dyn_trait_with_prefix, write_visibility, HirDisplay, HirDisplayError,
@@ -19,8 +18,9 @@ use hir_ty::{
 
 use crate::{
     Adt, AsAssocItem, AssocItemContainer, Const, ConstParam, Enum, ExternCrateDecl, Field,
-    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, Static, Struct,
-    Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam, Union, Variant,
+    Function, GenericParam, HasCrate, HasVisibility, LifetimeParam, Macro, Module, SelfParam,
+    Static, Struct, Trait, TraitAlias, TyBuilder, Type, TypeAlias, TypeOrConstParam, TypeParam,
+    Union, Variant,
 };
 
 impl HirDisplay for Function {
@@ -57,37 +57,21 @@ impl HirDisplay for Function {
 
         f.write_char('(')?;
 
-        let write_self_param = |ty: &TypeRef, f: &mut HirFormatter<'_>| match ty {
-            TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
-            TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
-            {
-                f.write_char('&')?;
-                if let Some(lifetime) = lifetime {
-                    write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
-                }
-                if let hir_def::type_ref::Mutability::Mut = mut_ {
-                    f.write_str("mut ")?;
-                }
-                f.write_str("self")
-            }
-            _ => {
-                f.write_str("self: ")?;
-                ty.hir_fmt(f)
-            }
-        };
-
         let mut first = true;
+        let mut skip_self = 0;
+        if let Some(self_param) = self.self_param(db) {
+            self_param.hir_fmt(f)?;
+            first = false;
+            skip_self = 1;
+        }
+
         // FIXME: Use resolved `param.ty` once we no longer discard lifetimes
-        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)) {
+        for (type_ref, param) in data.params.iter().zip(self.assoc_fn_params(db)).skip(skip_self) {
             let local = param.as_local(db).map(|it| it.name(db));
             if !first {
                 f.write_str(", ")?;
             } else {
                 first = false;
-                if local == Some(name!(self)) {
-                    write_self_param(type_ref, f)?;
-                    continue;
-                }
             }
             match local {
                 Some(name) => write!(f, "{}: ", name.display(f.db.upcast()))?,
@@ -137,6 +121,31 @@ impl HirDisplay for Function {
     }
 }
 
+impl HirDisplay for SelfParam {
+    fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
+        let data = f.db.function_data(self.func);
+        let param = data.params.first().unwrap();
+        match &**param {
+            TypeRef::Path(p) if p.is_self_type() => f.write_str("self"),
+            TypeRef::Reference(inner, lifetime, mut_) if matches!(&**inner, TypeRef::Path(p) if p.is_self_type()) =>
+            {
+                f.write_char('&')?;
+                if let Some(lifetime) = lifetime {
+                    write!(f, "{} ", lifetime.name.display(f.db.upcast()))?;
+                }
+                if let hir_def::type_ref::Mutability::Mut = mut_ {
+                    f.write_str("mut ")?;
+                }
+                f.write_str("self")
+            }
+            ty => {
+                f.write_str("self: ")?;
+                ty.hir_fmt(f)
+            }
+        }
+    }
+}
+
 impl HirDisplay for Adt {
     fn hir_fmt(&self, f: &mut HirFormatter<'_>) -> Result<(), HirDisplayError> {
         match self {
@@ -357,6 +366,11 @@ fn write_generic_params(
                     delim(f)?;
                     write!(f, "const {}: ", name.display(f.db.upcast()))?;
                     c.ty.hir_fmt(f)?;
+
+                    if let Some(default) = &c.default {
+                        f.write_str(" = ")?;
+                        write!(f, "{}", default.display(f.db.upcast()))?;
+                    }
                 }
             }
         }
diff --git a/src/tools/rust-analyzer/crates/hir/src/lib.rs b/src/tools/rust-analyzer/crates/hir/src/lib.rs
index bf041b61f2f..512fe7e0428 100644
--- a/src/tools/rust-analyzer/crates/hir/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/lib.rs
@@ -63,12 +63,13 @@ use hir_ty::{
     all_super_traits, autoderef,
     consteval::{try_const_usize, unknown_const_as_generic, ConstEvalError, ConstExt},
     diagnostics::BodyValidationDiagnostic,
+    known_const_to_ast,
     layout::{Layout as TyLayout, RustcEnumVariantIdx, TagEncoding},
     method_resolution::{self, TyFingerprint},
     mir::{self, interpret_mir},
     primitive::UintTy,
     traits::FnTrait,
-    AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId,
+    AliasTy, CallableDefId, CallableSig, Canonical, CanonicalVarKinds, Cast, ClosureId, GenericArg,
     GenericArgData, Interner, ParamKind, QuantifiedWhereClause, Scalar, Substitution,
     TraitEnvironment, TraitRefExt, Ty, TyBuilder, TyDefId, TyExt, TyKind, ValueTyDefId,
     WhereClause,
@@ -87,7 +88,7 @@ use triomphe::Arc;
 use crate::db::{DefDatabase, HirDatabase};
 
 pub use crate::{
-    attrs::{HasAttrs, Namespace},
+    attrs::{DocLinkDef, HasAttrs},
     diagnostics::{
         AnyDiagnostic, BreakOutsideOfLoop, CaseType, ExpectedFunction, InactiveCode,
         IncoherentImpl, IncorrectCase, InvalidDeriveTarget, MacroDefError, MacroError,
@@ -121,6 +122,7 @@ pub use {
         lang_item::LangItem,
         nameres::{DefMap, ModuleSource},
         path::{ModPath, PathKind},
+        per_ns::Namespace,
         type_ref::{Mutability, TypeRef},
         visibility::Visibility,
         // FIXME: This is here since some queries take it as input that are used
@@ -719,20 +721,18 @@ fn emit_def_diagnostic_(
 ) {
     match diag {
         DefDiagnosticKind::UnresolvedModule { ast: declaration, candidates } => {
-            let decl = declaration.to_node(db.upcast());
+            let decl = declaration.to_ptr(db.upcast());
             acc.push(
                 UnresolvedModule {
-                    decl: InFile::new(declaration.file_id, AstPtr::new(&decl)),
+                    decl: InFile::new(declaration.file_id, decl),
                     candidates: candidates.clone(),
                 }
                 .into(),
             )
         }
         DefDiagnosticKind::UnresolvedExternCrate { ast } => {
-            let item = ast.to_node(db.upcast());
-            acc.push(
-                UnresolvedExternCrate { decl: InFile::new(ast.file_id, AstPtr::new(&item)) }.into(),
-            );
+            let item = ast.to_ptr(db.upcast());
+            acc.push(UnresolvedExternCrate { decl: InFile::new(ast.file_id, item) }.into());
         }
 
         DefDiagnosticKind::UnresolvedImport { id, index } => {
@@ -747,14 +747,10 @@ fn emit_def_diagnostic_(
         }
 
         DefDiagnosticKind::UnconfiguredCode { ast, cfg, opts } => {
-            let item = ast.to_node(db.upcast());
+            let item = ast.to_ptr(db.upcast());
             acc.push(
-                InactiveCode {
-                    node: ast.with_value(SyntaxNodePtr::new(&item).into()),
-                    cfg: cfg.clone(),
-                    opts: opts.clone(),
-                }
-                .into(),
+                InactiveCode { node: ast.with_value(item), cfg: cfg.clone(), opts: opts.clone() }
+                    .into(),
             );
         }
         DefDiagnosticKind::UnresolvedProcMacro { ast, krate } => {
@@ -1273,7 +1269,7 @@ impl Adt {
             .fill(|x| {
                 let r = it.next().unwrap_or_else(|| TyKind::Error.intern(Interner));
                 match x {
-                    ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
+                    ParamKind::Type => r.cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
                 }
             })
@@ -2096,14 +2092,6 @@ impl SelfParam {
             .unwrap_or(Access::Owned)
     }
 
-    pub fn display(self, db: &dyn HirDatabase) -> &'static str {
-        match self.access(db) {
-            Access::Shared => "&self",
-            Access::Exclusive => "&mut self",
-            Access::Owned => "self",
-        }
-    }
-
     pub fn source(&self, db: &dyn HirDatabase) -> Option<InFile<ast::SelfParam>> {
         let InFile { file_id, value } = Function::from(self.func).source(db)?;
         value
@@ -3142,12 +3130,8 @@ impl TypeParam {
     }
 
     pub fn default(self, db: &dyn HirDatabase) -> Option<Type> {
-        let params = db.generic_defaults(self.id.parent());
-        let local_idx = hir_ty::param_idx(db, self.id.into())?;
+        let ty = generic_arg_from_param(db, self.id.into())?;
         let resolver = self.id.parent().resolver(db.upcast());
-        let ty = params.get(local_idx)?.clone();
-        let subst = TyBuilder::placeholder_subst(db, self.id.parent());
-        let ty = ty.substitute(Interner, &subst);
         match ty.data(Interner) {
             GenericArgData::Ty(it) => {
                 Some(Type::new_with_resolver_inner(db, &resolver, it.clone()))
@@ -3209,6 +3193,19 @@ impl ConstParam {
     pub fn ty(self, db: &dyn HirDatabase) -> Type {
         Type::new(db, self.id.parent(), db.const_param_ty(self.id))
     }
+
+    pub fn default(self, db: &dyn HirDatabase) -> Option<ast::ConstArg> {
+        let arg = generic_arg_from_param(db, self.id.into())?;
+        known_const_to_ast(arg.constant(Interner)?, db)
+    }
+}
+
+fn generic_arg_from_param(db: &dyn HirDatabase, id: TypeOrConstParamId) -> Option<GenericArg> {
+    let params = db.generic_defaults(id.parent);
+    let local_idx = hir_ty::param_idx(db, id)?;
+    let ty = params.get(local_idx)?.clone();
+    let subst = TyBuilder::placeholder_subst(db, id.parent);
+    Some(ty.substitute(Interner, &subst))
 }
 
 #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
@@ -3716,7 +3713,7 @@ impl Type {
             .fill(|x| {
                 let r = it.next().unwrap();
                 match x {
-                    ParamKind::Type => GenericArgData::Ty(r).intern(Interner),
+                    ParamKind::Type => r.cast(Interner),
                     ParamKind::Const(ty) => {
                         // FIXME: this code is not covered in tests.
                         unknown_const_as_generic(ty.clone())
@@ -3749,9 +3746,7 @@ impl Type {
             .fill(|it| {
                 // FIXME: this code is not covered in tests.
                 match it {
-                    ParamKind::Type => {
-                        GenericArgData::Ty(args.next().unwrap().ty.clone()).intern(Interner)
-                    }
+                    ParamKind::Type => args.next().unwrap().ty.clone().cast(Interner),
                     ParamKind::Const(ty) => unknown_const_as_generic(ty.clone()),
                 }
             })
@@ -4414,14 +4409,13 @@ impl Callable {
             Other => CallableKind::Other,
         }
     }
-    pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(ast::SelfParam, Type)> {
+    pub fn receiver_param(&self, db: &dyn HirDatabase) -> Option<(SelfParam, Type)> {
         let func = match self.callee {
             Callee::Def(CallableDefId::FunctionId(it)) if self.is_bound_method => it,
             _ => return None,
         };
-        let src = func.lookup(db.upcast()).source(db.upcast());
-        let param_list = src.value.param_list()?;
-        Some((param_list.self_param()?, self.ty.derived(self.sig.params()[0].clone())))
+        let func = Function { id: func };
+        Some((func.self_param(db)?, self.ty.derived(self.sig.params()[0].clone())))
     }
     pub fn n_params(&self) -> usize {
         self.sig.params().len() - if self.is_bound_method { 1 } else { 0 }
diff --git a/src/tools/rust-analyzer/crates/hir/src/semantics.rs b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
index e99d2984c36..b8d4ecd4414 100644
--- a/src/tools/rust-analyzer/crates/hir/src/semantics.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/semantics.rs
@@ -170,6 +170,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.is_derive_annotated(item)
     }
 
+    /// Expand the macro call with a different token tree, mapping the `token_to_map` down into the
+    /// expansion. `token_to_map` should be a token from the `speculative args` node.
     pub fn speculative_expand(
         &self,
         actual_macro_call: &ast::MacroCall,
@@ -179,6 +181,8 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         self.imp.speculative_expand(actual_macro_call, speculative_args, token_to_map)
     }
 
+    /// Expand the macro call with a different item as the input, mapping the `token_to_map` down into the
+    /// expansion. `token_to_map` should be a token from the `speculative args` node.
     pub fn speculative_expand_attr_macro(
         &self,
         actual_macro_call: &ast::Item,
@@ -201,14 +205,22 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
         )
     }
 
-    /// Descend the token into macrocalls to its first mapped counterpart.
-    pub fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken {
-        self.imp.descend_into_macros_single(token)
+    /// Descend the token into its macro call if it is part of one, returning the token in the
+    /// expansion that it is associated with. If `offset` points into the token's range, it will
+    /// be considered for the mapping in case of inline format args.
+    pub fn descend_into_macros_single(&self, token: SyntaxToken, offset: TextSize) -> SyntaxToken {
+        self.imp.descend_into_macros_single(token, offset)
     }
 
-    /// Descend the token into macrocalls to all its mapped counterparts.
-    pub fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
-        self.imp.descend_into_macros(token)
+    /// Descend the token into its macro call if it is part of one, returning the tokens in the
+    /// expansion that it is associated with. If `offset` points into the token's range, it will
+    /// be considered for the mapping in case of inline format args.
+    pub fn descend_into_macros(
+        &self,
+        token: SyntaxToken,
+        offset: TextSize,
+    ) -> SmallVec<[SyntaxToken; 1]> {
+        self.imp.descend_into_macros(token, offset)
     }
 
     /// Descend the token into macrocalls to all its mapped counterparts that have the same text as the input token.
@@ -217,12 +229,17 @@ impl<'db, DB: HirDatabase> Semantics<'db, DB> {
     pub fn descend_into_macros_with_same_text(
         &self,
         token: SyntaxToken,
+        offset: TextSize,
     ) -> SmallVec<[SyntaxToken; 1]> {
-        self.imp.descend_into_macros_with_same_text(token)
+        self.imp.descend_into_macros_with_same_text(token, offset)
     }
 
-    pub fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken {
-        self.imp.descend_into_macros_with_kind_preference(token)
+    pub fn descend_into_macros_with_kind_preference(
+        &self,
+        token: SyntaxToken,
+        offset: TextSize,
+    ) -> SyntaxToken {
+        self.imp.descend_into_macros_with_kind_preference(token, offset)
     }
 
     /// Maps a node down by mapping its first and last token down.
@@ -606,7 +623,7 @@ impl<'db> SemanticsImpl<'db> {
         let macro_call_id = macro_call.as_call_id(self.db.upcast(), krate, |path| {
             resolver
                 .resolve_path_as_macro(self.db.upcast(), &path, Some(MacroSubNs::Bang))
-                .map(|it| macro_id_to_def_id(self.db.upcast(), it))
+                .map(|(it, _)| macro_id_to_def_id(self.db.upcast(), it))
         })?;
         hir_expand::db::expand_speculative(
             self.db.upcast(),
@@ -665,7 +682,7 @@ impl<'db> SemanticsImpl<'db> {
         };
 
         if first == last {
-            self.descend_into_macros_impl(first, &mut |InFile { value, .. }| {
+            self.descend_into_macros_impl(first, 0.into(), &mut |InFile { value, .. }| {
                 if let Some(node) = value.parent_ancestors().find_map(N::cast) {
                     res.push(node)
                 }
@@ -674,7 +691,7 @@ impl<'db> SemanticsImpl<'db> {
         } else {
             // Descend first and last token, then zip them to look for the node they belong to
             let mut scratch: SmallVec<[_; 1]> = smallvec![];
-            self.descend_into_macros_impl(first, &mut |token| {
+            self.descend_into_macros_impl(first, 0.into(), &mut |token| {
                 scratch.push(token);
                 false
             });
@@ -682,6 +699,7 @@ impl<'db> SemanticsImpl<'db> {
             let mut scratch = scratch.into_iter();
             self.descend_into_macros_impl(
                 last,
+                0.into(),
                 &mut |InFile { value: last, file_id: last_fid }| {
                     if let Some(InFile { value: first, file_id: first_fid }) = scratch.next() {
                         if first_fid == last_fid {
@@ -705,19 +723,27 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    fn descend_into_macros(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
+    fn descend_into_macros(
+        &self,
+        token: SyntaxToken,
+        offset: TextSize,
+    ) -> SmallVec<[SyntaxToken; 1]> {
         let mut res = smallvec![];
-        self.descend_into_macros_impl(token, &mut |InFile { value, .. }| {
+        self.descend_into_macros_impl(token, offset, &mut |InFile { value, .. }| {
             res.push(value);
             false
         });
         res
     }
 
-    fn descend_into_macros_with_same_text(&self, token: SyntaxToken) -> SmallVec<[SyntaxToken; 1]> {
+    fn descend_into_macros_with_same_text(
+        &self,
+        token: SyntaxToken,
+        offset: TextSize,
+    ) -> SmallVec<[SyntaxToken; 1]> {
         let text = token.text();
         let mut res = smallvec![];
-        self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| {
+        self.descend_into_macros_impl(token.clone(), offset, &mut |InFile { value, .. }| {
             if value.text() == text {
                 res.push(value);
             }
@@ -729,7 +755,11 @@ impl<'db> SemanticsImpl<'db> {
         res
     }
 
-    fn descend_into_macros_with_kind_preference(&self, token: SyntaxToken) -> SyntaxToken {
+    fn descend_into_macros_with_kind_preference(
+        &self,
+        token: SyntaxToken,
+        offset: TextSize,
+    ) -> SyntaxToken {
         let fetch_kind = |token: &SyntaxToken| match token.parent() {
             Some(node) => match node.kind() {
                 kind @ (SyntaxKind::NAME | SyntaxKind::NAME_REF) => {
@@ -741,7 +771,7 @@ impl<'db> SemanticsImpl<'db> {
         };
         let preferred_kind = fetch_kind(&token);
         let mut res = None;
-        self.descend_into_macros_impl(token.clone(), &mut |InFile { value, .. }| {
+        self.descend_into_macros_impl(token.clone(), offset, &mut |InFile { value, .. }| {
             if fetch_kind(&value) == preferred_kind {
                 res = Some(value);
                 true
@@ -755,9 +785,9 @@ impl<'db> SemanticsImpl<'db> {
         res.unwrap_or(token)
     }
 
-    fn descend_into_macros_single(&self, token: SyntaxToken) -> SyntaxToken {
+    fn descend_into_macros_single(&self, token: SyntaxToken, offset: TextSize) -> SyntaxToken {
         let mut res = token.clone();
-        self.descend_into_macros_impl(token, &mut |InFile { value, .. }| {
+        self.descend_into_macros_impl(token, offset, &mut |InFile { value, .. }| {
             res = value;
             true
         });
@@ -767,9 +797,13 @@ impl<'db> SemanticsImpl<'db> {
     fn descend_into_macros_impl(
         &self,
         token: SyntaxToken,
+        // FIXME: We might want this to be Option<TextSize> to be able to opt out of subrange
+        // mapping, specifically for node downmapping
+        offset: TextSize,
         f: &mut dyn FnMut(InFile<SyntaxToken>) -> bool,
     ) {
         let _p = profile::span("descend_into_macros");
+        let relative_token_offset = token.text_range().start().checked_sub(offset);
         let parent = match token.parent() {
             Some(it) => it,
             None => return,
@@ -796,7 +830,12 @@ impl<'db> SemanticsImpl<'db> {
                     self.cache(value, file_id);
                 }
 
-                let mapped_tokens = expansion_info.map_token_down(self.db.upcast(), item, token)?;
+                let mapped_tokens = expansion_info.map_token_down(
+                    self.db.upcast(),
+                    item,
+                    token,
+                    relative_token_offset,
+                )?;
                 let len = stack.len();
 
                 // requeue the tokens we got from mapping our current token down
@@ -943,7 +982,7 @@ impl<'db> SemanticsImpl<'db> {
         offset: TextSize,
     ) -> impl Iterator<Item = impl Iterator<Item = SyntaxNode> + '_> + '_ {
         node.token_at_offset(offset)
-            .map(move |token| self.descend_into_macros(token))
+            .map(move |token| self.descend_into_macros(token, offset))
             .map(|descendants| {
                 descendants.into_iter().map(move |it| self.token_ancestors_with_macros(it))
             })
@@ -1683,6 +1722,14 @@ impl SemanticsScope<'_> {
             |name, id| cb(name, id.into()),
         )
     }
+
+    pub fn extern_crates(&self) -> impl Iterator<Item = (Name, Module)> + '_ {
+        self.resolver.extern_crates_in_scope().map(|(name, id)| (name, Module { id }))
+    }
+
+    pub fn extern_crate_decls(&self) -> impl Iterator<Item = Name> + '_ {
+        self.resolver.extern_crate_decls_in_scope(self.db.upcast())
+    }
 }
 
 #[derive(Debug)]
diff --git a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
index 3499daf1140..f29fb1edf00 100644
--- a/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/source_analyzer.rs
@@ -487,7 +487,7 @@ impl SourceAnalyzer {
         let path = macro_call.value.path().and_then(|ast| Path::from_src(ast, &ctx))?;
         self.resolver
             .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Bang))
-            .map(|it| it.into())
+            .map(|(it, _)| it.into())
     }
 
     pub(crate) fn resolve_bind_pat_to_const(
@@ -760,7 +760,7 @@ impl SourceAnalyzer {
         let macro_call_id = macro_call.as_call_id(db.upcast(), krate, |path| {
             self.resolver
                 .resolve_path_as_macro(db.upcast(), &path, Some(MacroSubNs::Bang))
-                .map(|it| macro_id_to_def_id(db.upcast(), it))
+                .map(|(it, _)| macro_id_to_def_id(db.upcast(), it))
         })?;
         Some(macro_call_id.as_file()).filter(|it| it.expansion_level(db.upcast()) < 64)
     }
@@ -966,6 +966,7 @@ pub(crate) fn resolve_hir_path_as_attr_macro(
 ) -> Option<Macro> {
     resolver
         .resolve_path_as_macro(db.upcast(), path.mod_path()?, Some(MacroSubNs::Attr))
+        .map(|(it, _)| it)
         .map(Into::into)
 }
 
@@ -983,7 +984,7 @@ fn resolve_hir_path_(
                 res.map(|ty_ns| (ty_ns, path.segments().first()))
             }
             None => {
-                let (ty, remaining_idx) = resolver.resolve_path_in_type_ns(db.upcast(), path)?;
+                let (ty, remaining_idx, _) = resolver.resolve_path_in_type_ns(db.upcast(), path)?;
                 match remaining_idx {
                     Some(remaining_idx) => {
                         if remaining_idx + 1 == path.segments().len() {
@@ -1067,7 +1068,7 @@ fn resolve_hir_path_(
     let macros = || {
         resolver
             .resolve_path_as_macro(db.upcast(), path.mod_path()?, None)
-            .map(|def| PathResolution::Def(ModuleDef::Macro(def.into())))
+            .map(|(def, _)| PathResolution::Def(ModuleDef::Macro(def.into())))
     };
 
     if prefer_value_ns { values().or_else(types) } else { types().or_else(values) }
diff --git a/src/tools/rust-analyzer/crates/hir/src/symbols.rs b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
index 43d957412bc..ca7874c3683 100644
--- a/src/tools/rust-analyzer/crates/hir/src/symbols.rs
+++ b/src/tools/rust-analyzer/crates/hir/src/symbols.rs
@@ -2,8 +2,10 @@
 
 use base_db::FileRange;
 use hir_def::{
-    src::HasSource, AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId,
-    ModuleDefId, ModuleId, TraitId,
+    item_scope::ItemInNs,
+    src::{HasChildSource, HasSource},
+    AdtId, AssocItemId, DefWithBodyId, HasModule, ImplId, Lookup, MacroId, ModuleDefId, ModuleId,
+    TraitId,
 };
 use hir_expand::{HirFileId, InFile};
 use hir_ty::db::HirDatabase;
@@ -167,6 +169,40 @@ impl<'a> SymbolCollector<'a> {
             self.collect_from_impl(impl_id);
         }
 
+        // Record renamed imports.
+        // In case it imports multiple items under different namespaces we just pick one arbitrarily
+        // for now.
+        for id in scope.imports() {
+            let loc = id.import.lookup(self.db.upcast());
+            loc.id.item_tree(self.db.upcast());
+            let source = id.import.child_source(self.db.upcast());
+            let Some(use_tree_src) = source.value.get(id.idx) else { continue };
+            let Some(rename) = use_tree_src.rename() else { continue };
+            let Some(name) = rename.name() else { continue };
+
+            let res = scope.fully_resolve_import(self.db.upcast(), id);
+            res.iter_items().for_each(|(item, _)| {
+                let def = match item {
+                    ItemInNs::Types(def) | ItemInNs::Values(def) => def,
+                    ItemInNs::Macros(def) => ModuleDefId::from(def),
+                }
+                .into();
+                let dec_loc = DeclarationLocation {
+                    hir_file_id: source.file_id,
+                    ptr: SyntaxNodePtr::new(use_tree_src.syntax()),
+                    name_ptr: SyntaxNodePtr::new(name.syntax()),
+                };
+
+                self.symbols.push(FileSymbol {
+                    name: name.text().into(),
+                    def,
+                    container_name: self.current_container_name.clone(),
+                    loc: dec_loc,
+                    is_alias: false,
+                });
+            });
+        }
+
         for const_id in scope.unnamed_consts() {
             self.collect_from_body(const_id);
         }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
index 6aca716bb60..c0e5429a22c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/add_missing_impl_members.rs
@@ -422,7 +422,7 @@ impl<'x, 'y, T, V, U: Default> Trait<'x, 'y, T, V, U> for () {
         check_assist(
             add_missing_default_members,
             r#"
-struct Bar<const: N: bool> {
+struct Bar<const N: usize> {
     bar: [i32, N]
 }
 
@@ -439,7 +439,7 @@ impl<const X: usize, Y, Z> Foo<X, Z> for S<Y> {
     $0
 }"#,
             r#"
-struct Bar<const: N: bool> {
+struct Bar<const N: usize> {
     bar: [i32, N]
 }
 
@@ -484,6 +484,107 @@ impl<X> Foo<42, {20 + 22}, X> for () {
     }
 
     #[test]
+    fn test_const_substitution_with_defaults() {
+        check_assist(
+            add_missing_default_members,
+            r#"
+trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {
+    fn get_n(&self) -> usize { N }
+    fn get_m(&self) -> bool { M }
+    fn get_p(&self) -> char { P }
+    fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }
+}
+
+impl<X> Foo<X> for () {
+    $0
+}"#,
+            r#"
+trait Foo<T, const N: usize = 42, const M: bool = false, const P: char = 'a'> {
+    fn get_n(&self) -> usize { N }
+    fn get_m(&self) -> bool { M }
+    fn get_p(&self) -> char { P }
+    fn get_array(&self, arg: &T) -> [bool; N] { [M; N] }
+}
+
+impl<X> Foo<X> for () {
+    $0fn get_n(&self) -> usize { 42 }
+
+    fn get_m(&self) -> bool { false }
+
+    fn get_p(&self) -> char { 'a' }
+
+    fn get_array(&self, arg: &X) -> [bool; 42] { [false; 42] }
+}"#,
+        );
+    }
+
+    #[test]
+    fn test_const_substitution_with_defaults_2() {
+        check_assist(
+            add_missing_impl_members,
+            r#"
+mod m {
+    pub const LEN: usize = 42;
+    pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {
+        fn get_t(&self) -> T;
+    }
+}
+
+impl m::Foo for () {
+    $0
+}"#,
+            r#"
+mod m {
+    pub const LEN: usize = 42;
+    pub trait Foo<const M: usize = LEN, const N: usize = M, T = [bool; N]> {
+        fn get_t(&self) -> T;
+    }
+}
+
+impl m::Foo for () {
+    fn get_t(&self) -> [bool; m::LEN] {
+        ${0:todo!()}
+    }
+}"#,
+        )
+    }
+
+    #[test]
+    fn test_const_substitution_with_defaults_3() {
+        check_assist(
+            add_missing_default_members,
+            r#"
+mod m {
+    pub const VAL: usize = 0;
+
+    pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {
+        fn get_n(&self) -> usize { N }
+        fn get_m(&self) -> usize { M }
+    }
+}
+
+impl m::Foo for () {
+    $0
+}"#,
+            r#"
+mod m {
+    pub const VAL: usize = 0;
+
+    pub trait Foo<const N: usize = {40 + 2}, const M: usize = {VAL + 1}> {
+        fn get_n(&self) -> usize { N }
+        fn get_m(&self) -> usize { M }
+    }
+}
+
+impl m::Foo for () {
+    $0fn get_n(&self) -> usize { {40 + 2} }
+
+    fn get_m(&self) -> usize { {m::VAL + 1} }
+}"#,
+        )
+    }
+
+    #[test]
     fn test_cursor_after_empty_impl_def() {
         check_assist(
             add_missing_impl_members,
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
index 57cfa17cc8e..66bc2f6dadc 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/apply_demorgan.rs
@@ -1,6 +1,10 @@
 use std::collections::VecDeque;
 
-use syntax::ast::{self, AstNode};
+use syntax::{
+    ast::{self, AstNode, Expr::BinExpr},
+    ted::{self, Position},
+    SyntaxKind,
+};
 
 use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKind, Assists};
 
@@ -23,121 +27,117 @@ use crate::{utils::invert_boolean_expression, AssistContext, AssistId, AssistKin
 // }
 // ```
 pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<()> {
-    let expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
-    let op = expr.op_kind()?;
-    let op_range = expr.op_token()?.text_range();
+    let mut bin_expr = ctx.find_node_at_offset::<ast::BinExpr>()?;
+    let op = bin_expr.op_kind()?;
+    let op_range = bin_expr.op_token()?.text_range();
 
-    let opposite_op = match op {
-        ast::BinaryOp::LogicOp(ast::LogicOp::And) => "||",
-        ast::BinaryOp::LogicOp(ast::LogicOp::Or) => "&&",
-        _ => return None,
-    };
-
-    let cursor_in_range = op_range.contains_range(ctx.selection_trimmed());
-    if !cursor_in_range {
+    // Is the cursor on the expression's logical operator?
+    if !op_range.contains_range(ctx.selection_trimmed()) {
         return None;
     }
 
-    let mut expr = expr;
-
     // Walk up the tree while we have the same binary operator
-    while let Some(parent_expr) = expr.syntax().parent().and_then(ast::BinExpr::cast) {
-        match expr.op_kind() {
+    while let Some(parent_expr) = bin_expr.syntax().parent().and_then(ast::BinExpr::cast) {
+        match parent_expr.op_kind() {
             Some(parent_op) if parent_op == op => {
-                expr = parent_expr;
+                bin_expr = parent_expr;
             }
             _ => break,
         }
     }
 
-    let mut expr_stack = vec![expr.clone()];
-    let mut terms = Vec::new();
-    let mut op_ranges = Vec::new();
-
-    // Find all the children with the same binary operator
-    while let Some(expr) = expr_stack.pop() {
-        let mut traverse_bin_expr_arm = |expr| {
-            if let ast::Expr::BinExpr(bin_expr) = expr {
-                if let Some(expr_op) = bin_expr.op_kind() {
-                    if expr_op == op {
-                        expr_stack.push(bin_expr);
-                    } else {
-                        terms.push(ast::Expr::BinExpr(bin_expr));
-                    }
+    let op = bin_expr.op_kind()?;
+    let inv_token = match op {
+        ast::BinaryOp::LogicOp(ast::LogicOp::And) => SyntaxKind::PIPE2,
+        ast::BinaryOp::LogicOp(ast::LogicOp::Or) => SyntaxKind::AMP2,
+        _ => return None,
+    };
+
+    let demorganed = bin_expr.clone_subtree().clone_for_update();
+
+    ted::replace(demorganed.op_token()?, ast::make::token(inv_token));
+    let mut exprs = VecDeque::from(vec![
+        (bin_expr.lhs()?, demorganed.lhs()?),
+        (bin_expr.rhs()?, demorganed.rhs()?),
+    ]);
+
+    while let Some((expr, dm)) = exprs.pop_front() {
+        if let BinExpr(bin_expr) = &expr {
+            if let BinExpr(cbin_expr) = &dm {
+                if op == bin_expr.op_kind()? {
+                    ted::replace(cbin_expr.op_token()?, ast::make::token(inv_token));
+                    exprs.push_back((bin_expr.lhs()?, cbin_expr.lhs()?));
+                    exprs.push_back((bin_expr.rhs()?, cbin_expr.rhs()?));
                 } else {
-                    terms.push(ast::Expr::BinExpr(bin_expr));
+                    let mut inv = invert_boolean_expression(expr);
+                    if inv.needs_parens_in(dm.syntax().parent()?) {
+                        inv = ast::make::expr_paren(inv).clone_for_update();
+                    }
+                    ted::replace(dm.syntax(), inv.syntax());
                 }
             } else {
-                terms.push(expr);
+                return None;
             }
-        };
-
-        op_ranges.extend(expr.op_token().map(|t| t.text_range()));
-        traverse_bin_expr_arm(expr.lhs()?);
-        traverse_bin_expr_arm(expr.rhs()?);
+        } else {
+            let mut inv = invert_boolean_expression(dm.clone_subtree()).clone_for_update();
+            if inv.needs_parens_in(dm.syntax().parent()?) {
+                inv = ast::make::expr_paren(inv).clone_for_update();
+            }
+            ted::replace(dm.syntax(), inv.syntax());
+        }
     }
 
+    let dm_lhs = demorganed.lhs()?;
+
     acc.add(
         AssistId("apply_demorgan", AssistKind::RefactorRewrite),
         "Apply De Morgan's law",
         op_range,
         |edit| {
-            terms.sort_by_key(|t| t.syntax().text_range().start());
-            let mut terms = VecDeque::from(terms);
-
-            let paren_expr = expr.syntax().parent().and_then(ast::ParenExpr::cast);
-
+            let paren_expr = bin_expr.syntax().parent().and_then(ast::ParenExpr::cast);
             let neg_expr = paren_expr
                 .clone()
                 .and_then(|paren_expr| paren_expr.syntax().parent())
                 .and_then(ast::PrefixExpr::cast)
                 .and_then(|prefix_expr| {
-                    if prefix_expr.op_kind().unwrap() == ast::UnaryOp::Not {
+                    if prefix_expr.op_kind()? == ast::UnaryOp::Not {
                         Some(prefix_expr)
                     } else {
                         None
                     }
                 });
 
-            for op_range in op_ranges {
-                edit.replace(op_range, opposite_op);
-            }
-
             if let Some(paren_expr) = paren_expr {
-                for term in terms {
-                    let range = term.syntax().text_range();
-                    let not_term = invert_boolean_expression(term);
-
-                    edit.replace(range, not_term.syntax().text());
-                }
-
                 if let Some(neg_expr) = neg_expr {
                     cov_mark::hit!(demorgan_double_negation);
-                    edit.replace(neg_expr.op_token().unwrap().text_range(), "");
+                    edit.replace_ast(ast::Expr::PrefixExpr(neg_expr), demorganed.into());
                 } else {
                     cov_mark::hit!(demorgan_double_parens);
-                    edit.replace(paren_expr.l_paren_token().unwrap().text_range(), "!(");
+                    ted::insert_all_raw(
+                        Position::before(dm_lhs.syntax()),
+                        vec![
+                            syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)),
+                            syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)),
+                        ],
+                    );
+
+                    ted::append_child_raw(
+                        demorganed.syntax(),
+                        syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::R_PAREN)),
+                    );
+
+                    edit.replace_ast(ast::Expr::ParenExpr(paren_expr), demorganed.into());
                 }
             } else {
-                if let Some(lhs) = terms.pop_front() {
-                    let lhs_range = lhs.syntax().text_range();
-                    let not_lhs = invert_boolean_expression(lhs);
-
-                    edit.replace(lhs_range, format!("!({not_lhs}"));
-                }
-
-                if let Some(rhs) = terms.pop_back() {
-                    let rhs_range = rhs.syntax().text_range();
-                    let not_rhs = invert_boolean_expression(rhs);
-
-                    edit.replace(rhs_range, format!("{not_rhs})"));
-                }
-
-                for term in terms {
-                    let term_range = term.syntax().text_range();
-                    let not_term = invert_boolean_expression(term);
-                    edit.replace(term_range, not_term.to_string());
-                }
+                ted::insert_all_raw(
+                    Position::before(dm_lhs.syntax()),
+                    vec![
+                        syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::BANG)),
+                        syntax::NodeOrToken::Token(ast::make::token(SyntaxKind::L_PAREN)),
+                    ],
+                );
+                ted::append_child_raw(demorganed.syntax(), ast::make::token(SyntaxKind::R_PAREN));
+                edit.replace_ast(bin_expr, demorganed);
             }
         },
     )
@@ -145,9 +145,8 @@ pub(crate) fn apply_demorgan(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opti
 
 #[cfg(test)]
 mod tests {
-    use crate::tests::{check_assist, check_assist_not_applicable};
-
     use super::*;
+    use crate::tests::{check_assist, check_assist_not_applicable};
 
     #[test]
     fn demorgan_handles_leq() {
@@ -213,7 +212,7 @@ fn f() { !(S <= S || S < S) }
     #[test]
     fn demorgan_doesnt_double_negation() {
         cov_mark::check!(demorgan_double_negation);
-        check_assist(apply_demorgan, "fn f() { !(x ||$0 x) }", "fn f() { (!x && !x) }")
+        check_assist(apply_demorgan, "fn f() { !(x ||$0 x) }", "fn f() { !x && !x }")
     }
 
     #[test]
@@ -222,13 +221,38 @@ fn f() { !(S <= S || S < S) }
         check_assist(apply_demorgan, "fn f() { (x ||$0 x) }", "fn f() { !(!x && !x) }")
     }
 
-    // https://github.com/rust-lang/rust-analyzer/issues/10963
+    // FIXME : This needs to go.
+    // // https://github.com/rust-lang/rust-analyzer/issues/10963
+    // #[test]
+    // fn demorgan_doesnt_hang() {
+    //     check_assist(
+    //         apply_demorgan,
+    //         "fn f() { 1 || 3 &&$0 4 || 5 }",
+    //         "fn f() { !(!1 || !3 || !4) || 5 }",
+    //     )
+    // }
+
+    #[test]
+    fn demorgan_keep_pars_for_op_precedence() {
+        check_assist(
+            apply_demorgan,
+            "fn main() {
+    let _ = !(!a ||$0 !(b || c));
+}
+",
+            "fn main() {
+    let _ = a && (b || c);
+}
+",
+        );
+    }
+
     #[test]
-    fn demorgan_doesnt_hang() {
+    fn demorgan_removes_pars_in_eq_precedence() {
         check_assist(
             apply_demorgan,
-            "fn f() { 1 || 3 &&$0 4 || 5 }",
-            "fn f() { !(!1 || !3 || !4) || 5 }",
+            "fn() { let x = a && !(!b |$0| !c); }",
+            "fn() { let x = a && b && c; }",
         )
     }
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
index fe1cb6fce36..76f021ed912 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_named_struct_to_tuple_struct.rs
@@ -161,9 +161,9 @@ fn process_struct_name_reference(
     let path_segment = name_ref.syntax().parent().and_then(ast::PathSegment::cast)?;
     // A `PathSegment` always belongs to a `Path`, so there's at least one `Path` at this point.
     let full_path =
-        path_segment.syntax().parent()?.ancestors().map_while(ast::Path::cast).last().unwrap();
+        path_segment.syntax().parent()?.ancestors().map_while(ast::Path::cast).last()?;
 
-    if full_path.segment().unwrap().name_ref()? != *name_ref {
+    if full_path.segment()?.name_ref()? != *name_ref {
         // `name_ref` isn't the last segment of the path, so `full_path` doesn't point to the
         // struct we want to edit.
         return None;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
index dcb96ab8af4..7d0e424769e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/convert_to_guarded_return.rs
@@ -58,7 +58,7 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<'
                     return None;
                 }
 
-                let bound_ident = pat.fields().next().unwrap();
+                let bound_ident = pat.fields().next()?;
                 if !ast::IdentPat::can_cast(bound_ident.syntax().kind()) {
                     return None;
                 }
@@ -108,6 +108,15 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<'
 
     then_block.syntax().last_child_or_token().filter(|t| t.kind() == T!['}'])?;
 
+    let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update();
+
+    let end_of_then = then_block_items.syntax().last_child_or_token()?;
+    let end_of_then = if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
+        end_of_then.prev_sibling_or_token()?
+    } else {
+        end_of_then
+    };
+
     let target = if_expr.syntax().text_range();
     acc.add(
         AssistId("convert_to_guarded_return", AssistKind::RefactorRewrite),
@@ -141,16 +150,6 @@ pub(crate) fn convert_to_guarded_return(acc: &mut Assists, ctx: &AssistContext<'
                 }
             };
 
-            let then_block_items = then_block.dedent(IndentLevel(1)).clone_for_update();
-
-            let end_of_then = then_block_items.syntax().last_child_or_token().unwrap();
-            let end_of_then =
-                if end_of_then.prev_sibling_or_token().map(|n| n.kind()) == Some(WHITESPACE) {
-                    end_of_then.prev_sibling_or_token().unwrap()
-                } else {
-                    end_of_then
-                };
-
             let then_statements = replacement
                 .children_with_tokens()
                 .chain(
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
index 4f3b6e0c287..c3d925cb26c 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_expressions_from_format_string.rs
@@ -48,7 +48,7 @@ pub(crate) fn extract_expressions_from_format_string(
     let tt = fmt_string.syntax().parent().and_then(ast::TokenTree::cast)?;
 
     let expanded_t = ast::String::cast(
-        ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone()),
+        ctx.sema.descend_into_macros_with_kind_preference(fmt_string.syntax().clone(), 0.into()),
     )?;
     if !is_format_string(&expanded_t) {
         return None;
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
index b8b781ea48d..ea7a21e77a4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/extract_function.rs
@@ -750,7 +750,7 @@ impl FunctionBody {
                         .descendants_with_tokens()
                         .filter_map(SyntaxElement::into_token)
                         .filter(|it| matches!(it.kind(), SyntaxKind::IDENT | T![self]))
-                        .flat_map(|t| sema.descend_into_macros(t))
+                        .flat_map(|t| sema.descend_into_macros(t, 0.into()))
                         .for_each(|t| add_name_if_local(t.parent().and_then(ast::NameRef::cast)));
                 }
             }
@@ -810,7 +810,7 @@ impl FunctionBody {
                         (true, konst.body(), Some(sema.to_def(&konst)?.ty(sema.db)))
                     },
                     ast::ConstParam(cp) => {
-                        (true, cp.default_val(), Some(sema.to_def(&cp)?.ty(sema.db)))
+                        (true, cp.default_val()?.expr(), Some(sema.to_def(&cp)?.ty(sema.db)))
                     },
                     ast::ConstBlockPat(cbp) => {
                         let expr = cbp.block_expr().map(ast::Expr::BlockExpr);
@@ -1385,31 +1385,30 @@ enum FlowHandler {
 
 impl FlowHandler {
     fn from_ret_ty(fun: &Function, ret_ty: &FunType) -> FlowHandler {
-        match &fun.control_flow.kind {
-            None => FlowHandler::None,
-            Some(flow_kind) => {
-                let action = flow_kind.clone();
-                if let FunType::Unit = ret_ty {
-                    match flow_kind {
-                        FlowKind::Return(None)
-                        | FlowKind::Break(_, None)
-                        | FlowKind::Continue(_) => FlowHandler::If { action },
-                        FlowKind::Return(_) | FlowKind::Break(_, _) => {
-                            FlowHandler::IfOption { action }
-                        }
-                        FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
-                    }
-                } else {
-                    match flow_kind {
-                        FlowKind::Return(None)
-                        | FlowKind::Break(_, None)
-                        | FlowKind::Continue(_) => FlowHandler::MatchOption { none: action },
-                        FlowKind::Return(_) | FlowKind::Break(_, _) => {
-                            FlowHandler::MatchResult { err: action }
-                        }
-                        FlowKind::Try { kind } => FlowHandler::Try { kind: kind.clone() },
-                    }
+        if fun.contains_tail_expr {
+            return FlowHandler::None;
+        }
+        let Some(action) = fun.control_flow.kind.clone() else {
+            return FlowHandler::None;
+        };
+
+        if let FunType::Unit = ret_ty {
+            match action {
+                FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
+                    FlowHandler::If { action }
+                }
+                FlowKind::Return(_) | FlowKind::Break(_, _) => FlowHandler::IfOption { action },
+                FlowKind::Try { kind } => FlowHandler::Try { kind },
+            }
+        } else {
+            match action {
+                FlowKind::Return(None) | FlowKind::Break(_, None) | FlowKind::Continue(_) => {
+                    FlowHandler::MatchOption { none: action }
+                }
+                FlowKind::Return(_) | FlowKind::Break(_, _) => {
+                    FlowHandler::MatchResult { err: action }
                 }
+                FlowKind::Try { kind } => FlowHandler::Try { kind },
             }
         }
     }
@@ -1654,11 +1653,7 @@ impl Function {
 
     fn make_ret_ty(&self, ctx: &AssistContext<'_>, module: hir::Module) -> Option<ast::RetType> {
         let fun_ty = self.return_type(ctx);
-        let handler = if self.contains_tail_expr {
-            FlowHandler::None
-        } else {
-            FlowHandler::from_ret_ty(self, &fun_ty)
-        };
+        let handler = FlowHandler::from_ret_ty(self, &fun_ty);
         let ret_ty = match &handler {
             FlowHandler::None => {
                 if matches!(fun_ty, FunType::Unit) {
@@ -1728,11 +1723,7 @@ fn make_body(
     fun: &Function,
 ) -> ast::BlockExpr {
     let ret_ty = fun.return_type(ctx);
-    let handler = if fun.contains_tail_expr {
-        FlowHandler::None
-    } else {
-        FlowHandler::from_ret_ty(fun, &ret_ty)
-    };
+    let handler = FlowHandler::from_ret_ty(fun, &ret_ty);
 
     let block = match &fun.body {
         FunctionBody::Expr(expr) => {
@@ -4471,7 +4462,7 @@ async fn foo() -> Result<(), ()> {
 "#,
             r#"
 async fn foo() -> Result<(), ()> {
-    fun_name().await?
+    fun_name().await
 }
 
 async fn $0fun_name() -> Result<(), ()> {
@@ -4690,7 +4681,7 @@ fn $0fun_name() {
         check_assist(
             extract_function,
             r#"
-//- minicore: result
+//- minicore: result, try
 fn foo() -> Result<(), i64> {
     $0Result::<i32, i64>::Ok(0)?;
     Ok(())$0
@@ -4698,7 +4689,7 @@ fn foo() -> Result<(), i64> {
 "#,
             r#"
 fn foo() -> Result<(), i64> {
-    fun_name()?
+    fun_name()
 }
 
 fn $0fun_name() -> Result<(), i64> {
@@ -5754,6 +5745,34 @@ fn $0fun_name<T, V>(t: T, v: V) -> i32 where T: Into<i32> + Copy, V: Into<i32> {
     }
 
     #[test]
+    fn tail_expr_no_extra_control_flow() {
+        check_assist(
+            extract_function,
+            r#"
+//- minicore: result
+fn fallible() -> Result<(), ()> {
+    $0if true {
+        return Err(());
+    }
+    Ok(())$0
+}
+"#,
+            r#"
+fn fallible() -> Result<(), ()> {
+    fun_name()
+}
+
+fn $0fun_name() -> Result<(), ()> {
+    if true {
+        return Err(());
+    }
+    Ok(())
+}
+"#,
+        );
+    }
+
+    #[test]
     fn non_tail_expr_of_tail_expr_loop() {
         check_assist(
             extract_function,
@@ -5800,12 +5819,6 @@ fn $0fun_name() -> ControlFlow<()> {
             extract_function,
             r#"
 //- minicore: option, try
-impl<T> core::ops::Try for Option<T> {
-    type Output = T;
-    type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
 fn f() -> Option<()> {
     if true {
         let a = $0if true {
@@ -5820,12 +5833,6 @@ fn f() -> Option<()> {
 }
 "#,
             r#"
-impl<T> core::ops::Try for Option<T> {
-    type Output = T;
-    type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
 fn f() -> Option<()> {
     if true {
         let a = fun_name()?;;
@@ -5852,12 +5859,6 @@ fn $0fun_name() -> Option<()> {
             extract_function,
             r#"
 //- minicore: option, try
-impl<T> core::ops::Try for Option<T> {
-    type Output = T;
-    type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
 fn f() -> Option<()> {
     if true {
         $0{
@@ -5874,15 +5875,9 @@ fn f() -> Option<()> {
 }
 "#,
             r#"
-impl<T> core::ops::Try for Option<T> {
-    type Output = T;
-    type Residual = Option<!>;
-}
-impl<T> core::ops::FromResidual for Option<T> {}
-
 fn f() -> Option<()> {
     if true {
-        fun_name()?
+        fun_name()
     } else {
         None
     }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
index 31fc69562c9..bbac0a26ea4 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_delegate_methods.rs
@@ -95,6 +95,9 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
         let Some(impl_def) = find_struct_impl(ctx, &adt, std::slice::from_ref(&name)) else {
             continue;
         };
+
+        let field = make::ext::field_from_idents(["self", &field_name])?;
+
         acc.add_group(
             &GroupLabel("Generate delegate methods…".to_owned()),
             AssistId("generate_delegate_methods", AssistKind::Generate),
@@ -115,11 +118,7 @@ pub(crate) fn generate_delegate_methods(acc: &mut Assists, ctx: &AssistContext<'
                     Some(list) => convert_param_list_to_arg_list(list),
                     None => make::arg_list([]),
                 };
-                let tail_expr = make::expr_method_call(
-                    make::ext::field_from_idents(["self", &field_name]).unwrap(), // This unwrap is ok because we have at least 1 arg in the list
-                    make::name_ref(&name),
-                    arg_list,
-                );
+                let tail_expr = make::expr_method_call(field, make::name_ref(&name), arg_list);
                 let ret_type = method_source.ret_type();
                 let is_async = method_source.async_token().is_some();
                 let is_const = method_source.const_token().is_some();
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs
index 747f70f9f6f..53ba144ba9e 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/generate_derive.rs
@@ -27,13 +27,19 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
     let cap = ctx.config.snippet_cap?;
     let nominal = ctx.find_node_at_offset::<ast::Adt>()?;
     let target = nominal.syntax().text_range();
+    let derive_attr = nominal
+        .attrs()
+        .filter_map(|x| x.as_simple_call())
+        .filter(|(name, _arg)| name == "derive")
+        .map(|(_name, arg)| arg)
+        .next();
+
+    let delimiter = match &derive_attr {
+        None => None,
+        Some(tt) => Some(tt.right_delimiter_token()?),
+    };
+
     acc.add(AssistId("generate_derive", AssistKind::Generate), "Add `#[derive]`", target, |edit| {
-        let derive_attr = nominal
-            .attrs()
-            .filter_map(|x| x.as_simple_call())
-            .filter(|(name, _arg)| name == "derive")
-            .map(|(_name, arg)| arg)
-            .next();
         match derive_attr {
             None => {
                 let derive = make::attr_outer(make::meta_token_tree(
@@ -45,16 +51,23 @@ pub(crate) fn generate_derive(acc: &mut Assists, ctx: &AssistContext<'_>) -> Opt
                 let nominal = edit.make_mut(nominal);
                 nominal.add_attr(derive.clone());
 
+                let delimiter = derive
+                    .meta()
+                    .expect("make::attr_outer was expected to have Meta")
+                    .token_tree()
+                    .expect("failed to get token tree out of Meta")
+                    .r_paren_token()
+                    .expect("make::attr_outer was expected to have a R_PAREN");
+
+                edit.add_tabstop_before_token(cap, delimiter);
+            }
+            Some(_) => {
+                // Just move the cursor.
                 edit.add_tabstop_before_token(
                     cap,
-                    derive.meta().unwrap().token_tree().unwrap().r_paren_token().unwrap(),
+                    delimiter.expect("Right delim token could not be found."),
                 );
             }
-            Some(tt) => {
-                // Just move the cursor.
-                let tt = edit.make_mut(tt);
-                edit.add_tabstop_before_token(cap, tt.right_delimiter_token().unwrap());
-            }
         };
     })
 }
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
index a403d5bc672..e2b82223289 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_dbg.rs
@@ -39,14 +39,11 @@ pub(crate) fn remove_dbg(acc: &mut Assists, ctx: &AssistContext<'_>) -> Option<(
 
     let replacements =
         macro_calls.into_iter().filter_map(compute_dbg_replacement).collect::<Vec<_>>();
-    if replacements.is_empty() {
-        return None;
-    }
 
     acc.add(
         AssistId("remove_dbg", AssistKind::Refactor),
         "Remove dbg!()",
-        replacements.iter().map(|&(range, _)| range).reduce(|acc, range| acc.cover(range)).unwrap(),
+        replacements.iter().map(|&(range, _)| range).reduce(|acc, range| acc.cover(range))?,
         |builder| {
             for (range, expr) in replacements {
                 if let Some(expr) = expr {
diff --git a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
index dd4839351fb..5fcab8c02b0 100644
--- a/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
+++ b/src/tools/rust-analyzer/crates/ide-assists/src/handlers/remove_unused_imports.rs
@@ -67,7 +67,7 @@ pub(crate) fn remove_unused_imports(acc: &mut Assists, ctx: &AssistContext<'_>)
                 // This case maps to the situation where the * token is braced.
                 // In this case, the parent use tree's path is the one we should use to resolve the glob.
                 match u.syntax().ancestors().skip(1).find_map(ast::UseTree::cast) {
-                    Some(parent_u) if parent_u.path().is_some() => parent_u.path().unwrap(),
+                    Some(parent_u) if parent_u.path().is_some() => parent_u.path()?,
                     _ => return None,
                 }
             } else {
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
index 480cb77b4fd..f60ac150164 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions.rs
@@ -20,6 +20,7 @@ pub(crate) mod r#type;
 pub(crate) mod use_;
 pub(crate) mod vis;
 pub(crate) mod env_vars;
+pub(crate) mod extern_crate;
 
 use std::iter;
 
@@ -703,7 +704,9 @@ pub(super) fn complete_name_ref(
                         TypeLocation::TypeAscription(ascription) => {
                             r#type::complete_ascribed_type(acc, ctx, path_ctx, ascription);
                         }
-                        TypeLocation::GenericArgList(_)
+                        TypeLocation::GenericArg { .. }
+                        | TypeLocation::AssocConstEq
+                        | TypeLocation::AssocTypeEq
                         | TypeLocation::TypeBound
                         | TypeLocation::ImplTarget
                         | TypeLocation::ImplTrait
@@ -737,6 +740,7 @@ pub(super) fn complete_name_ref(
                 }
             }
         }
+        NameRefKind::ExternCrate => extern_crate::complete_extern_crate(acc, ctx),
         NameRefKind::DotAccess(dot_access) => {
             flyimport::import_on_the_fly_dot(acc, ctx, dot_access);
             dot::complete_dot(acc, ctx, dot_access);
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs
new file mode 100644
index 00000000000..0d0e143f5f6
--- /dev/null
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/extern_crate.rs
@@ -0,0 +1,71 @@
+//! Completion for extern crates
+
+use hir::{HasAttrs, Name};
+use ide_db::SymbolKind;
+
+use crate::{context::CompletionContext, CompletionItem, CompletionItemKind};
+
+use super::Completions;
+
+pub(crate) fn complete_extern_crate(acc: &mut Completions, ctx: &CompletionContext<'_>) {
+    let imported_extern_crates: Vec<Name> = ctx.scope.extern_crate_decls().collect();
+
+    for (name, module) in ctx.scope.extern_crates() {
+        if imported_extern_crates.contains(&name) {
+            continue;
+        }
+
+        let mut item = CompletionItem::new(
+            CompletionItemKind::SymbolKind(SymbolKind::Module),
+            ctx.source_range(),
+            name.to_smol_str(),
+        );
+        item.set_documentation(module.docs(ctx.db));
+
+        item.add_to(acc, ctx.db);
+    }
+}
+
+#[cfg(test)]
+mod test {
+    use crate::tests::completion_list_no_kw;
+
+    #[test]
+    fn can_complete_extern_crate() {
+        let case = r#"
+//- /lib.rs crate:other_crate_a
+// nothing here
+//- /other_crate_b.rs crate:other_crate_b
+pub mod good_mod{}
+//- /lib.rs crate:crate_c
+// nothing here
+//- /lib.rs crate:lib deps:other_crate_a,other_crate_b,crate_c extern-prelude:other_crate_a
+extern crate oth$0
+mod other_mod {}
+"#;
+
+        let completion_list = completion_list_no_kw(case);
+
+        assert_eq!("md other_crate_a\n".to_string(), completion_list);
+    }
+
+    #[test]
+    fn will_not_complete_existing_import() {
+        let case = r#"
+//- /lib.rs crate:other_crate_a
+// nothing here
+//- /lib.rs crate:crate_c
+// nothing here
+//- /lib.rs crate:other_crate_b
+//
+//- /lib.rs crate:lib deps:other_crate_a,other_crate_b,crate_c extern-prelude:other_crate_a,other_crate_b
+extern crate other_crate_b;
+extern crate oth$0
+mod other_mod {}
+"#;
+
+        let completion_list = completion_list_no_kw(case);
+
+        assert_eq!("md other_crate_a\n".to_string(), completion_list);
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
index e4705475638..a30fd13b1d5 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/completions/type.rs
@@ -1,7 +1,7 @@
 //! Completion of names from the current scope in type position.
 
 use hir::{HirDisplay, ScopeDef};
-use syntax::{ast, AstNode, SyntaxKind};
+use syntax::{ast, AstNode};
 
 use crate::{
     context::{PathCompletionCtx, Qualified, TypeAscriptionTarget, TypeLocation},
@@ -20,16 +20,15 @@ pub(crate) fn complete_type_path(
     let scope_def_applicable = |def| {
         use hir::{GenericParam::*, ModuleDef::*};
         match def {
-            ScopeDef::GenericParam(LifetimeParam(_)) | ScopeDef::Label(_) => false,
+            ScopeDef::GenericParam(LifetimeParam(_)) => location.complete_lifetimes(),
+            ScopeDef::Label(_) => false,
             // no values in type places
             ScopeDef::ModuleDef(Function(_) | Variant(_) | Static(_)) | ScopeDef::Local(_) => false,
             // unless its a constant in a generic arg list position
             ScopeDef::ModuleDef(Const(_)) | ScopeDef::GenericParam(ConstParam(_)) => {
-                matches!(location, TypeLocation::GenericArgList(_))
-            }
-            ScopeDef::ImplSelfType(_) => {
-                !matches!(location, TypeLocation::ImplTarget | TypeLocation::ImplTrait)
+                location.complete_consts()
             }
+            ScopeDef::ImplSelfType(_) => location.complete_self_type(),
             // Don't suggest attribute macros and derives.
             ScopeDef::ModuleDef(Macro(mac)) => mac.is_fn_like(ctx.db),
             // Type things are fine
@@ -38,12 +37,12 @@ pub(crate) fn complete_type_path(
             )
             | ScopeDef::AdtSelfType(_)
             | ScopeDef::Unknown
-            | ScopeDef::GenericParam(TypeParam(_)) => true,
+            | ScopeDef::GenericParam(TypeParam(_)) => location.complete_types(),
         }
     };
 
     let add_assoc_item = |acc: &mut Completions, item| match item {
-        hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArgList(_)) => {
+        hir::AssocItem::Const(ct) if matches!(location, TypeLocation::GenericArg { .. }) => {
             acc.add_const(ctx, ct)
         }
         hir::AssocItem::Function(_) | hir::AssocItem::Const(_) => (),
@@ -157,56 +156,30 @@ pub(crate) fn complete_type_path(
                     });
                     return;
                 }
-                TypeLocation::GenericArgList(Some(arg_list)) => {
-                    let in_assoc_type_arg = ctx
-                        .original_token
-                        .parent_ancestors()
-                        .any(|node| node.kind() == SyntaxKind::ASSOC_TYPE_ARG);
-
-                    if !in_assoc_type_arg {
-                        if let Some(path_seg) =
-                            arg_list.syntax().parent().and_then(ast::PathSegment::cast)
-                        {
-                            if path_seg
-                                .syntax()
-                                .ancestors()
-                                .find_map(ast::TypeBound::cast)
-                                .is_some()
-                            {
-                                if let Some(hir::PathResolution::Def(hir::ModuleDef::Trait(
-                                    trait_,
-                                ))) = ctx.sema.resolve_path(&path_seg.parent_path())
-                                {
-                                    let arg_idx = arg_list
-                                        .generic_args()
-                                        .filter(|arg| {
-                                            arg.syntax().text_range().end()
-                                                < ctx.original_token.text_range().start()
-                                        })
-                                        .count();
-
-                                    let n_required_params =
-                                        trait_.type_or_const_param_count(ctx.sema.db, true);
-                                    if arg_idx >= n_required_params {
-                                        trait_
-                                            .items_with_supertraits(ctx.sema.db)
-                                            .into_iter()
-                                            .for_each(|it| {
-                                                if let hir::AssocItem::TypeAlias(alias) = it {
-                                                    cov_mark::hit!(
-                                                        complete_assoc_type_in_generics_list
-                                                    );
-                                                    acc.add_type_alias_with_eq(ctx, alias);
-                                                }
-                                            });
-
-                                        let n_params =
-                                            trait_.type_or_const_param_count(ctx.sema.db, false);
-                                        if arg_idx >= n_params {
-                                            return; // only show assoc types
-                                        }
-                                    }
+                TypeLocation::GenericArg {
+                    args: Some(arg_list), of_trait: Some(trait_), ..
+                } => {
+                    if arg_list.syntax().ancestors().find_map(ast::TypeBound::cast).is_some() {
+                        let arg_idx = arg_list
+                            .generic_args()
+                            .filter(|arg| {
+                                arg.syntax().text_range().end()
+                                    < ctx.original_token.text_range().start()
+                            })
+                            .count();
+
+                        let n_required_params = trait_.type_or_const_param_count(ctx.sema.db, true);
+                        if arg_idx >= n_required_params {
+                            trait_.items_with_supertraits(ctx.sema.db).into_iter().for_each(|it| {
+                                if let hir::AssocItem::TypeAlias(alias) = it {
+                                    cov_mark::hit!(complete_assoc_type_in_generics_list);
+                                    acc.add_type_alias_with_eq(ctx, alias);
                                 }
+                            });
+
+                            let n_params = trait_.type_or_const_param_count(ctx.sema.db, false);
+                            if arg_idx >= n_params {
+                                return; // only show assoc types
                             }
                         }
                     }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
index 3cb65b2729a..0da7ba6d000 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context.rs
@@ -155,13 +155,63 @@ pub(crate) struct ExprCtx {
 pub(crate) enum TypeLocation {
     TupleField,
     TypeAscription(TypeAscriptionTarget),
-    GenericArgList(Option<ast::GenericArgList>),
+    /// Generic argument position e.g. `Foo<$0>`
+    GenericArg {
+        /// The generic argument list containing the generic arg
+        args: Option<ast::GenericArgList>,
+        /// `Some(trait_)` if `trait_` is being instantiated with `args`
+        of_trait: Option<hir::Trait>,
+        /// The generic parameter being filled in by the generic arg
+        corresponding_param: Option<ast::GenericParam>,
+    },
+    /// Associated type equality constraint e.g. `Foo<Bar = $0>`
+    AssocTypeEq,
+    /// Associated constant equality constraint e.g. `Foo<X = $0>`
+    AssocConstEq,
     TypeBound,
     ImplTarget,
     ImplTrait,
     Other,
 }
 
+impl TypeLocation {
+    pub(crate) fn complete_lifetimes(&self) -> bool {
+        matches!(
+            self,
+            TypeLocation::GenericArg {
+                corresponding_param: Some(ast::GenericParam::LifetimeParam(_)),
+                ..
+            }
+        )
+    }
+
+    pub(crate) fn complete_consts(&self) -> bool {
+        match self {
+            TypeLocation::GenericArg {
+                corresponding_param: Some(ast::GenericParam::ConstParam(_)),
+                ..
+            } => true,
+            TypeLocation::AssocConstEq => true,
+            _ => false,
+        }
+    }
+
+    pub(crate) fn complete_types(&self) -> bool {
+        match self {
+            TypeLocation::GenericArg { corresponding_param: Some(param), .. } => {
+                matches!(param, ast::GenericParam::TypeParam(_))
+            }
+            TypeLocation::AssocConstEq => false,
+            TypeLocation::AssocTypeEq => true,
+            _ => true,
+        }
+    }
+
+    pub(crate) fn complete_self_type(&self) -> bool {
+        self.complete_types() && !matches!(self, TypeLocation::ImplTarget | TypeLocation::ImplTrait)
+    }
+}
+
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub(crate) enum TypeAscriptionTarget {
     Let(Option<ast::Pat>),
@@ -301,6 +351,7 @@ pub(super) enum NameRefKind {
         expr: ast::RecordExpr,
     },
     Pattern(PatternContext),
+    ExternCrate,
 }
 
 /// The identifier we are currently completing.
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
index 3ea50659030..1e6b2f319aa 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/context/analysis.rs
@@ -1,11 +1,11 @@
 //! Module responsible for analyzing the code surrounding the cursor for completion.
 use std::iter;
 
-use hir::{Semantics, Type, TypeInfo, Variant};
+use hir::{HasSource, Semantics, Type, TypeInfo, Variant};
 use ide_db::{active_parameter::ActiveParameter, RootDatabase};
 use syntax::{
     algo::{find_node_at_offset, non_trivia_sibling},
-    ast::{self, AttrKind, HasArgList, HasLoopBody, HasName, NameOrNameRef},
+    ast::{self, AttrKind, HasArgList, HasGenericParams, HasLoopBody, HasName, NameOrNameRef},
     match_ast, AstNode, AstToken, Direction, NodeOrToken, SyntaxElement, SyntaxKind, SyntaxNode,
     SyntaxToken, TextRange, TextSize, T,
 };
@@ -624,6 +624,10 @@ fn classify_name_ref(
                 });
                 return Some(make_res(kind));
             },
+            ast::ExternCrate(_) => {
+                let kind = NameRefKind::ExternCrate;
+                return Some(make_res(kind));
+            },
             ast::MethodCallExpr(method) => {
                 let receiver = find_opt_node_in_file(original_file, method.receiver());
                 let kind = NameRefKind::DotAccess(DotAccess {
@@ -719,6 +723,136 @@ fn classify_name_ref(
         None
     };
 
+    let generic_arg_location = |arg: ast::GenericArg| {
+        let mut override_location = None;
+        let location = find_opt_node_in_file_compensated(
+            sema,
+            original_file,
+            arg.syntax().parent().and_then(ast::GenericArgList::cast),
+        )
+        .map(|args| {
+            let mut in_trait = None;
+            let param = (|| {
+                let parent = args.syntax().parent()?;
+                let params = match_ast! {
+                    match parent {
+                        ast::PathSegment(segment) => {
+                            match sema.resolve_path(&segment.parent_path().top_path())? {
+                                hir::PathResolution::Def(def) => match def {
+                                    hir::ModuleDef::Function(func) => {
+                                        func.source(sema.db)?.value.generic_param_list()
+                                    }
+                                    hir::ModuleDef::Adt(adt) => {
+                                        adt.source(sema.db)?.value.generic_param_list()
+                                    }
+                                    hir::ModuleDef::Variant(variant) => {
+                                        variant.parent_enum(sema.db).source(sema.db)?.value.generic_param_list()
+                                    }
+                                    hir::ModuleDef::Trait(trait_) => {
+                                        if let ast::GenericArg::AssocTypeArg(arg) = &arg {
+                                            let arg_name = arg.name_ref()?;
+                                            let arg_name = arg_name.text();
+                                            for item in trait_.items_with_supertraits(sema.db) {
+                                                match item {
+                                                    hir::AssocItem::TypeAlias(assoc_ty) => {
+                                                        if assoc_ty.name(sema.db).as_str()? == arg_name {
+                                                            override_location = Some(TypeLocation::AssocTypeEq);
+                                                            return None;
+                                                        }
+                                                    },
+                                                    hir::AssocItem::Const(const_) => {
+                                                        if const_.name(sema.db)?.as_str()? == arg_name {
+                                                            override_location =  Some(TypeLocation::AssocConstEq);
+                                                            return None;
+                                                        }
+                                                    },
+                                                    _ => (),
+                                                }
+                                            }
+                                            return None;
+                                        } else {
+                                            in_trait = Some(trait_);
+                                            trait_.source(sema.db)?.value.generic_param_list()
+                                        }
+                                    }
+                                    hir::ModuleDef::TraitAlias(trait_) => {
+                                        trait_.source(sema.db)?.value.generic_param_list()
+                                    }
+                                    hir::ModuleDef::TypeAlias(ty_) => {
+                                        ty_.source(sema.db)?.value.generic_param_list()
+                                    }
+                                    _ => None,
+                                },
+                                _ => None,
+                            }
+                        },
+                        ast::MethodCallExpr(call) => {
+                            let func = sema.resolve_method_call(&call)?;
+                            func.source(sema.db)?.value.generic_param_list()
+                        },
+                        ast::AssocTypeArg(arg) => {
+                            let trait_ = ast::PathSegment::cast(arg.syntax().parent()?.parent()?)?;
+                            match sema.resolve_path(&trait_.parent_path().top_path())? {
+                                hir::PathResolution::Def(def) => match def {
+                                    hir::ModuleDef::Trait(trait_) => {
+                                        let arg_name = arg.name_ref()?;
+                                        let arg_name = arg_name.text();
+                                        let trait_items = trait_.items_with_supertraits(sema.db);
+                                        let assoc_ty = trait_items.iter().find_map(|item| match item {
+                                            hir::AssocItem::TypeAlias(assoc_ty) => {
+                                                (assoc_ty.name(sema.db).as_str()? == arg_name)
+                                                    .then_some(assoc_ty)
+                                            },
+                                            _ => None,
+                                        })?;
+                                        assoc_ty.source(sema.db)?.value.generic_param_list()
+                                    }
+                                    _ => None,
+                                },
+                                _ => None,
+                            }
+                        },
+                        _ => None,
+                    }
+                }?;
+                // Determine the index of the argument in the `GenericArgList` and match it with
+                // the corresponding parameter in the `GenericParamList`. Since lifetime parameters
+                // are often omitted, ignore them for the purposes of matching the argument with
+                // its parameter unless a lifetime argument is provided explicitly. That is, for
+                // `struct S<'a, 'b, T>`, match `S::<$0>` to `T` and `S::<'a, $0, _>` to `'b`.
+                // FIXME: This operates on the syntax tree and will produce incorrect results when
+                // generic parameters are disabled by `#[cfg]` directives. It should operate on the
+                // HIR, but the functionality necessary to do so is not exposed at the moment.
+                let mut explicit_lifetime_arg = false;
+                let arg_idx = arg
+                    .syntax()
+                    .siblings(Direction::Prev)
+                    // Skip the node itself
+                    .skip(1)
+                    .map(|arg| if ast::LifetimeArg::can_cast(arg.kind()) { explicit_lifetime_arg = true })
+                    .count();
+                let param_idx = if explicit_lifetime_arg {
+                    arg_idx
+                } else {
+                    // Lifetimes parameters always precede type and generic parameters,
+                    // so offset the argument index by the total number of lifetime params
+                    arg_idx + params.lifetime_params().count()
+                };
+                params.generic_params().nth(param_idx)
+            })();
+            (args, in_trait, param)
+        });
+        let (arg_list, of_trait, corresponding_param) = match location {
+            Some((arg_list, of_trait, param)) => (Some(arg_list), of_trait, param),
+            _ => (None, None, None),
+        };
+        override_location.unwrap_or(TypeLocation::GenericArg {
+            args: arg_list,
+            of_trait,
+            corresponding_param,
+        })
+    };
+
     let type_location = |node: &SyntaxNode| {
         let parent = node.parent()?;
         let res = match_ast! {
@@ -774,9 +908,12 @@ fn classify_name_ref(
                 ast::TypeBound(_) => TypeLocation::TypeBound,
                 // is this case needed?
                 ast::TypeBoundList(_) => TypeLocation::TypeBound,
-                ast::GenericArg(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, it.syntax().parent().and_then(ast::GenericArgList::cast))),
+                ast::GenericArg(it) => generic_arg_location(it),
                 // is this case needed?
-                ast::GenericArgList(it) => TypeLocation::GenericArgList(find_opt_node_in_file_compensated(sema, original_file, Some(it))),
+                ast::GenericArgList(it) => {
+                    let args = find_opt_node_in_file_compensated(sema, original_file, Some(it));
+                    TypeLocation::GenericArg { args, of_trait: None, corresponding_param: None }
+                },
                 ast::TupleField(_) => TypeLocation::TupleField,
                 _ => return None,
             }
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
index 8c038c0fbaa..4cdfd546f6a 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/flyimport.rs
@@ -1286,3 +1286,57 @@ macro_rules! println {
         expect![""],
     )
 }
+
+#[test]
+fn no_completions_for_external_doc_hidden_in_path() {
+    check(
+        r#"
+//- /main.rs crate:main deps:dep
+fn main() {
+    Span$0
+}
+//- /lib.rs crate:dep
+#[doc(hidden)]
+pub mod bridge {
+    pub mod server {
+        pub trait Span
+    }
+}
+pub mod bridge2 {
+    #[doc(hidden)]
+    pub mod server2 {
+        pub trait Span
+    }
+}
+"#,
+        expect![""],
+    );
+    // unless re-exported
+    check(
+        r#"
+//- /main.rs crate:main deps:dep
+fn main() {
+    Span$0
+}
+//- /lib.rs crate:dep
+#[doc(hidden)]
+pub mod bridge {
+    pub mod server {
+        pub trait Span
+    }
+}
+pub use bridge::server::Span;
+pub mod bridge2 {
+    #[doc(hidden)]
+    pub mod server2 {
+        pub trait Span2
+    }
+}
+pub use bridge2::server2::Span2;
+"#,
+        expect![[r#"
+            tt Span (use dep::Span)
+            tt Span2 (use dep::Span2)
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
index 8cb1ff4a125..d518dd76410 100644
--- a/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
+++ b/src/tools/rust-analyzer/crates/ide-completion/src/tests/type_pos.rs
@@ -384,10 +384,8 @@ trait Trait2<T>: Trait1 {
 fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
 "#,
         expect![[r#"
-            ct CONST
-            cp CONST_PARAM
             en Enum
-            ma makro!(…)   macro_rules! makro
+            ma makro!(…) macro_rules! makro
             md module
             st Record
             st Tuple
@@ -404,14 +402,13 @@ fn foo<'lt, T: Trait2<$0>, const CONST_PARAM: usize>(_: T) {}
     );
     check(
         r#"
-trait Trait2 {
+trait Trait2<T> {
     type Foo;
 }
 
 fn foo<'lt, T: Trait2<self::$0>, const CONST_PARAM: usize>(_: T) {}
     "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -437,7 +434,6 @@ trait Tr<T> {
 impl Tr<$0
     "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -485,7 +481,6 @@ trait MyTrait<T, U> {
 fn f(t: impl MyTrait<u$0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -511,7 +506,6 @@ trait MyTrait<T, U> {
 fn f(t: impl MyTrait<u8, u$0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -555,7 +549,6 @@ trait MyTrait<T, U = u8> {
 fn f(t: impl MyTrait<u$0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -581,7 +574,6 @@ trait MyTrait<T, U = u8> {
 fn f(t: impl MyTrait<u8, u$0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…)             macro_rules! makro
             md module
@@ -627,7 +619,6 @@ trait MyTrait {
 fn f(t: impl MyTrait<Item1 = $0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -653,7 +644,6 @@ trait MyTrait {
 fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
 "#,
         expect![[r#"
-            ct CONST
             en Enum
             ma makro!(…) macro_rules! makro
             md module
@@ -668,6 +658,22 @@ fn f(t: impl MyTrait<Item1 = u8, Item2 = $0
             kw self::
         "#]],
     );
+
+    check(
+        r#"
+trait MyTrait {
+    const C: usize;
+};
+
+fn f(t: impl MyTrait<C = $0
+"#,
+        expect![[r#"
+            ct CONST
+            ma makro!(…) macro_rules! makro
+            kw crate::
+            kw self::
+        "#]],
+    );
 }
 
 #[test]
@@ -719,3 +725,267 @@ pub struct S;
         "#]],
     )
 }
+
+#[test]
+fn completes_const_and_type_generics_separately() {
+    // Function generic params
+    check(
+        r#"
+    struct Foo;
+    const X: usize = 0;
+    fn foo<T, const N: usize>() {}
+    fn main() {
+        foo::<F$0, _>();
+    }
+            "#,
+        expect![[r#"
+                en Enum
+                ma makro!(…) macro_rules! makro
+                md module
+                st Foo
+                st Record
+                st Tuple
+                st Unit
+                tt Trait
+                un Union
+                bt u32
+                kw crate::
+                kw self::
+            "#]],
+    );
+    // FIXME: This should probably also suggest completions for types, at least those that have
+    // associated constants usable in this position. For example, a user could be typing
+    // `foo::<_, { usize::MAX }>()`, but we currently don't suggest `usize` in constant position.
+    check(
+        r#"
+    struct Foo;
+    const X: usize = 0;
+    fn foo<T, const N: usize>() {}
+    fn main() {
+        foo::<_, $0>();
+    }
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Method generic params
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo;
+    impl Foo { fn bar<const N: usize, T>(self) {} }
+    fn main() {
+        Foo.bar::<_, $0>();
+    }
+            "#,
+        expect![[r#"
+                en Enum
+                ma makro!(…) macro_rules! makro
+                md module
+                st Foo
+                st Record
+                st Tuple
+                st Unit
+                tt Trait
+                un Union
+                bt u32
+                kw crate::
+                kw self::
+            "#]],
+    );
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo;
+    impl Foo { fn bar<const N: usize, T>(self) {} }
+    fn main() {
+        Foo.bar::<X$0, _>();
+    }
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Associated type generic params
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo;
+    trait Bar {
+        type Baz<T, const X: usize>;
+    }
+    fn foo(_: impl Bar<Baz<F$0, 0> = ()>) {}
+            "#,
+        expect![[r#"
+                en Enum
+                ma makro!(…) macro_rules! makro
+                md module
+                st Foo
+                st Record
+                st Tuple
+                st Unit
+                tt Bar
+                tt Trait
+                un Union
+                bt u32
+                kw crate::
+                kw self::
+            "#]],
+    );
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo;
+    trait Bar {
+        type Baz<T, const X: usize>;
+    }
+    fn foo<T: Bar<Baz<(), $0> = ()>>() {}
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Type generic params
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo<T, const N: usize>(T);
+    fn main() {
+        let _: Foo::<_, $0> = Foo(());
+    }
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Type alias generic params
+    check(
+        r#"
+    const X: usize = 0;
+    struct Foo<T, const N: usize>(T);
+    type Bar<const X: usize, U> = Foo<U, X>;
+    fn main() {
+        let _: Bar::<X$0, _> = Bar(());
+    }
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Enum variant params
+    check(
+        r#"
+    const X: usize = 0;
+    enum Foo<T, const N: usize> { A(T), B }
+    fn main() {
+        Foo::B::<(), $0>;
+    }
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Trait params
+    check(
+        r#"
+    const X: usize = 0;
+    trait Foo<T, const N: usize> {}
+    impl Foo<(), $0> for () {}
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Trait alias params
+    check(
+        r#"
+    #![feature(trait_alias)]
+    const X: usize = 0;
+    trait Foo<T, const N: usize> {}
+    trait Bar<const M: usize, U> = Foo<U, M>;
+    fn foo<T: Bar<X$0, ()>>() {}
+            "#,
+        expect![[r#"
+                ct CONST
+                ct X
+                ma makro!(…) macro_rules! makro
+                kw crate::
+                kw self::
+            "#]],
+    );
+
+    // Omitted lifetime params
+    check(
+        r#"
+struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>);
+fn foo<'a>() { S::<F$0, _>; }
+        "#,
+        expect![[r#"
+            ct CONST
+            ma makro!(…) macro_rules! makro
+            kw crate::
+            kw self::
+        "#]],
+    );
+    // Explicit lifetime params
+    check(
+        r#"
+struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>);
+fn foo<'a>() { S::<'static, 'static, F$0, _>; }
+        "#,
+        expect![[r#"
+            ct CONST
+            ma makro!(…) macro_rules! makro
+            kw crate::
+            kw self::
+        "#]],
+    );
+    check(
+        r#"
+struct S<'a, 'b, const C: usize, T>(core::marker::PhantomData<&'a &'b T>);
+fn foo<'a>() { S::<'static, F$0, _, _>; }
+        "#,
+        expect![[r#"
+            lt 'a
+            ma makro!(…) macro_rules! makro
+            kw crate::
+            kw self::
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
index 5e4562d9c58..4ce80532e8e 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/defs.rs
@@ -7,7 +7,7 @@
 
 use arrayvec::ArrayVec;
 use hir::{
-    Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper,
+    Adt, AsAssocItem, AssocItem, BuiltinAttr, BuiltinType, Const, Crate, DeriveHelper, DocLinkDef,
     ExternCrateDecl, Field, Function, GenericParam, HasVisibility, Impl, Label, Local, Macro,
     Module, ModuleDef, Name, PathResolution, Semantics, Static, ToolModule, Trait, TraitAlias,
     TypeAlias, Variant, Visibility,
@@ -649,3 +649,13 @@ impl From<ModuleDef> for Definition {
         }
     }
 }
+
+impl From<DocLinkDef> for Definition {
+    fn from(def: DocLinkDef) -> Self {
+        match def {
+            DocLinkDef::ModuleDef(it) => it.into(),
+            DocLinkDef::Field(it) => it.into(),
+            DocLinkDef::SelfType(it) => it.into(),
+        }
+    }
+}
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
index 1eb8f00020b..330af442f75 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/helpers.rs
@@ -117,7 +117,7 @@ pub fn get_definition(
     sema: &Semantics<'_, RootDatabase>,
     token: SyntaxToken,
 ) -> Option<Definition> {
-    for token in sema.descend_into_macros(token) {
+    for token in sema.descend_into_macros(token, 0.into()) {
         let def = IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops);
         if let Some(&[x]) = def.as_deref() {
             return Some(x);
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
index e52dc356775..e475c5cd66b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/imports/import_assets.rs
@@ -6,7 +6,7 @@ use hir::{
 use itertools::Itertools;
 use rustc_hash::FxHashSet;
 use syntax::{
-    ast::{self, HasName},
+    ast::{self, make, HasName},
     utils::path_to_string_stripping_turbo_fish,
     AstNode, SyntaxNode,
 };
@@ -607,7 +607,7 @@ impl ImportCandidate {
     fn for_name(sema: &Semantics<'_, RootDatabase>, name: &ast::Name) -> Option<Self> {
         if sema
             .scope(name.syntax())?
-            .speculative_resolve(&ast::make::ext::ident_path(&name.text()))
+            .speculative_resolve(&make::ext::ident_path(&name.text()))
             .is_some()
         {
             return None;
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
index f27ed485d81..ac3511ba47b 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/lib.rs
@@ -94,18 +94,21 @@ impl fmt::Debug for RootDatabase {
 }
 
 impl Upcast<dyn ExpandDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn ExpandDatabase + 'static) {
         &*self
     }
 }
 
 impl Upcast<dyn DefDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn DefDatabase + 'static) {
         &*self
     }
 }
 
 impl Upcast<dyn HirDatabase> for RootDatabase {
+    #[inline]
     fn upcast(&self) -> &(dyn HirDatabase + 'static) {
         &*self
     }
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
index 1d0cb426a57..fb75b5b4584 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/path_transform.rs
@@ -5,7 +5,7 @@ use either::Either;
 use hir::{AsAssocItem, HirDisplay, SemanticsScope};
 use rustc_hash::FxHashMap;
 use syntax::{
-    ast::{self, AstNode},
+    ast::{self, make, AstNode},
     ted, SyntaxNode,
 };
 
@@ -21,6 +21,7 @@ enum TypeOrConst {
 }
 
 type LifetimeName = String;
+type DefaultedParam = Either<hir::TypeParam, hir::ConstParam>;
 
 /// `PathTransform` substitutes path in SyntaxNodes in bulk.
 ///
@@ -115,7 +116,7 @@ impl<'a> PathTransform<'a> {
         };
         let mut type_substs: FxHashMap<hir::TypeParam, ast::Type> = Default::default();
         let mut const_substs: FxHashMap<hir::ConstParam, SyntaxNode> = Default::default();
-        let mut default_types: Vec<hir::TypeParam> = Default::default();
+        let mut defaulted_params: Vec<DefaultedParam> = Default::default();
         self.generic_def
             .into_iter()
             .flat_map(|it| it.type_params(db))
@@ -138,8 +139,8 @@ impl<'a> PathTransform<'a> {
                         if let Some(default) =
                             &default.display_source_code(db, source_module.into(), false).ok()
                         {
-                            type_substs.insert(k, ast::make::ty(default).clone_for_update());
-                            default_types.push(k);
+                            type_substs.insert(k, make::ty(default).clone_for_update());
+                            defaulted_params.push(Either::Left(k));
                         }
                     }
                 }
@@ -155,11 +156,19 @@ impl<'a> PathTransform<'a> {
                         // is a standalone statement or a part of another expresson)
                         // and sometimes require slight modifications; see
                         // https://doc.rust-lang.org/reference/statements.html#expression-statements
+                        // (default values in curly brackets can cause the same problem)
                         const_substs.insert(k, expr.syntax().clone());
                     }
                 }
-                (Either::Left(_), None) => (), // FIXME: get default const value
-                _ => (),                       // ignore mismatching params
+                (Either::Left(k), None) => {
+                    if let Some(default) = k.default(db) {
+                        if let Some(default) = default.expr() {
+                            const_substs.insert(k, default.syntax().clone_for_update());
+                            defaulted_params.push(Either::Right(k));
+                        }
+                    }
+                }
+                _ => (), // ignore mismatching params
             });
         let lifetime_substs: FxHashMap<_, _> = self
             .generic_def
@@ -175,7 +184,7 @@ impl<'a> PathTransform<'a> {
             target_module,
             source_scope: self.source_scope,
         };
-        ctx.transform_default_type_substs(default_types);
+        ctx.transform_default_values(defaulted_params);
         ctx
     }
 }
@@ -212,13 +221,19 @@ impl Ctx<'_> {
         });
     }
 
-    fn transform_default_type_substs(&self, default_types: Vec<hir::TypeParam>) {
-        for k in default_types {
-            let v = self.type_substs.get(&k).unwrap();
+    fn transform_default_values(&self, defaulted_params: Vec<DefaultedParam>) {
+        // By now the default values are simply copied from where they are declared
+        // and should be transformed. As any value is allowed to refer to previous
+        // generic (both type and const) parameters, they should be all iterated left-to-right.
+        for param in defaulted_params {
+            let value = match param {
+                Either::Left(k) => self.type_substs.get(&k).unwrap().syntax(),
+                Either::Right(k) => self.const_substs.get(&k).unwrap(),
+            };
             // `transform_path` may update a node's parent and that would break the
             // tree traversal. Thus all paths in the tree are collected into a vec
             // so that such operation is safe.
-            let paths = postorder(&v.syntax()).filter_map(ast::Path::cast).collect::<Vec<_>>();
+            let paths = postorder(value).filter_map(ast::Path::cast).collect::<Vec<_>>();
             for path in paths {
                 self.transform_path(path);
             }
@@ -263,15 +278,14 @@ impl Ctx<'_> {
                                 hir::ModuleDef::Trait(trait_ref),
                                 false,
                             )?;
-                            match ast::make::ty_path(mod_path_to_ast(&found_path)) {
+                            match make::ty_path(mod_path_to_ast(&found_path)) {
                                 ast::Type::PathType(path_ty) => Some(path_ty),
                                 _ => None,
                             }
                         });
 
-                        let segment = ast::make::path_segment_ty(subst.clone(), trait_ref);
-                        let qualified =
-                            ast::make::path_from_segments(std::iter::once(segment), false);
+                        let segment = make::path_segment_ty(subst.clone(), trait_ref);
+                        let qualified = make::path_from_segments(std::iter::once(segment), false);
                         ted::replace(path.syntax(), qualified.clone_for_update().syntax());
                     } else if let Some(path_ty) = ast::PathType::cast(parent) {
                         ted::replace(
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/search.rs b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
index d5abd099126..7e00d368652 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/search.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/search.rs
@@ -456,14 +456,14 @@ impl<'a> FindUsages<'a> {
                     it.text().trim_start_matches("r#") == name
                 })
                 .into_iter()
-                .flat_map(|token| {
+                .flat_map(move |token| {
                     // FIXME: There should be optimization potential here
                     // Currently we try to descend everything we find which
                     // means we call `Semantics::descend_into_macros` on
                     // every textual hit. That function is notoriously
                     // expensive even for things that do not get down mapped
                     // into macros.
-                    sema.descend_into_macros(token).into_iter().filter_map(|it| it.parent())
+                    sema.descend_into_macros(token, offset).into_iter().filter_map(|it| it.parent())
                 })
         };
 
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
index b54c43b296b..f699f999baf 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/symbol_index.rs
@@ -323,6 +323,8 @@ impl Query {
                             hir::ModuleDef::Adt(..)
                                 | hir::ModuleDef::TypeAlias(..)
                                 | hir::ModuleDef::BuiltinType(..)
+                                | hir::ModuleDef::TraitAlias(..)
+                                | hir::ModuleDef::Trait(..)
                         )
                     {
                         continue;
@@ -417,9 +419,16 @@ const CONST_WITH_INNER: () = {
 
 mod b_mod;
 
+
+use define_struct as really_define_struct;
+use Macro as ItemLikeMacro;
+use Macro as Trait; // overlay namespaces
 //- /b_mod.rs
 struct StructInModB;
-        "#,
+use super::Macro as SuperItemLikeMacro;
+use crate::b_mod::StructInModB as ThisStruct;
+use crate::Trait as IsThisJustATrait;
+"#,
         );
 
         let symbols: Vec<_> = Crate::from(db.test_crate())
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
index 1a00e29384e..87ad5844c64 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
+++ b/src/tools/rust-analyzer/crates/ide-db/src/test_data/test_symbol_index_collection.txt
@@ -119,6 +119,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "ItemLikeMacro",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 654..676,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 663..676,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "Macro",
                 def: Macro(
                     Macro {
@@ -353,6 +382,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "Trait",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 682..696,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 691..696,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "Union",
                 def: Adt(
                     Union(
@@ -552,6 +610,35 @@
                 is_alias: false,
             },
             FileSymbol {
+                name: "really_define_struct",
+                def: Macro(
+                    Macro {
+                        id: MacroRulesId(
+                            MacroRulesId(
+                                1,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            0,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 611..648,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 628..648,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "trait_fn",
                 def: Function(
                     Function {
@@ -632,6 +719,35 @@
         },
         [
             FileSymbol {
+                name: "IsThisJustATrait",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 111..143,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 127..143,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
                 name: "StructInModB",
                 def: Adt(
                     Struct(
@@ -660,6 +776,93 @@
                 container_name: None,
                 is_alias: false,
             },
+            FileSymbol {
+                name: "SuperItemLikeMacro",
+                def: Macro(
+                    Macro {
+                        id: Macro2Id(
+                            Macro2Id(
+                                0,
+                            ),
+                        ),
+                    },
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 25..59,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 41..59,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                3,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 65..105,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 95..105,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
+            FileSymbol {
+                name: "ThisStruct",
+                def: Adt(
+                    Struct(
+                        Struct {
+                            id: StructId(
+                                3,
+                            ),
+                        },
+                    ),
+                ),
+                loc: DeclarationLocation {
+                    hir_file_id: FileId(
+                        FileId(
+                            1,
+                        ),
+                    ),
+                    ptr: SyntaxNodePtr {
+                        kind: USE_TREE,
+                        range: 65..105,
+                    },
+                    name_ptr: SyntaxNodePtr {
+                        kind: NAME,
+                        range: 95..105,
+                    },
+                },
+                container_name: None,
+                is_alias: false,
+            },
         ],
     ),
 ]
diff --git a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs
index f96ea29ae2f..a915391ad90 100644
--- a/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs
+++ b/src/tools/rust-analyzer/crates/ide-db/src/use_trivial_constructor.rs
@@ -1,31 +1,29 @@
 //! Functionality for generating trivial constructors
 
 use hir::StructKind;
-use syntax::ast;
+use syntax::ast::{make, Expr, Path};
 
 /// given a type return the trivial constructor (if one exists)
 pub fn use_trivial_constructor(
     db: &crate::RootDatabase,
-    path: ast::Path,
+    path: Path,
     ty: &hir::Type,
-) -> Option<ast::Expr> {
+) -> Option<Expr> {
     match ty.as_adt() {
         Some(hir::Adt::Enum(x)) => {
             if let &[variant] = &*x.variants(db) {
                 if variant.kind(db) == hir::StructKind::Unit {
-                    let path = ast::make::path_qualified(
+                    let path = make::path_qualified(
                         path,
-                        syntax::ast::make::path_segment(ast::make::name_ref(
-                            &variant.name(db).to_smol_str(),
-                        )),
+                        make::path_segment(make::name_ref(&variant.name(db).to_smol_str())),
                     );
 
-                    return Some(syntax::ast::make::expr_path(path));
+                    return Some(make::expr_path(path));
                 }
             }
         }
         Some(hir::Adt::Struct(x)) if x.kind(db) == StructKind::Unit => {
-            return Some(syntax::ast::make::expr_path(path));
+            return Some(make::expr_path(path));
         }
         _ => {}
     }
diff --git a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
index a8e88369088..60fcbbbd397 100644
--- a/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
+++ b/src/tools/rust-analyzer/crates/ide-ssr/src/matching.rs
@@ -560,8 +560,10 @@ impl<'db, 'sema> Matcher<'db, 'sema> {
                         placeholder_value.autoref_kind = self
                             .sema
                             .resolve_method_call_as_callable(code)
-                            .and_then(|callable| callable.receiver_param(self.sema.db))
-                            .map(|(self_param, _)| self_param.kind())
+                            .and_then(|callable| {
+                                let (self_param, _) = callable.receiver_param(self.sema.db)?;
+                                Some(self_param.source(self.sema.db)?.value.kind())
+                            })
                             .unwrap_or(ast::SelfParamKind::Owned);
                     }
                 }
diff --git a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
index dd1d0d75c63..f834f2ce592 100644
--- a/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/call_hierarchy.rs
@@ -74,18 +74,20 @@ pub(crate) fn incoming_calls(
     Some(calls.into_items())
 }
 
-pub(crate) fn outgoing_calls(db: &RootDatabase, position: FilePosition) -> Option<Vec<CallItem>> {
+pub(crate) fn outgoing_calls(
+    db: &RootDatabase,
+    FilePosition { file_id, offset }: FilePosition,
+) -> Option<Vec<CallItem>> {
     let sema = Semantics::new(db);
-    let file_id = position.file_id;
     let file = sema.parse(file_id);
     let file = file.syntax();
-    let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
+    let token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
         IDENT => 1,
         _ => 0,
     })?;
     let mut calls = CallLocations::default();
 
-    sema.descend_into_macros(token)
+    sema.descend_into_macros(token, offset)
         .into_iter()
         .filter_map(|it| it.parent_ancestors().nth(1).and_then(ast::Item::cast))
         .filter_map(|item| match item {
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
index d240127f376..901f7a2a79a 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links.rs
@@ -131,19 +131,19 @@ pub(crate) fn remove_links(markdown: &str) -> String {
 // |===
 pub(crate) fn external_docs(
     db: &RootDatabase,
-    position: &FilePosition,
+    FilePosition { file_id, offset }: FilePosition,
     target_dir: Option<&OsStr>,
     sysroot: Option<&OsStr>,
 ) -> Option<DocumentationLinks> {
     let sema = &Semantics::new(db);
-    let file = sema.parse(position.file_id).syntax().clone();
-    let token = pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
+    let file = sema.parse(file_id).syntax().clone();
+    let token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
         IDENT | INT_NUMBER | T![self] => 3,
         T!['('] | T![')'] => 2,
         kind if kind.is_trivia() => 0,
         _ => 1,
     })?;
-    let token = sema.descend_into_macros_single(token);
+    let token = sema.descend_into_macros_single(token, offset);
 
     let node = token.parent()?;
     let definition = match_ast! {
@@ -285,7 +285,7 @@ impl DocCommentToken {
         let original_start = doc_token.text_range().start();
         let relative_comment_offset = offset - original_start - prefix_len;
 
-        sema.descend_into_macros(doc_token).into_iter().find_map(|t| {
+        sema.descend_into_macros(doc_token, offset).into_iter().find_map(|t| {
             let (node, descended_prefix_len) = match_ast! {
                 match t {
                     ast::Comment(comment) => (t.parent()?, TextSize::try_from(comment.prefix().len()).ok()?),
diff --git a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
index 05a64b33bfd..8036c77072b 100644
--- a/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/doc_links/tests.rs
@@ -518,6 +518,62 @@ fn function();
 }
 
 #[test]
+fn doc_links_field() {
+    check_doc_links(
+        r#"
+/// [`S::f`]
+/// [`S2::f`]
+/// [`T::0`]
+/// [`U::a`]
+/// [`E::A::f`]
+/// [`E::B::0`]
+struct S$0 {
+    f: i32,
+  //^ S::f
+  //^ S2::f
+}
+type S2 = S;
+struct T(i32);
+       //^^^ T::0
+union U {
+    a: i32,
+  //^ U::a
+}
+enum E {
+    A { f: i32 },
+      //^ E::A::f
+    B(i32),
+    //^^^ E::B::0
+}
+"#,
+    );
+}
+
+#[test]
+fn doc_links_field_via_self() {
+    check_doc_links(
+        r#"
+/// [`Self::f`]
+struct S$0 {
+    f: i32,
+  //^ Self::f
+}
+"#,
+    );
+}
+
+#[test]
+fn doc_links_tuple_field_via_self() {
+    check_doc_links(
+        r#"
+/// [`Self::0`]
+struct S$0(i32);
+       //^^^ Self::0
+"#,
+    );
+}
+
+#[test]
 fn rewrite_html_root_url() {
     check_rewrite(
         r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
index d6bbf2bf794..119a9c7c3f4 100644
--- a/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/expand_macro.rs
@@ -40,28 +40,33 @@ pub(crate) fn expand_macro(db: &RootDatabase, position: FilePosition) -> Option<
     // struct Bar;
     // ```
 
-    let derive = sema.descend_into_macros(tok.clone()).into_iter().find_map(|descended| {
-        let hir_file = sema.hir_file_for(&descended.parent()?);
-        if !hir_file.is_derive_attr_pseudo_expansion(db) {
-            return None;
-        }
+    let derive =
+        sema.descend_into_macros(tok.clone(), 0.into()).into_iter().find_map(|descended| {
+            let hir_file = sema.hir_file_for(&descended.parent()?);
+            if !hir_file.is_derive_attr_pseudo_expansion(db) {
+                return None;
+            }
 
-        let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string();
-        // up map out of the #[derive] expansion
-        let token = hir::InFile::new(hir_file, descended).upmap(db)?.value;
-        let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
-        let expansions = sema.expand_derive_macro(&attr)?;
-        let idx = attr
-            .token_tree()?
-            .token_trees_and_tokens()
-            .filter_map(NodeOrToken::into_token)
-            .take_while(|it| it != &token)
-            .filter(|it| it.kind() == T![,])
-            .count();
-        let expansion =
-            format(db, SyntaxKind::MACRO_ITEMS, position.file_id, expansions.get(idx).cloned()?);
-        Some(ExpandedMacro { name, expansion })
-    });
+            let name = descended.parent_ancestors().filter_map(ast::Path::cast).last()?.to_string();
+            // up map out of the #[derive] expansion
+            let token = hir::InFile::new(hir_file, descended).upmap(db)?.value;
+            let attr = token.parent_ancestors().find_map(ast::Attr::cast)?;
+            let expansions = sema.expand_derive_macro(&attr)?;
+            let idx = attr
+                .token_tree()?
+                .token_trees_and_tokens()
+                .filter_map(NodeOrToken::into_token)
+                .take_while(|it| it != &token)
+                .filter(|it| it.kind() == T![,])
+                .count();
+            let expansion = format(
+                db,
+                SyntaxKind::MACRO_ITEMS,
+                position.file_id,
+                expansions.get(idx).cloned()?,
+            );
+            Some(ExpandedMacro { name, expansion })
+        });
 
     if derive.is_some() {
         return derive;
diff --git a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
index f9061822244..3d89599c583 100644
--- a/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/extend_selection.rs
@@ -17,8 +17,6 @@ use crate::FileRange;
 // Extends or shrinks the current selection to the encompassing syntactic construct
 // (expression, statement, item, module, etc). It works with multiple cursors.
 //
-// This is a standard LSP feature and not a protocol extension.
-//
 // |===
 // | Editor  | Shortcut
 //
@@ -142,8 +140,10 @@ fn extend_tokens_from_range(
 
     // compute original mapped token range
     let extended = {
-        let fst_expanded = sema.descend_into_macros_single(first_token.clone());
-        let lst_expanded = sema.descend_into_macros_single(last_token.clone());
+        let fst_expanded =
+            sema.descend_into_macros_single(first_token.clone(), original_range.start());
+        let lst_expanded =
+            sema.descend_into_macros_single(last_token.clone(), original_range.end());
         let mut lca =
             algo::least_common_ancestor(&fst_expanded.parent()?, &lst_expanded.parent()?)?;
         lca = shallowest_node(&lca);
@@ -154,13 +154,16 @@ fn extend_tokens_from_range(
     };
 
     // Compute parent node range
-    let validate = |token: &SyntaxToken| -> bool {
-        let expanded = sema.descend_into_macros_single(token.clone());
-        let parent = match expanded.parent() {
-            Some(it) => it,
-            None => return false,
-        };
-        algo::least_common_ancestor(&extended, &parent).as_ref() == Some(&extended)
+    let validate = |offset: TextSize| {
+        let extended = &extended;
+        move |token: &SyntaxToken| -> bool {
+            let expanded = sema.descend_into_macros_single(token.clone(), offset);
+            let parent = match expanded.parent() {
+                Some(it) => it,
+                None => return false,
+            };
+            algo::least_common_ancestor(extended, &parent).as_ref() == Some(extended)
+        }
     };
 
     // Find the first and last text range under expanded parent
@@ -168,14 +171,14 @@ fn extend_tokens_from_range(
         let token = token.prev_token()?;
         skip_trivia_token(token, Direction::Prev)
     })
-    .take_while(validate)
+    .take_while(validate(original_range.start()))
     .last()?;
 
     let last = successors(Some(last_token), |token| {
         let token = token.next_token()?;
         skip_trivia_token(token, Direction::Next)
     })
-    .take_while(validate)
+    .take_while(validate(original_range.end()))
     .last()?;
 
     let range = first.text_range().cover(last.text_range());
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
index c39c696cfd9..7e0fab42608 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_declaration.rs
@@ -20,16 +20,16 @@ use crate::{
 // - fields in patterns will navigate to the field declaration of the struct, union or variant
 pub(crate) fn goto_declaration(
     db: &RootDatabase,
-    position: FilePosition,
+    position @ FilePosition { file_id, offset }: FilePosition,
 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
     let sema = Semantics::new(db);
-    let file = sema.parse(position.file_id).syntax().clone();
+    let file = sema.parse(file_id).syntax().clone();
     let original_token = file
-        .token_at_offset(position.offset)
+        .token_at_offset(offset)
         .find(|it| matches!(it.kind(), IDENT | T![self] | T![super] | T![crate] | T![Self]))?;
     let range = original_token.text_range();
     let info: Vec<NavigationTarget> = sema
-        .descend_into_macros(original_token)
+        .descend_into_macros(original_token, offset)
         .iter()
         .filter_map(|token| {
             let parent = token.parent()?;
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
index 21471ab2a03..e09b9f39148 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_definition.rs
@@ -29,45 +29,39 @@ use syntax::{ast, AstNode, AstToken, SyntaxKind::*, SyntaxToken, TextRange, T};
 // image::https://user-images.githubusercontent.com/48062697/113065563-025fbe00-91b1-11eb-83e4-a5a703610b23.gif[]
 pub(crate) fn goto_definition(
     db: &RootDatabase,
-    position: FilePosition,
+    FilePosition { file_id, offset }: FilePosition,
 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
     let sema = &Semantics::new(db);
-    let file = sema.parse(position.file_id).syntax().clone();
-    let original_token =
-        pick_best_token(file.token_at_offset(position.offset), |kind| match kind {
-            IDENT
-            | INT_NUMBER
-            | LIFETIME_IDENT
-            | T![self]
-            | T![super]
-            | T![crate]
-            | T![Self]
-            | COMMENT => 4,
-            // index and prefix ops
-            T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
-            kind if kind.is_keyword() => 2,
-            T!['('] | T![')'] => 2,
-            kind if kind.is_trivia() => 0,
-            _ => 1,
-        })?;
+    let file = sema.parse(file_id).syntax().clone();
+    let original_token = pick_best_token(file.token_at_offset(offset), |kind| match kind {
+        IDENT
+        | INT_NUMBER
+        | LIFETIME_IDENT
+        | T![self]
+        | T![super]
+        | T![crate]
+        | T![Self]
+        | COMMENT => 4,
+        // index and prefix ops
+        T!['['] | T![']'] | T![?] | T![*] | T![-] | T![!] => 3,
+        kind if kind.is_keyword() => 2,
+        T!['('] | T![')'] => 2,
+        kind if kind.is_trivia() => 0,
+        _ => 1,
+    })?;
     if let Some(doc_comment) = token_as_doc_comment(&original_token) {
-        return doc_comment.get_definition_with_descend_at(
-            sema,
-            position.offset,
-            |def, _, link_range| {
-                let nav = def.try_to_nav(db)?;
-                Some(RangeInfo::new(link_range, vec![nav]))
-            },
-        );
+        return doc_comment.get_definition_with_descend_at(sema, offset, |def, _, link_range| {
+            let nav = def.try_to_nav(db)?;
+            Some(RangeInfo::new(link_range, vec![nav]))
+        });
     }
     let navs = sema
-        .descend_into_macros(original_token.clone())
+        .descend_into_macros(original_token.clone(), offset)
         .into_iter()
         .filter_map(|token| {
             let parent = token.parent()?;
             if let Some(tt) = ast::TokenTree::cast(parent) {
-                if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), position.file_id)
-                {
+                if let Some(x) = try_lookup_include_path(sema, tt, token.clone(), file_id) {
                     return Some(vec![x]);
                 }
             }
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
index 37166bdbd0c..544c6b42317 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_implementation.rs
@@ -22,20 +22,19 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
 // image::https://user-images.githubusercontent.com/48062697/113065566-02f85480-91b1-11eb-9288-aaad8abd8841.gif[]
 pub(crate) fn goto_implementation(
     db: &RootDatabase,
-    position: FilePosition,
+    FilePosition { file_id, offset }: FilePosition,
 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
     let sema = Semantics::new(db);
-    let source_file = sema.parse(position.file_id);
+    let source_file = sema.parse(file_id);
     let syntax = source_file.syntax().clone();
 
-    let original_token =
-        pick_best_token(syntax.token_at_offset(position.offset), |kind| match kind {
-            IDENT | T![self] | INT_NUMBER => 1,
-            _ => 0,
-        })?;
+    let original_token = pick_best_token(syntax.token_at_offset(offset), |kind| match kind {
+        IDENT | T![self] | INT_NUMBER => 1,
+        _ => 0,
+    })?;
     let range = original_token.text_range();
     let navs =
-        sema.descend_into_macros(original_token)
+        sema.descend_into_macros(original_token, offset)
             .into_iter()
             .filter_map(|token| token.parent().and_then(ast::NameLike::cast))
             .filter_map(|node| match &node {
diff --git a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
index 6048990f749..955923d7691 100644
--- a/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/goto_type_definition.rs
@@ -16,13 +16,13 @@ use crate::{FilePosition, NavigationTarget, RangeInfo, TryToNav};
 // image::https://user-images.githubusercontent.com/48062697/113020657-b560f500-917a-11eb-9007-0f809733a338.gif[]
 pub(crate) fn goto_type_definition(
     db: &RootDatabase,
-    position: FilePosition,
+    FilePosition { file_id, offset }: FilePosition,
 ) -> Option<RangeInfo<Vec<NavigationTarget>>> {
     let sema = hir::Semantics::new(db);
 
-    let file: ast::SourceFile = sema.parse(position.file_id);
+    let file: ast::SourceFile = sema.parse(file_id);
     let token: SyntaxToken =
-        pick_best_token(file.syntax().token_at_offset(position.offset), |kind| match kind {
+        pick_best_token(file.syntax().token_at_offset(offset), |kind| match kind {
             IDENT | INT_NUMBER | T![self] => 2,
             kind if kind.is_trivia() => 0,
             _ => 1,
@@ -37,7 +37,7 @@ pub(crate) fn goto_type_definition(
         }
     };
     let range = token.text_range();
-    sema.descend_into_macros(token)
+    sema.descend_into_macros(token, offset)
         .into_iter()
         .filter_map(|token| {
             let ty = sema
diff --git a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
index 43e89a334bf..46a0464e9e6 100644
--- a/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/highlight_related.rs
@@ -15,6 +15,7 @@ use syntax::{
     SyntaxKind::{self, IDENT, INT_NUMBER},
     SyntaxNode, SyntaxToken, TextRange, T,
 };
+use text_edit::TextSize;
 
 use crate::{navigation_target::ToNav, references, NavigationTarget, TryToNav};
 
@@ -51,7 +52,7 @@ pub struct HighlightRelatedConfig {
 pub(crate) fn highlight_related(
     sema: &Semantics<'_, RootDatabase>,
     config: HighlightRelatedConfig,
-    FilePosition { offset, file_id }: FilePosition,
+    pos @ FilePosition { offset, file_id }: FilePosition,
 ) -> Option<Vec<HighlightedRange>> {
     let _p = profile::span("highlight_related");
     let syntax = sema.parse(file_id).syntax().clone();
@@ -79,7 +80,7 @@ pub(crate) fn highlight_related(
         }
         T![|] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
         T![move] if config.closure_captures => highlight_closure_captures(sema, token, file_id),
-        _ if config.references => highlight_references(sema, &syntax, token, file_id),
+        _ if config.references => highlight_references(sema, &syntax, token, pos),
         _ => None,
     }
 }
@@ -129,9 +130,9 @@ fn highlight_references(
     sema: &Semantics<'_, RootDatabase>,
     node: &SyntaxNode,
     token: SyntaxToken,
-    file_id: FileId,
+    FilePosition { file_id, offset }: FilePosition,
 ) -> Option<Vec<HighlightedRange>> {
-    let defs = find_defs(sema, token.clone());
+    let defs = find_defs(sema, token.clone(), offset);
     let usages = defs
         .iter()
         .filter_map(|&d| {
@@ -455,8 +456,12 @@ fn cover_range(r0: Option<TextRange>, r1: Option<TextRange>) -> Option<TextRange
     }
 }
 
-fn find_defs(sema: &Semantics<'_, RootDatabase>, token: SyntaxToken) -> FxHashSet<Definition> {
-    sema.descend_into_macros(token)
+fn find_defs(
+    sema: &Semantics<'_, RootDatabase>,
+    token: SyntaxToken,
+    offset: TextSize,
+) -> FxHashSet<Definition> {
+    sema.descend_into_macros(token, offset)
         .into_iter()
         .filter_map(|token| IdentClass::classify_token(sema, &token))
         .map(IdentClass::definitions_no_ops)
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover.rs b/src/tools/rust-analyzer/crates/ide/src/hover.rs
index 40659e6c263..21934b9480e 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover.rs
@@ -162,9 +162,9 @@ fn hover_simple(
     // prefer descending the same token kind in attribute expansions, in normal macros text
     // equivalency is more important
     let descended = if in_attr {
-        [sema.descend_into_macros_with_kind_preference(original_token.clone())].into()
+        [sema.descend_into_macros_with_kind_preference(original_token.clone(), offset)].into()
     } else {
-        sema.descend_into_macros_with_same_text(original_token.clone())
+        sema.descend_into_macros_with_same_text(original_token.clone(), offset)
     };
     let descended = || descended.iter();
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
index ddc71dffa8a..d0f9f7b0e16 100644
--- a/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/hover/tests.rs
@@ -1557,6 +1557,49 @@ fn test_hover_function_show_types() {
 }
 
 #[test]
+fn test_hover_function_associated_type_params() {
+    check(
+        r#"
+trait Foo { type Bar; }
+impl Foo for i32 { type Bar = i64; }
+fn foo(arg: <i32 as Foo>::Bar) {}
+fn main() { foo$0; }
+"#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            fn foo(arg: <i32 as Foo>::Bar)
+            ```
+        "#]],
+    );
+
+    check(
+        r#"
+trait Foo<T> { type Bar<U>; }
+impl Foo<i64> for i32 { type Bar<U> = i32; }
+fn foo(arg: <<i32 as Foo<i64>>::Bar<i8> as Foo<i64>>::Bar<i8>) {}
+fn main() { foo$0; }
+"#,
+        expect![[r#"
+            *foo*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            fn foo(arg: <<i32 as Foo<i64>>::Bar<i8> as Foo<i64>>::Bar<i8>)
+            ```
+        "#]],
+    );
+}
+
+#[test]
 fn test_hover_function_pointer_show_identifiers() {
     check(
         r#"type foo$0 = fn(a: i32, b: i32) -> i32;"#,
@@ -3292,7 +3335,50 @@ struct S$0T<const C: usize = 1, T = Foo>(T);
             ```
 
             ```rust
-            struct ST<const C: usize, T = Foo>
+            struct ST<const C: usize = 1, T = Foo>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_default_value() {
+    check(
+        r#"
+struct Foo;
+struct S$0T<const C: usize = {40 + 2}, T = Foo>(T);
+"#,
+        expect![[r#"
+            *ST*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            struct ST<const C: usize = {const}, T = Foo>
+            ```
+        "#]],
+    );
+}
+
+#[test]
+fn const_generic_default_value_2() {
+    check(
+        r#"
+struct Foo;
+const VAL = 1;
+struct S$0T<const C: usize = VAL, T = Foo>(T);
+"#,
+        expect![[r#"
+            *ST*
+
+            ```rust
+            test
+            ```
+
+            ```rust
+            struct ST<const C: usize = VAL, T = Foo>
             ```
         "#]],
     );
@@ -6469,3 +6555,22 @@ fn test() {
         "#]],
     );
 }
+
+#[test]
+fn generic_params_disabled_by_cfg() {
+    check(
+        r#"
+struct S<#[cfg(never)] T>;
+fn test() {
+    let s$0: S = S;
+}
+"#,
+        expect![[r#"
+            *s*
+
+            ```rust
+            let s: S // size = 0, align = 1
+            ```
+        "#]],
+    );
+}
diff --git a/src/tools/rust-analyzer/crates/ide/src/lib.rs b/src/tools/rust-analyzer/crates/ide/src/lib.rs
index bf77d55d58e..c9cdbff7d7d 100644
--- a/src/tools/rust-analyzer/crates/ide/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/lib.rs
@@ -484,7 +484,7 @@ impl Analysis {
         sysroot: Option<&OsStr>,
     ) -> Cancellable<doc_links::DocumentationLinks> {
         self.with_db(|db| {
-            doc_links::external_docs(db, &position, target_dir, sysroot).unwrap_or_default()
+            doc_links::external_docs(db, position, target_dir, sysroot).unwrap_or_default()
         })
     }
 
diff --git a/src/tools/rust-analyzer/crates/ide/src/moniker.rs b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
index 17f3771b1a5..2ca2b5b1d5f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/moniker.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/moniker.rs
@@ -99,7 +99,7 @@ pub(crate) fn moniker(
         });
     }
     let navs = sema
-        .descend_into_macros(original_token.clone())
+        .descend_into_macros(original_token.clone(), offset)
         .into_iter()
         .filter_map(|token| {
             IdentClass::classify_token(sema, &token).map(IdentClass::definitions_no_ops).map(|it| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
index d1479dd1e58..0740bfbc7b1 100644
--- a/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/navigation_target.rs
@@ -175,8 +175,12 @@ impl TryToNav for FileSymbol {
 
         Some(NavigationTarget {
             file_id: full_range.file_id,
-            name: if self.is_alias { self.def.name(db)?.to_smol_str() } else { self.name.clone() },
-            alias: if self.is_alias { Some(self.name.clone()) } else { None },
+            name: self
+                .is_alias
+                .then(|| self.def.name(db))
+                .flatten()
+                .map_or_else(|| self.name.clone(), |it| it.to_smol_str()),
+            alias: self.is_alias.then(|| self.name.clone()),
             kind: Some(hir::ModuleDefId::from(self.def).into()),
             full_range: full_range.range,
             focus_range,
diff --git a/src/tools/rust-analyzer/crates/ide/src/references.rs b/src/tools/rust-analyzer/crates/ide/src/references.rs
index 813f9ed943f..2d0295692ac 100644
--- a/src/tools/rust-analyzer/crates/ide/src/references.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/references.rs
@@ -126,7 +126,7 @@ pub(crate) fn find_defs<'a>(
         )
     });
     token.map(|token| {
-        sema.descend_into_macros_with_same_text(token)
+        sema.descend_into_macros_with_same_text(token, offset)
             .into_iter()
             .filter_map(|it| ast::NameLike::cast(it.parent()?))
             .filter_map(move |name_like| {
diff --git a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
index 7795be54e26..847ab3d21ad 100644
--- a/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/signature_help.rs
@@ -67,17 +67,20 @@ impl SignatureHelp {
 }
 
 /// Computes parameter information for the given position.
-pub(crate) fn signature_help(db: &RootDatabase, position: FilePosition) -> Option<SignatureHelp> {
+pub(crate) fn signature_help(
+    db: &RootDatabase,
+    FilePosition { file_id, offset }: FilePosition,
+) -> Option<SignatureHelp> {
     let sema = Semantics::new(db);
-    let file = sema.parse(position.file_id);
+    let file = sema.parse(file_id);
     let file = file.syntax();
     let token = file
-        .token_at_offset(position.offset)
+        .token_at_offset(offset)
         .left_biased()
         // if the cursor is sandwiched between two space tokens and the call is unclosed
         // this prevents us from leaving the CallExpression
         .and_then(|tok| algo::skip_trivia_token(tok, Direction::Prev))?;
-    let token = sema.descend_into_macros_single(token);
+    let token = sema.descend_into_macros_single(token, offset);
 
     for node in token.parent_ancestors() {
         match_ast! {
@@ -202,7 +205,7 @@ fn signature_help_for_call(
     res.signature.push('(');
     {
         if let Some((self_param, _)) = callable.receiver_param(db) {
-            format_to!(res.signature, "{}", self_param)
+            format_to!(res.signature, "{}", self_param.display(db))
         }
         let mut buf = String::new();
         for (idx, (pat, ty)) in callable.params(db).into_iter().enumerate() {
@@ -1315,6 +1318,25 @@ id! {
     }
 
     #[test]
+    fn fn_signature_for_method_call_defined_in_macro() {
+        check(
+            r#"
+macro_rules! id { ($($tt:tt)*) => { $($tt)* } }
+struct S;
+id! {
+    impl S {
+        fn foo<'a>(&'a mut self) {}
+    }
+}
+fn test() { S.foo($0); }
+"#,
+            expect![[r#"
+                fn foo(&'a mut self)
+            "#]],
+        );
+    }
+
+    #[test]
     fn call_info_for_lambdas() {
         check(
             r#"
diff --git a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
index ae97236409e..bb01c81d66f 100644
--- a/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
+++ b/src/tools/rust-analyzer/crates/ide/src/syntax_highlighting.rs
@@ -395,10 +395,10 @@ fn traverse(
                 NodeOrToken::Token(token) if token.kind() != COMMENT => {
                     let token = match attr_or_derive_item {
                         Some(AttrOrDerive::Attr(_)) => {
-                            sema.descend_into_macros_with_kind_preference(token)
+                            sema.descend_into_macros_with_kind_preference(token, 0.into())
                         }
                         Some(AttrOrDerive::Derive(_)) | None => {
-                            sema.descend_into_macros_single(token)
+                            sema.descend_into_macros_single(token, 0.into())
                         }
                     };
                     match token.parent().and_then(ast::NameLike::cast) {
diff --git a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
index 62b2accf5cd..7b9bb61e696 100644
--- a/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
+++ b/src/tools/rust-analyzer/crates/mbe/src/syntax_bridge.rs
@@ -961,6 +961,7 @@ impl TtTreeSink<'_> {
                 if has_pseudo_dot {
                     assert!(right.is_empty(), "{left}.{right}");
                 } else {
+                    assert!(!right.is_empty(), "{left}.{right}");
                     self.inner.start_node(SyntaxKind::NAME_REF);
                     self.inner.token(SyntaxKind::INT_NUMBER, right);
                     self.inner.finish_node();
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar.rs b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
index 333318f53b7..6a2a9adce15 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar.rs
@@ -184,7 +184,9 @@ pub(crate) mod entry {
             };
             p.bump_any();
             while !p.at(EOF) && !p.at(closing_paren_kind) {
-                expressions::expr(p);
+                if expressions::expr(p).is_none() {
+                    break;
+                }
                 if !p.at(EOF) && !p.at(closing_paren_kind) {
                     p.expect(T![,]);
                 }
diff --git a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
index 8ed1c84c4c6..29d9b05d3f3 100644
--- a/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/grammar/generic_params.rs
@@ -88,7 +88,7 @@ fn const_param(p: &mut Parser<'_>, m: Marker) {
 
         // test const_param_default_path
         // struct A<const N: i32 = i32::MAX>;
-        generic_args::const_arg_expr(p);
+        generic_args::const_arg(p);
     }
 
     m.complete(p, CONST_PARAM);
diff --git a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
index 53cdad64992..2c47e3d086d 100644
--- a/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
+++ b/src/tools/rust-analyzer/crates/parser/src/shortcuts.rs
@@ -46,12 +46,16 @@ impl LexedStr<'_> {
                     // Tag the token as joint if it is float with a fractional part
                     // we use this jointness to inform the parser about what token split
                     // event to emit when we encounter a float literal in a field access
-                    if kind == SyntaxKind::FLOAT_NUMBER && !self.text(i).ends_with('.') {
-                        res.was_joint();
+                    if kind == SyntaxKind::FLOAT_NUMBER {
+                        if !self.text(i).ends_with('.') {
+                            res.was_joint();
+                        } else {
+                            was_joint = false;
+                        }
+                    } else {
+                        was_joint = true;
                     }
                 }
-
-                was_joint = true;
             }
         }
         res
@@ -204,6 +208,7 @@ impl Builder<'_, '_> {
                     assert!(right.is_empty(), "{left}.{right}");
                     self.state = State::Normal;
                 } else {
+                    assert!(!right.is_empty(), "{left}.{right}");
                     (self.sink)(StrStep::Enter { kind: SyntaxKind::NAME_REF });
                     (self.sink)(StrStep::Token { kind: SyntaxKind::INT_NUMBER, text: right });
                     (self.sink)(StrStep::Exit);
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
index 809ad1b8d5b..49f163b164a 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/err/0022_recover_from_missing_const_default.rast
@@ -20,7 +20,8 @@ SOURCE_FILE
                 IDENT "i32"
         WHITESPACE " "
         EQ "="
-      WHITESPACE " "
+        WHITESPACE " "
+        CONST_ARG
       COMMA ","
       WHITESPACE " "
       CONST_PARAM
@@ -37,8 +38,9 @@ SOURCE_FILE
                 IDENT "i32"
         WHITESPACE " "
         EQ "="
+        CONST_ARG
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
-error 23: expected a generic const argument
+error 24: expected a generic const argument
 error 40: expected a generic const argument
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast
index 11002bf98d0..3f5fb47d287 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0188_const_param_default_path.rast
@@ -21,16 +21,17 @@ SOURCE_FILE
         WHITESPACE " "
         EQ "="
         WHITESPACE " "
-        PATH_EXPR
-          PATH
+        CONST_ARG
+          PATH_EXPR
             PATH
+              PATH
+                PATH_SEGMENT
+                  NAME_REF
+                    IDENT "i32"
+              COLON2 "::"
               PATH_SEGMENT
                 NAME_REF
-                  IDENT "i32"
-            COLON2 "::"
-            PATH_SEGMENT
-              NAME_REF
-                IDENT "MAX"
+                  IDENT "MAX"
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast
index 0607ff54fbb..d6501137498 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0199_const_param_default_expression.rast
@@ -21,14 +21,15 @@ SOURCE_FILE
         WHITESPACE " "
         EQ "="
         WHITESPACE " "
-        BLOCK_EXPR
-          STMT_LIST
-            L_CURLY "{"
-            WHITESPACE " "
-            LITERAL
-              INT_NUMBER "1"
-            WHITESPACE " "
-            R_CURLY "}"
+        CONST_ARG
+          BLOCK_EXPR
+            STMT_LIST
+              L_CURLY "{"
+              WHITESPACE " "
+              LITERAL
+                INT_NUMBER "1"
+              WHITESPACE " "
+              R_CURLY "}"
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast
index 8e52313651c..6de10353bf0 100644
--- a/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast
+++ b/src/tools/rust-analyzer/crates/parser/test_data/parser/inline/ok/0200_const_param_default_literal.rast
@@ -21,10 +21,11 @@ SOURCE_FILE
         WHITESPACE " "
         EQ "="
         WHITESPACE " "
-        PREFIX_EXPR
-          MINUS "-"
-          LITERAL
-            INT_NUMBER "1"
+        CONST_ARG
+          PREFIX_EXPR
+            MINUS "-"
+            LITERAL
+              INT_NUMBER "1"
       R_ANGLE ">"
     SEMICOLON ";"
   WHITESPACE "\n"
diff --git a/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs b/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
index 71303d5a631..814a0257402 100644
--- a/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
+++ b/src/tools/rust-analyzer/crates/profile/src/stop_watch.rs
@@ -10,13 +10,13 @@ pub struct StopWatch {
     time: Instant,
     #[cfg(target_os = "linux")]
     counter: Option<perf_event::Counter>,
-    memory: Option<MemoryUsage>,
+    memory: MemoryUsage,
 }
 
 pub struct StopWatchSpan {
     pub time: Duration,
     pub instructions: Option<u64>,
-    pub memory: Option<MemoryUsage>,
+    pub memory: MemoryUsage,
 }
 
 impl StopWatch {
@@ -45,20 +45,16 @@ impl StopWatch {
                 None
             }
         };
+        let memory = MemoryUsage::now();
         let time = Instant::now();
         StopWatch {
             time,
             #[cfg(target_os = "linux")]
             counter,
-            memory: None,
+            memory,
         }
     }
-    pub fn memory(mut self, yes: bool) -> StopWatch {
-        if yes {
-            self.memory = Some(MemoryUsage::now());
-        }
-        self
-    }
+
     pub fn elapsed(&mut self) -> StopWatchSpan {
         let time = self.time.elapsed();
 
@@ -69,7 +65,7 @@ impl StopWatch {
         #[cfg(not(target_os = "linux"))]
         let instructions = None;
 
-        let memory = self.memory.map(|it| MemoryUsage::now() - it);
+        let memory = MemoryUsage::now() - self.memory;
         StopWatchSpan { time, instructions, memory }
     }
 }
@@ -93,9 +89,7 @@ impl fmt::Display for StopWatchSpan {
             }
             write!(f, ", {instructions}{prefix}instr")?;
         }
-        if let Some(memory) = self.memory {
-            write!(f, ", {memory}")?;
-        }
+        write!(f, ", {}", self.memory)?;
         Ok(())
     }
 }
diff --git a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
index f51ea7eeb22..13463e9f72e 100644
--- a/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
+++ b/src/tools/rust-analyzer/crates/project-model/src/workspace.rs
@@ -167,7 +167,8 @@ impl ProjectWorkspace {
                 cmd.envs(&config.extra_env);
                 cmd.arg("--version").current_dir(current_dir);
                 cmd
-            })?;
+            })
+            .with_context(|| format!("Failed to query rust toolchain version at {current_dir}, is your toolchain setup correctly?"))?;
             anyhow::Ok(
                 cargo_version
                     .get(prefix.len()..)
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
index 5bfac7ee45c..1f9d6db9314 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/Cargo.toml
@@ -24,7 +24,7 @@ crossbeam-channel = "0.5.5"
 dissimilar = "1.0.4"
 itertools = "0.10.5"
 scip = "0.1.1"
-lsp-types = { version = "=0.94", features = ["proposed"] }
+lsp-types = { version = "=0.94.0", features = ["proposed"] }
 parking_lot = "0.12.1"
 xflags = "0.3.0"
 oorandom = "11.1.3"
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
index f446a7c0596..4a03be1893c 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/analysis_stats.rs
@@ -235,9 +235,7 @@ impl flags::AnalysisStats {
         if let Some(instructions) = total_span.instructions {
             report_metric("total instructions", instructions, "#instr");
         }
-        if let Some(memory) = total_span.memory {
-            report_metric("total memory", memory.allocated.megabytes() as u64, "MB");
-        }
+        report_metric("total memory", total_span.memory.allocated.megabytes() as u64, "MB");
 
         if env::var("RA_COUNT").is_ok() {
             eprintln!("{}", profile::countme::get_all());
@@ -257,7 +255,7 @@ impl flags::AnalysisStats {
             eprintln!("source files: {total_file_size}, macro files: {total_macro_file_size}");
         }
 
-        if self.memory_usage && verbosity.is_verbose() {
+        if verbosity.is_verbose() {
             print_memory_usage(host, vfs);
         }
 
@@ -814,7 +812,7 @@ impl flags::AnalysisStats {
     }
 
     fn stop_watch(&self) -> StopWatch {
-        StopWatch::start().memory(self.memory_usage)
+        StopWatch::start()
     }
 }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
index 13b7f039bb0..419440b6df7 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/cli/flags.rs
@@ -62,8 +62,6 @@ xflags::xflags! {
             optional --randomize
             /// Run type inference in parallel.
             optional --parallel
-            /// Collect memory usage statistics.
-            optional --memory-usage
             /// Print the total length of all source and macro files (whitespace is not counted).
             optional --source-stats
 
@@ -191,7 +189,6 @@ pub struct AnalysisStats {
     pub output: Option<OutputFormat>,
     pub randomize: bool,
     pub parallel: bool,
-    pub memory_usage: bool,
     pub source_stats: bool,
     pub only: Option<String>,
     pub with_deps: bool,
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
index fa20c796ec2..40c50f6d176 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/config.rs
@@ -150,18 +150,22 @@ config_data! {
         ///
         /// Set to `"all"` to pass `--all-features` to Cargo.
         check_features | checkOnSave_features: Option<CargoFeaturesDef>  = "null",
+        /// List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.
+        ///
+        /// For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...
+        check_ignore: FxHashSet<String> = "[]",
         /// Specifies the working directory for running checks.
         /// - "workspace": run checks for workspaces in the corresponding workspaces' root directories.
         // FIXME: Ideally we would support this in some way
-        ///   This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.
+        ///   This falls back to "root" if `#rust-analyzer.cargo.check.invocationStrategy#` is set to `once`.
         /// - "root": run checks in the project's root directory.
-        /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+        /// This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`
         /// is set.
         check_invocationLocation | checkOnSave_invocationLocation: InvocationLocation = "\"workspace\"",
-        /// Specifies the invocation strategy to use when running the checkOnSave command.
+        /// Specifies the invocation strategy to use when running the check command.
         /// If `per_workspace` is set, the command will be executed for each workspace.
         /// If `once` is set, the command will be executed once.
-        /// This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+        /// This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`
         /// is set.
         check_invocationStrategy | checkOnSave_invocationStrategy: InvocationStrategy = "\"per_workspace\"",
         /// Whether to pass `--no-default-features` to Cargo. Defaults to
@@ -1098,6 +1102,7 @@ impl Config {
             remap_prefix: self.data.diagnostics_remapPrefix.clone(),
             warnings_as_info: self.data.diagnostics_warningsAsInfo.clone(),
             warnings_as_hint: self.data.diagnostics_warningsAsHint.clone(),
+            check_ignore: self.data.check_ignore.clone(),
         }
     }
 
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
index 33422fd058e..b65f38a0c71 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics.rs
@@ -6,6 +6,7 @@ use std::mem;
 use ide::FileId;
 use ide_db::FxHashMap;
 use nohash_hasher::{IntMap, IntSet};
+use rustc_hash::FxHashSet;
 use triomphe::Arc;
 
 use crate::lsp_ext;
@@ -17,6 +18,7 @@ pub struct DiagnosticsMapConfig {
     pub remap_prefix: FxHashMap<String, String>,
     pub warnings_as_info: Vec<String>,
     pub warnings_as_hint: Vec<String>,
+    pub check_ignore: FxHashSet<String>,
 }
 
 #[derive(Debug, Default, Clone)]
diff --git a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
index e1d1130ff1b..06564578d80 100644
--- a/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
+++ b/src/tools/rust-analyzer/crates/rust-analyzer/src/diagnostics/to_proto.rs
@@ -292,6 +292,13 @@ pub(crate) fn map_rust_diagnostic_to_lsp(
 
     let mut source = String::from("rustc");
     let mut code = rd.code.as_ref().map(|c| c.code.clone());
+
+    if let Some(code_val) = &code {
+        if config.check_ignore.contains(code_val) {
+            return Vec::new();
+        }
+    }
+
     if let Some(code_val) = &code {
         // See if this is an RFC #2103 scoped lint (e.g. from Clippy)
         let scoped_code: Vec<&str> = code_val.split("::").collect();
diff --git a/src/tools/rust-analyzer/crates/syntax/rust.ungram b/src/tools/rust-analyzer/crates/syntax/rust.ungram
index 138ddd20897..ea7ebd85b33 100644
--- a/src/tools/rust-analyzer/crates/syntax/rust.ungram
+++ b/src/tools/rust-analyzer/crates/syntax/rust.ungram
@@ -296,7 +296,7 @@ TypeParam =
 
 ConstParam =
   Attr* 'const' Name ':' Type
-  ('=' default_val:Expr)?
+  ('=' default_val:ConstArg)?
 
 LifetimeParam =
   Attr* Lifetime (':' TypeBoundList?)?
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
index 0b27faa535d..16448db04f8 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/generated/nodes.rs
@@ -709,7 +709,7 @@ impl ConstParam {
     pub fn colon_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![:]) }
     pub fn ty(&self) -> Option<Type> { support::child(&self.syntax) }
     pub fn eq_token(&self) -> Option<SyntaxToken> { support::token(&self.syntax, T![=]) }
-    pub fn default_val(&self) -> Option<Expr> { support::child(&self.syntax) }
+    pub fn default_val(&self) -> Option<ConstArg> { support::child(&self.syntax) }
 }
 
 #[derive(Debug, Clone, PartialEq, Eq, Hash)]
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
index 4c6db0ef06c..17e311c0c50 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/make.rs
@@ -503,11 +503,16 @@ pub fn hacky_block_expr(
 pub fn expr_unit() -> ast::Expr {
     expr_from_text("()")
 }
+
 pub fn expr_literal(text: &str) -> ast::Literal {
     assert_eq!(text.trim(), text);
     ast_from_text(&format!("fn f() {{ let _ = {text}; }}"))
 }
 
+pub fn expr_const_value(text: &str) -> ast::ConstArg {
+    ast_from_text(&format!("trait Foo<const N: usize = {text}> {{}}"))
+}
+
 pub fn expr_empty_block() -> ast::Expr {
     expr_from_text("{}")
 }
@@ -1100,7 +1105,7 @@ pub mod tokens {
 
     pub(super) static SOURCE_FILE: Lazy<Parse<SourceFile>> = Lazy::new(|| {
         SourceFile::parse(
-            "const C: <()>::Item = (1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n",
+            "const C: <()>::Item = ( true && true , true || true , 1 != 1, 2 == 2, 3 < 3, 4 <= 4, 5 > 5, 6 >= 6, !true, *p, &p , &mut p)\n;\n\n",
         )
     });
 
diff --git a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
index 3308077da5b..691d0c618f3 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/ast/node_ext.rs
@@ -61,6 +61,14 @@ impl ast::BlockExpr {
     pub fn tail_expr(&self) -> Option<ast::Expr> {
         self.stmt_list()?.tail_expr()
     }
+    /// Block expressions accept outer and inner attributes, but only when they are the outer
+    /// expression of an expression statement or the final expression of another block expression.
+    pub fn may_carry_attributes(&self) -> bool {
+        matches!(
+            self.syntax().parent().map(|it| it.kind()),
+            Some(SyntaxKind::BLOCK_EXPR | SyntaxKind::EXPR_STMT)
+        )
+    }
 }
 
 #[derive(Debug, PartialEq, Eq, Clone)]
diff --git a/src/tools/rust-analyzer/crates/syntax/src/lib.rs b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
index 4cd668a0cd5..27c8a13e58d 100644
--- a/src/tools/rust-analyzer/crates/syntax/src/lib.rs
+++ b/src/tools/rust-analyzer/crates/syntax/src/lib.rs
@@ -195,11 +195,16 @@ impl ast::TokenTree {
                     // Tag the token as joint if it is float with a fractional part
                     // we use this jointness to inform the parser about what token split
                     // event to emit when we encounter a float literal in a field access
-                    if kind == SyntaxKind::FLOAT_NUMBER && !t.text().ends_with('.') {
-                        parser_input.was_joint();
+                    if kind == SyntaxKind::FLOAT_NUMBER {
+                        if !t.text().ends_with('.') {
+                            parser_input.was_joint();
+                        } else {
+                            was_joint = false;
+                        }
+                    } else {
+                        was_joint = true;
                     }
                 }
-                was_joint = true;
             }
         }
 
@@ -250,6 +255,7 @@ impl ast::TokenTree {
                             if has_pseudo_dot {
                                 assert!(right.is_empty(), "{left}.{right}");
                             } else {
+                                assert!(!right.is_empty(), "{left}.{right}");
                                 builder.start_node(SyntaxKind::NAME_REF);
                                 builder.token(SyntaxKind::INT_NUMBER, right);
                                 builder.finish_node();
diff --git a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
index 75e7a3fec00..3f8b5a08969 100644
--- a/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
+++ b/src/tools/rust-analyzer/crates/test-utils/src/fixture.rs
@@ -313,7 +313,7 @@ impl FixtureWithProjectMeta {
 }
 
 impl MiniCore {
-    const RAW_SOURCE: &str = include_str!("./minicore.rs");
+    const RAW_SOURCE: &'static str = include_str!("./minicore.rs");
 
     fn has_flag(&self, flag: &str) -> bool {
         self.activated_flags.iter().any(|it| it == flag)
diff --git a/src/tools/rust-analyzer/docs/user/generated_config.adoc b/src/tools/rust-analyzer/docs/user/generated_config.adoc
index ea00c9540ff..71feed0f72c 100644
--- a/src/tools/rust-analyzer/docs/user/generated_config.adoc
+++ b/src/tools/rust-analyzer/docs/user/generated_config.adoc
@@ -161,23 +161,30 @@ List of features to activate. Defaults to
 
 Set to `"all"` to pass `--all-features` to Cargo.
 --
+[[rust-analyzer.check.ignore]]rust-analyzer.check.ignore (default: `[]`)::
++
+--
+List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.
+
+For example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...
+--
 [[rust-analyzer.check.invocationLocation]]rust-analyzer.check.invocationLocation (default: `"workspace"`)::
 +
 --
 Specifies the working directory for running checks.
 - "workspace": run checks for workspaces in the corresponding workspaces' root directories.
-  This falls back to "root" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.
+  This falls back to "root" if `#rust-analyzer.cargo.check.invocationStrategy#` is set to `once`.
 - "root": run checks in the project's root directory.
-This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`
 is set.
 --
 [[rust-analyzer.check.invocationStrategy]]rust-analyzer.check.invocationStrategy (default: `"per_workspace"`)::
 +
 --
-Specifies the invocation strategy to use when running the checkOnSave command.
+Specifies the invocation strategy to use when running the check command.
 If `per_workspace` is set, the command will be executed for each workspace.
 If `once` is set, the command will be executed once.
-This config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`
+This config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`
 is set.
 --
 [[rust-analyzer.check.noDefaultFeatures]]rust-analyzer.check.noDefaultFeatures (default: `null`)::
diff --git a/src/tools/rust-analyzer/editors/code/package.json b/src/tools/rust-analyzer/editors/code/package.json
index 76d7e91f381..44f1b81675a 100644
--- a/src/tools/rust-analyzer/editors/code/package.json
+++ b/src/tools/rust-analyzer/editors/code/package.json
@@ -292,6 +292,11 @@
                 "command": "rust-analyzer.viewMemoryLayout",
                 "title": "View Memory Layout",
                 "category": "rust-analyzer"
+            },
+            {
+                "command": "rust-analyzer.toggleCheckOnSave",
+                "title": "Toggle Check on Save",
+                "category": "rust-analyzer"
             }
         ],
         "keybindings": [
@@ -700,8 +705,17 @@
                         }
                     ]
                 },
+                "rust-analyzer.check.ignore": {
+                    "markdownDescription": "List of `cargo check` (or other command specified in `check.command`) diagnostics to ignore.\n\nFor example for `cargo check`: `dead_code`, `unused_imports`, `unused_variables`,...",
+                    "default": [],
+                    "type": "array",
+                    "items": {
+                        "type": "string"
+                    },
+                    "uniqueItems": true
+                },
                 "rust-analyzer.check.invocationLocation": {
-                    "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n    This falls back to \"root\" if `#rust-analyzer.cargo.checkOnSave.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.",
+                    "markdownDescription": "Specifies the working directory for running checks.\n- \"workspace\": run checks for workspaces in the corresponding workspaces' root directories.\n    This falls back to \"root\" if `#rust-analyzer.cargo.check.invocationStrategy#` is set to `once`.\n- \"root\": run checks in the project's root directory.\nThis config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`\nis set.",
                     "default": "workspace",
                     "type": "string",
                     "enum": [
@@ -714,7 +728,7 @@
                     ]
                 },
                 "rust-analyzer.check.invocationStrategy": {
-                    "markdownDescription": "Specifies the invocation strategy to use when running the checkOnSave command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.buildScripts.overrideCommand#`\nis set.",
+                    "markdownDescription": "Specifies the invocation strategy to use when running the check command.\nIf `per_workspace` is set, the command will be executed for each workspace.\nIf `once` is set, the command will be executed once.\nThis config only has an effect when `#rust-analyzer.cargo.check.overrideCommand#`\nis set.",
                     "default": "per_workspace",
                     "type": "string",
                     "enum": [
diff --git a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
index ef4dff095cf..6cf399599d9 100644
--- a/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
+++ b/src/tools/rust-analyzer/editors/code/src/bootstrap.ts
@@ -20,7 +20,7 @@ export async function bootstrap(
 
     log.info("Using server binary at", path);
 
-    if (!isValidExecutable(path)) {
+    if (!isValidExecutable(path, config.serverExtraEnv)) {
         if (config.serverPath) {
             throw new Error(`Failed to execute ${path} --version. \`config.server.path\` or \`config.serverPath\` has been set explicitly.\
             Consider removing this config or making a valid server binary available at that path.`);
diff --git a/src/tools/rust-analyzer/editors/code/src/commands.ts b/src/tools/rust-analyzer/editors/code/src/commands.ts
index e21f536f26a..aba37bac27d 100644
--- a/src/tools/rust-analyzer/editors/code/src/commands.ts
+++ b/src/tools/rust-analyzer/editors/code/src/commands.ts
@@ -1407,3 +1407,10 @@ locate()
         ctx.pushExtCleanup(document);
     };
 }
+
+export function toggleCheckOnSave(ctx: Ctx): Cmd {
+    return async () => {
+        await ctx.config.toggleCheckOnSave();
+        ctx.refreshServerStatus();
+    };
+}
diff --git a/src/tools/rust-analyzer/editors/code/src/config.ts b/src/tools/rust-analyzer/editors/code/src/config.ts
index 0e64054c11d..39e2f767c76 100644
--- a/src/tools/rust-analyzer/editors/code/src/config.ts
+++ b/src/tools/rust-analyzer/editors/code/src/config.ts
@@ -216,6 +216,39 @@ export class Config {
             ),
         );
     }
+    get checkOnSave() {
+        return this.get<boolean>("checkOnSave") ?? false;
+    }
+    async toggleCheckOnSave() {
+        const config = this.cfg.inspect<boolean>("checkOnSave") ?? { key: "checkOnSave" };
+        let overrideInLanguage;
+        let target;
+        let value;
+        if (
+            config.workspaceFolderValue !== undefined ||
+            config.workspaceFolderLanguageValue !== undefined
+        ) {
+            target = vscode.ConfigurationTarget.WorkspaceFolder;
+            overrideInLanguage = config.workspaceFolderLanguageValue;
+            value = config.workspaceFolderValue || config.workspaceFolderLanguageValue;
+        } else if (
+            config.workspaceValue !== undefined ||
+            config.workspaceLanguageValue !== undefined
+        ) {
+            target = vscode.ConfigurationTarget.Workspace;
+            overrideInLanguage = config.workspaceLanguageValue;
+            value = config.workspaceValue || config.workspaceLanguageValue;
+        } else if (config.globalValue !== undefined || config.globalLanguageValue !== undefined) {
+            target = vscode.ConfigurationTarget.Global;
+            overrideInLanguage = config.globalLanguageValue;
+            value = config.globalValue || config.globalLanguageValue;
+        } else if (config.defaultValue !== undefined || config.defaultLanguageValue !== undefined) {
+            overrideInLanguage = config.defaultLanguageValue;
+            value = config.defaultValue || config.defaultLanguageValue;
+        }
+        await this.cfg.update("checkOnSave", !(value || false), target || null, overrideInLanguage);
+    }
+
     get traceExtension() {
         return this.get<boolean>("trace.extension");
     }
diff --git a/src/tools/rust-analyzer/editors/code/src/ctx.ts b/src/tools/rust-analyzer/editors/code/src/ctx.ts
index 16c14ca54f2..363a7a82e68 100644
--- a/src/tools/rust-analyzer/editors/code/src/ctx.ts
+++ b/src/tools/rust-analyzer/editors/code/src/ctx.ts
@@ -94,6 +94,7 @@ export class Ctx {
     private unlinkedFiles: vscode.Uri[];
     private _dependencies: RustDependenciesProvider | undefined;
     private _treeView: vscode.TreeView<Dependency | DependencyFile | DependencyId> | undefined;
+    private lastStatus: ServerStatusParams | { health: "stopped" } = { health: "stopped" };
 
     get client() {
         return this._client;
@@ -404,7 +405,15 @@ export class Ctx {
     }
 
     setServerStatus(status: ServerStatusParams | { health: "stopped" }) {
+        this.lastStatus = status;
+        this.updateStatusBarItem();
+    }
+    refreshServerStatus() {
+        this.updateStatusBarItem();
+    }
+    private updateStatusBarItem() {
         let icon = "";
+        const status = this.lastStatus;
         const statusBar = this.statusBar;
         statusBar.show();
         statusBar.tooltip = new vscode.MarkdownString("", true);
@@ -447,13 +456,18 @@ export class Ctx {
                     "statusBarItem.warningBackground",
                 );
                 statusBar.command = "rust-analyzer.startServer";
-                statusBar.text = `$(stop-circle) rust-analyzer`;
+                statusBar.text = "$(stop-circle) rust-analyzer";
                 return;
         }
         if (statusBar.tooltip.value) {
             statusBar.tooltip.appendMarkdown("\n\n---\n\n");
         }
-        statusBar.tooltip.appendMarkdown("\n\n[Open logs](command:rust-analyzer.openLogs)");
+        statusBar.tooltip.appendMarkdown("\n\n[Open Logs](command:rust-analyzer.openLogs)");
+        statusBar.tooltip.appendMarkdown(
+            `\n\n[${
+                this.config.checkOnSave ? "Disable" : "Enable"
+            } Check on Save](command:rust-analyzer.toggleCheckOnSave)`,
+        );
         statusBar.tooltip.appendMarkdown(
             "\n\n[Reload Workspace](command:rust-analyzer.reloadWorkspace)",
         );
diff --git a/src/tools/rust-analyzer/editors/code/src/main.ts b/src/tools/rust-analyzer/editors/code/src/main.ts
index 448150bac06..ee5e5b1b80c 100644
--- a/src/tools/rust-analyzer/editors/code/src/main.ts
+++ b/src/tools/rust-analyzer/editors/code/src/main.ts
@@ -180,6 +180,7 @@ function createCommands(): Record<string, CommandFactory> {
         ssr: { enabled: commands.ssr },
         serverVersion: { enabled: commands.serverVersion },
         viewMemoryLayout: { enabled: commands.viewMemoryLayout },
+        toggleCheckOnSave: { enabled: commands.toggleCheckOnSave },
         // Internal commands which are invoked by the server.
         applyActionGroup: { enabled: commands.applyActionGroup },
         applySnippetWorkspaceEdit: { enabled: commands.applySnippetWorkspaceEditCommand },
diff --git a/src/tools/rust-analyzer/editors/code/src/util.ts b/src/tools/rust-analyzer/editors/code/src/util.ts
index 38ce6761578..0414ea0f806 100644
--- a/src/tools/rust-analyzer/editors/code/src/util.ts
+++ b/src/tools/rust-analyzer/editors/code/src/util.ts
@@ -2,6 +2,7 @@ import * as vscode from "vscode";
 import { strict as nativeAssert } from "assert";
 import { exec, type ExecOptions, spawnSync } from "child_process";
 import { inspect } from "util";
+import type { Env } from "./client";
 
 export function assert(condition: boolean, explanation: string): asserts condition {
     try {
@@ -93,10 +94,13 @@ export function isDocumentInWorkspace(document: RustDocument): boolean {
     return false;
 }
 
-export function isValidExecutable(path: string): boolean {
+export function isValidExecutable(path: string, extraEnv: Env): boolean {
     log.debug("Checking availability of a binary at", path);
 
-    const res = spawnSync(path, ["--version"], { encoding: "utf8" });
+    const res = spawnSync(path, ["--version"], {
+        encoding: "utf8",
+        env: { ...process.env, ...extraEnv },
+    });
 
     const printOutput = res.error ? log.warn : log.info;
     printOutput(path, "--version:", res);
@@ -151,6 +155,7 @@ export function execute(command: string, options: ExecOptions): Promise<string>
 }
 
 export function executeDiscoverProject(command: string, options: ExecOptions): Promise<string> {
+    options = Object.assign({ maxBuffer: 10 * 1024 * 1024 }, options);
     log.info(`running command: ${command}`);
     return new Promise((resolve, reject) => {
         exec(command, options, (err, stdout, _) => {
diff --git a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
index 01707d30191..e1c49db39d5 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
+++ b/src/tools/rust-analyzer/lib/lsp-server/Cargo.toml
@@ -1,6 +1,6 @@
 [package]
 name = "lsp-server"
-version = "0.7.2"
+version = "0.7.3"
 description = "Generic LSP server scaffold."
 license = "MIT OR Apache-2.0"
 repository = "https://github.com/rust-lang/rust-analyzer/tree/master/lib/lsp-server"
@@ -9,7 +9,8 @@ edition = "2021"
 [dependencies]
 log = "0.4.17"
 serde_json = "1.0.96"
-serde = { version = "1.0.156", features = ["derive"] }
+# See https://github.com/serde-rs/serde/issues/2538#issuecomment-1684517372 for why we pin serde
+serde = { version = "1.0.156, < 1.0.172", features = ["derive"] }
 crossbeam-channel = "0.5.6"
 
 [dev-dependencies]
diff --git a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
index 49a825e579b..e487b9b4622 100644
--- a/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
+++ b/src/tools/rust-analyzer/lib/lsp-server/src/stdio.rs
@@ -3,6 +3,8 @@ use std::{
     thread,
 };
 
+use log::debug;
+
 use crossbeam_channel::{bounded, Receiver, Sender};
 
 use crate::Message;
@@ -23,7 +25,8 @@ pub(crate) fn stdio_transport() -> (Sender<Message>, Receiver<Message>, IoThread
         while let Some(msg) = Message::read(&mut stdin)? {
             let is_exit = matches!(&msg, Message::Notification(n) if n.is_exit());
 
-            reader_sender.send(msg).unwrap();
+            debug!("sending message {:#?}", msg);
+            reader_sender.send(msg).expect("receiver was dropped, failed to send a message");
 
             if is_exit {
                 break;
diff --git a/src/tools/rust-analyzer/xtask/src/metrics.rs b/src/tools/rust-analyzer/xtask/src/metrics.rs
index 68537423195..e4710260409 100644
--- a/src/tools/rust-analyzer/xtask/src/metrics.rs
+++ b/src/tools/rust-analyzer/xtask/src/metrics.rs
@@ -103,9 +103,7 @@ impl Metrics {
         path: &str,
     ) -> anyhow::Result<()> {
         eprintln!("\nMeasuring analysis-stats/{name}");
-        let output =
-            cmd!(sh, "./target/release/rust-analyzer -q analysis-stats --memory-usage {path}")
-                .read()?;
+        let output = cmd!(sh, "./target/release/rust-analyzer -q analysis-stats {path}").read()?;
         for (metric, value, unit) in parse_metrics(&output) {
             self.report(&format!("analysis-stats/{name}/{metric}"), value, unit.into());
         }
diff --git a/src/version b/src/version
index 5e3a4256626..dc87e8af82f 100644
--- a/src/version
+++ b/src/version
@@ -1 +1 @@
-1.73.0
+1.74.0
diff --git a/tests/codegen/debuginfo-inline-callsite-location.rs b/tests/codegen/debuginfo-inline-callsite-location.rs
new file mode 100644
index 00000000000..e2ea9dda4a0
--- /dev/null
+++ b/tests/codegen/debuginfo-inline-callsite-location.rs
@@ -0,0 +1,26 @@
+// compile-flags: -g -O
+
+// Check that each inline call site for the same function uses the same "sub-program" so that LLVM
+// can correctly merge the debug info if it merges the inlined code (e.g., for merging of tail
+// calls to panic.
+
+// CHECK:       tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E
+// CHECK-SAME:  !dbg ![[#first_dbg:]]
+// CHECK:       tail call void @_ZN4core9panicking5panic17h{{([0-9a-z]{16})}}E
+// CHECK-SAME:  !dbg ![[#second_dbg:]]
+
+// CHECK:       ![[#func_dbg:]] = distinct !DISubprogram(name: "unwrap<i32>"
+// CHECK:       ![[#first_dbg]] = !DILocation(line: [[#]]
+// CHECK-SAME:  scope: ![[#func_dbg]], inlinedAt: ![[#]])
+// CHECK:       ![[#second_dbg]] = !DILocation(line: [[#]]
+// CHECK-SAME:  scope: ![[#func_dbg]], inlinedAt: ![[#]])
+
+#![crate_type = "lib"]
+
+#[no_mangle]
+extern "C" fn add_numbers(x: &Option<i32>, y: &Option<i32>) -> i32 {
+    let x1 = x.unwrap();
+    let y1 = y.unwrap();
+
+    x1 + y1
+}
diff --git a/tests/codegen/slice-ref-equality.rs b/tests/codegen/slice-ref-equality.rs
index 4d0dce7b074..afbdf66ce0a 100644
--- a/tests/codegen/slice-ref-equality.rs
+++ b/tests/codegen/slice-ref-equality.rs
@@ -44,48 +44,48 @@ pub fn is_zero_array(data: &[u8; 4]) -> bool {
 // equality for non-byte types also just emit a `bcmp`, not a loop.
 
 // CHECK-LABEL: @eq_slice_of_nested_u8(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_nested_u8(x: &[[u8; 3]], y: &[[u8; 3]]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %x.1, 3
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = mul nsw [[USIZE]] %1, 3
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_i32(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_i32(x: &[i32], y: &[i32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_nonzero(x: &[NonZeroU32], y: &[NonZeroU32]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 2
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 2
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
 }
 
 // CHECK-LABEL: @eq_slice_of_option_of_nonzero(
-// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %x.1
-// CHECK-SAME: [[USIZE]] noundef %y.1
+// CHECK-SAME: [[USIZE:i16|i32|i64]] noundef %1
+// CHECK-SAME: [[USIZE]] noundef %3
 #[no_mangle]
 fn eq_slice_of_option_of_nonzero(x: &[Option<NonZeroI16>], y: &[Option<NonZeroI16>]) -> bool {
-    // CHECK: icmp eq [[USIZE]] %x.1, %y.1
-    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %x.1, 1
+    // CHECK: icmp eq [[USIZE]] %1, %3
+    // CHECK: %[[BYTES:.+]] = shl nsw [[USIZE]] %1, 1
     // CHECK: tail call{{( noundef)?}} i32 @{{bcmp|memcmp}}(ptr
     // CHECK-SAME: , [[USIZE]]{{( noundef)?}} %[[BYTES]])
     x == y
diff --git a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
index 074ebddf78b..9be5b8509c7 100644
--- a/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.a-{closure#0}.generator_resume.0.mir
@@ -30,7 +30,7 @@ fn a::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:11:14: 11:16]>
     }
 
     bb2: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind continue];
+        assert(const false, "`async fn` resumed after completion") -> [success: bb2, unwind unreachable];
     }
 
     bb3: {
diff --git a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
index f774f32eb23..80ac92d59f3 100644
--- a/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
+++ b/tests/mir-opt/building/async_await.b-{closure#0}.generator_resume.0.mir
@@ -310,7 +310,7 @@ fn b::{closure#0}(_1: Pin<&mut [async fn body@$DIR/async_await.rs:14:18: 17:2]>,
     }
 
     bb28: {
-        assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind continue];
+        assert(const false, "`async fn` resumed after completion") -> [success: bb28, unwind unreachable];
     }
 
     bb29: {
diff --git a/tests/mir-opt/building/custom/terminators.rs b/tests/mir-opt/building/custom/terminators.rs
index f1240566168..123118f654e 100644
--- a/tests/mir-opt/building/custom/terminators.rs
+++ b/tests/mir-opt/building/custom/terminators.rs
@@ -12,7 +12,7 @@ fn ident<T>(t: T) -> T {
 fn direct_call(x: i32) -> i32 {
     mir!(
         {
-            Call(RET, retblock, ident(x))
+            Call(RET = ident(x), retblock)
         }
 
         retblock = {
@@ -26,7 +26,7 @@ fn direct_call(x: i32) -> i32 {
 fn indirect_call(x: i32, f: fn(i32) -> i32) -> i32 {
     mir!(
         {
-            Call(RET, retblock, f(x))
+            Call(RET = f(x), retblock)
         }
 
         retblock = {
diff --git a/tests/mir-opt/copy-prop/borrowed_local.rs b/tests/mir-opt/copy-prop/borrowed_local.rs
index a89b64441d0..bf94dc57d33 100644
--- a/tests/mir-opt/copy-prop/borrowed_local.rs
+++ b/tests/mir-opt/copy-prop/borrowed_local.rs
@@ -21,11 +21,11 @@ fn f() -> bool {
             let b = a;
             // We cannot propagate the place `a`.
             let r2 = &b;
-            Call(RET, next, cmp_ref(r1, r2))
+            Call(RET = cmp_ref(r1, r2), next)
         }
         next = {
             // But we can propagate the value `a`.
-            Call(RET, ret, opaque(b))
+            Call(RET = opaque(b), ret)
         }
         ret = {
             Return()
diff --git a/tests/mir-opt/copy-prop/custom_move_arg.rs b/tests/mir-opt/copy-prop/custom_move_arg.rs
index a90db08fa51..d1c5ffdff0d 100644
--- a/tests/mir-opt/copy-prop/custom_move_arg.rs
+++ b/tests/mir-opt/copy-prop/custom_move_arg.rs
@@ -13,11 +13,11 @@ struct NotCopy(bool);
 fn f(_1: NotCopy) {
     mir!({
         let _2 = _1;
-        Call(RET, bb1, opaque(Move(_1)))
+        Call(RET = opaque(Move(_1)), bb1)
     }
     bb1 = {
         let _3 = Move(_2);
-        Call(RET, bb2, opaque(_3))
+        Call(RET = opaque(_3), bb2)
     }
     bb2 = {
         Return()
diff --git a/tests/mir-opt/copy-prop/move_projection.rs b/tests/mir-opt/copy-prop/move_projection.rs
index 40f51ce8406..f94addb5629 100644
--- a/tests/mir-opt/copy-prop/move_projection.rs
+++ b/tests/mir-opt/copy-prop/move_projection.rs
@@ -17,10 +17,10 @@ fn f(a: Foo) -> bool {
             let b = a;
             // This is a move out of a copy, so must become a copy of `a.0`.
             let c = Move(b.0);
-            Call(RET, bb1, opaque(Move(a)))
+            Call(RET = opaque(Move(a)), bb1)
         }
         bb1 = {
-            Call(RET, ret, opaque(Move(c)))
+            Call(RET = opaque(Move(c)), ret)
         }
         ret = {
             Return()
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
index 486f276b21c..e3c57347392 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-abort.diff
@@ -7,7 +7,8 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: isize;
++         let mut _3: &std::option::Option<T>;
++         let mut _4: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
@@ -20,7 +21,7 @@
 +             }
 +         }
 +         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => &_2;
++             debug self => _3;
 +         }
 +     }
   
@@ -28,8 +29,9 @@
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind unreachable];
-+         _3 = discriminant(_2);
-+         switchInt(move _3) -> [1: bb2, otherwise: bb1];
++         StorageLive(_3);
++         _4 = discriminant(_2);
++         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -38,6 +40,7 @@
 + 
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_3);
           StorageDead(_2);
           return;
       }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
index 1c3aa537946..fc638cb3ace 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.Inline.panic-unwind.diff
@@ -7,7 +7,8 @@
       let mut _2: std::option::Option<T>;
 +     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
 +         debug self => _2;
-+         let mut _3: isize;
++         let mut _3: &std::option::Option<T>;
++         let mut _4: isize;
 +         scope 2 {
 +             debug val => _0;
 +         }
@@ -20,7 +21,7 @@
 +             }
 +         }
 +         scope 4 (inlined Option::<T>::is_some) {
-+             debug self => &_2;
++             debug self => _3;
 +         }
 +     }
   
@@ -28,8 +29,9 @@
           StorageLive(_2);
           _2 = move _1;
 -         _0 = Option::<T>::unwrap_unchecked(move _2) -> [return: bb1, unwind: bb2];
-+         _3 = discriminant(_2);
-+         switchInt(move _3) -> [1: bb2, otherwise: bb1];
++         StorageLive(_3);
++         _4 = discriminant(_2);
++         switchInt(move _4) -> [1: bb2, otherwise: bb1];
       }
   
       bb1: {
@@ -42,6 +44,7 @@
 -         resume;
 +     bb2: {
 +         _0 = move ((_2 as Some).0: T);
++         StorageDead(_3);
 +         StorageDead(_2);
 +         return;
       }
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
index 82238626798..fcc4d43ced6 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-abort.mir
@@ -6,6 +6,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
+        let mut _3: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
@@ -18,17 +19,19 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
             }
         }
         scope 4 (inlined Option::<T>::is_some) {
-            debug self => &_1;
+            debug self => _3;
         }
     }
 
     bb0: {
+        StorageLive(_3);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_3);
         return;
     }
 
diff --git a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
index 82238626798..fcc4d43ced6 100644
--- a/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/inline/unwrap_unchecked.unwrap_unchecked.PreCodegen.after.panic-unwind.mir
@@ -6,6 +6,7 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
     scope 1 (inlined #[track_caller] Option::<T>::unwrap_unchecked) {
         debug self => _1;
         let mut _2: isize;
+        let mut _3: &std::option::Option<T>;
         scope 2 {
             debug val => _0;
         }
@@ -18,17 +19,19 @@ fn unwrap_unchecked(_1: Option<T>) -> T {
             }
         }
         scope 4 (inlined Option::<T>::is_some) {
-            debug self => &_1;
+            debug self => _3;
         }
     }
 
     bb0: {
+        StorageLive(_3);
         _2 = discriminant(_1);
         switchInt(move _2) -> [1: bb1, otherwise: bb2];
     }
 
     bb1: {
         _0 = move ((_1 as Some).0: T);
+        StorageDead(_3);
         return;
     }
 
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
index b647455aeec..f61632728ba 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-abort.diff
@@ -13,13 +13,16 @@
       let mut _8: usize;
       let mut _9: usize;
       let mut _10: bool;
-      let mut _11: !;
+      let mut _14: !;
       scope 1 {
           debug v => _2;
+          let _11: &T;
+          let _12: &T;
+          let _13: &T;
           scope 2 {
-              debug v1 => &(*_2)[0 of 3];
-              debug v2 => &(*_2)[1 of 3];
-              debug v3 => &(*_2)[2 of 3];
+              debug v1 => _11;
+              debug v2 => _12;
+              debug v3 => _13;
           }
       }
   
@@ -39,10 +42,19 @@
       }
   
       bb1: {
-          _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
+          _14 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind unreachable;
       }
   
       bb2: {
+          StorageLive(_11);
+          _11 = &(*_2)[0 of 3];
+          StorageLive(_12);
+          _12 = &(*_2)[1 of 3];
+          StorageLive(_13);
+          _13 = &(*_2)[2 of 3];
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
index b02be61d031..f6c337be10f 100644
--- a/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
+++ b/tests/mir-opt/issue_76432.test.SimplifyComparisonIntegral.panic-unwind.diff
@@ -13,13 +13,16 @@
       let mut _8: usize;
       let mut _9: usize;
       let mut _10: bool;
-      let mut _11: !;
+      let mut _14: !;
       scope 1 {
           debug v => _2;
+          let _11: &T;
+          let _12: &T;
+          let _13: &T;
           scope 2 {
-              debug v1 => &(*_2)[0 of 3];
-              debug v2 => &(*_2)[1 of 3];
-              debug v3 => &(*_2)[2 of 3];
+              debug v1 => _11;
+              debug v2 => _12;
+              debug v3 => _13;
           }
       }
   
@@ -39,10 +42,19 @@
       }
   
       bb1: {
-          _11 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
+          _14 = core::panicking::panic(const "internal error: entered unreachable code") -> unwind continue;
       }
   
       bb2: {
+          StorageLive(_11);
+          _11 = &(*_2)[0 of 3];
+          StorageLive(_12);
+          _12 = &(*_2)[1 of 3];
+          StorageLive(_13);
+          _13 = &(*_2)[2 of 3];
+          StorageDead(_13);
+          StorageDead(_12);
+          StorageDead(_11);
           StorageDead(_4);
           return;
       }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
index a7a14ea645b..f8c85941813 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-abort.mir
@@ -8,8 +8,9 @@ fn num_to_digit(_1: char) -> u32 {
         debug self => _1;
         debug radix => const 8_u32;
         let _2: std::option::Option<u32>;
+        let mut _7: &std::option::Option<u32>;
         scope 2 (inlined Option::<u32>::is_some) {
-            debug self => &_2;
+            debug self => _7;
             let mut _3: isize;
         }
     }
@@ -23,12 +24,14 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb0: {
+        StorageLive(_7);
         StorageLive(_2);
         _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb1, unwind unreachable];
     }
 
     bb1: {
         _3 = discriminant(_2);
+        StorageDead(_7);
         StorageDead(_2);
         switchInt(move _3) -> [1: bb2, otherwise: bb7];
     }
diff --git a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
index 5f8c6f7283c..df7392edc50 100644
--- a/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/issues/issue_59352.num_to_digit.PreCodegen.after.panic-unwind.mir
@@ -8,8 +8,9 @@ fn num_to_digit(_1: char) -> u32 {
         debug self => _1;
         debug radix => const 8_u32;
         let _2: std::option::Option<u32>;
+        let mut _7: &std::option::Option<u32>;
         scope 2 (inlined Option::<u32>::is_some) {
-            debug self => &_2;
+            debug self => _7;
             let mut _3: isize;
         }
     }
@@ -23,12 +24,14 @@ fn num_to_digit(_1: char) -> u32 {
     }
 
     bb0: {
+        StorageLive(_7);
         StorageLive(_2);
         _2 = char::methods::<impl char>::to_digit(_1, const 8_u32) -> [return: bb1, unwind continue];
     }
 
     bb1: {
         _3 = discriminant(_2);
+        StorageDead(_7);
         StorageDead(_2);
         switchInt(move _3) -> [1: bb2, otherwise: bb7];
     }
diff --git a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
index 9be41bff3ca..b2ea96f033e 100644
--- a/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/checked_ops.step_forward.PreCodegen.after.mir
@@ -10,13 +10,14 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
         let _3: std::option::Option<u32>;
         let mut _6: bool;
         let mut _7: u32;
+        let mut _8: &std::option::Option<u32>;
         scope 2 {
         }
         scope 3 (inlined Option::<u32>::is_none) {
-            debug self => &_3;
+            debug self => _8;
             let mut _5: bool;
             scope 4 (inlined Option::<u32>::is_some) {
-                debug self => &_3;
+                debug self => _8;
                 let mut _4: isize;
             }
         }
@@ -28,6 +29,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
 
     bb0: {
         StorageLive(_6);
+        StorageLive(_8);
         StorageLive(_3);
         _3 = <u32 as Step>::forward_checked(_1, _2) -> [return: bb1, unwind continue];
     }
@@ -39,6 +41,7 @@ fn step_forward(_1: u32, _2: usize) -> u32 {
         _6 = Not(move _5);
         StorageDead(_5);
         StorageDead(_3);
+        StorageDead(_8);
         switchInt(move _6) -> [0: bb3, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
index 07a57a7b578..940b9ae1156 100644
--- a/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.filter_mapped.PreCodegen.after.mir
@@ -10,6 +10,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> ()
     let mut _8: std::option::Option<U>;
     let mut _9: isize;
     let _11: ();
+    let mut _12: &mut std::iter::FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>>;
     scope 1 {
         debug iter => _5;
         let _10: U;
@@ -17,7 +18,7 @@ fn filter_mapped(_1: impl Iterator<Item = T>, _2: impl Fn(T) -> Option<U>) -> ()
             debug x => _10;
         }
         scope 4 (inlined <FilterMap<impl Iterator<Item = T>, impl Fn(T) -> Option<U>> as Iterator>::next) {
-            debug self => &_5;
+            debug self => _12;
             let mut _6: &mut impl Iterator<Item = T>;
             let mut _7: &mut impl Fn(T) -> Option<U>;
         }
diff --git a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
index 4c6bcd1bdbd..2e51faeba5a 100644
--- a/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/loops.int_range.PreCodegen.after.mir
@@ -4,95 +4,108 @@ fn int_range(_1: usize, _2: usize) -> () {
     debug start => _1;
     debug end => _2;
     let mut _0: ();
-    let mut _3: usize;
-    let mut _6: std::option::Option<usize>;
-    let mut _9: isize;
-    let _11: ();
+    let mut _3: std::ops::Range<usize>;
+    let mut _4: std::ops::Range<usize>;
+    let mut _8: std::option::Option<usize>;
+    let mut _11: isize;
+    let _13: ();
+    let mut _14: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _3, .1 => _2, };
-        let _10: usize;
+        debug iter => _4;
+        let _12: usize;
         scope 2 {
-            debug i => _10;
+            debug i => _12;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _3, .1 => _2, };
+            debug self => _14;
             scope 5 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _3, .1 => _2, };
-                let mut _5: bool;
-                let _7: usize;
-                let mut _8: usize;
+                debug self => _14;
+                let mut _7: bool;
+                let _9: usize;
+                let mut _10: usize;
+                let mut _15: &usize;
+                let mut _16: &usize;
                 scope 6 {
-                    debug old => _7;
+                    debug old => _9;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_3;
-                    debug other => &_2;
-                    let mut _4: usize;
+                    debug self => _15;
+                    debug other => _16;
+                    let mut _5: usize;
+                    let mut _6: usize;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _1, .1 => _2, };
+        debug self => _3;
     }
 
     bb0: {
-        StorageLive(_3);
-        _3 = _1;
+        _3 = std::ops::Range::<usize> { start: _1, end: _2 };
+        StorageLive(_4);
+        _4 = move _3;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_6);
+        StorageLive(_8);
+        StorageLive(_9);
         StorageLive(_7);
+        StorageLive(_15);
+        StorageLive(_16);
         StorageLive(_5);
-        StorageLive(_4);
-        _4 = _3;
-        _5 = Lt(move _4, _2);
-        StorageDead(_4);
-        switchInt(move _5) -> [0: bb2, otherwise: bb3];
+        _5 = (_4.0: usize);
+        StorageLive(_6);
+        _6 = (_4.1: usize);
+        _7 = Lt(move _5, move _6);
+        StorageDead(_6);
+        StorageDead(_5);
+        StorageDead(_16);
+        StorageDead(_15);
+        switchInt(move _7) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _6 = Option::<usize>::None;
+        _8 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _7 = _3;
-        StorageLive(_8);
-        _8 = <usize as Step>::forward_unchecked(_7, const 1_usize) -> [return: bb4, unwind continue];
+        _9 = (_4.0: usize);
+        StorageLive(_10);
+        _10 = <usize as Step>::forward_unchecked(_9, const 1_usize) -> [return: bb4, unwind continue];
     }
 
     bb4: {
-        _3 = move _8;
-        StorageDead(_8);
-        _6 = Option::<usize>::Some(_7);
+        (_4.0: usize) = move _10;
+        StorageDead(_10);
+        _8 = Option::<usize>::Some(_9);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_5);
         StorageDead(_7);
-        _9 = discriminant(_6);
-        switchInt(move _9) -> [0: bb6, 1: bb7, otherwise: bb9];
+        StorageDead(_9);
+        _11 = discriminant(_8);
+        switchInt(move _11) -> [0: bb6, 1: bb7, otherwise: bb9];
     }
 
     bb6: {
-        StorageDead(_6);
-        StorageDead(_3);
+        StorageDead(_8);
+        StorageDead(_4);
         return;
     }
 
     bb7: {
-        _10 = ((_6 as Some).0: usize);
-        _11 = opaque::<usize>(move _10) -> [return: bb8, unwind continue];
+        _12 = ((_8 as Some).0: usize);
+        _13 = opaque::<usize>(move _12) -> [return: bb8, unwind continue];
     }
 
     bb8: {
-        StorageDead(_6);
+        StorageDead(_8);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
index cdaa3cfc995..d76b46bdd94 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-abort.mir
@@ -5,87 +5,100 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _7: std::option::Option<u32>;
-    let mut _10: isize;
-    let mut _12: &impl Fn(u32);
-    let mut _13: (u32,);
-    let _14: ();
+    let mut _4: std::ops::Range<u32>;
+    let mut _5: std::ops::Range<u32>;
+    let mut _9: std::option::Option<u32>;
+    let mut _12: isize;
+    let mut _14: &impl Fn(u32);
+    let mut _15: (u32,);
+    let _16: ();
+    let mut _17: &mut std::ops::Range<u32>;
     scope 1 {
-        debug iter => std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-        let _11: u32;
+        debug iter => _5;
+        let _13: u32;
         scope 2 {
-            debug x => _11;
+            debug x => _13;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
-            debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
+            debug self => _17;
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-                let mut _6: bool;
-                let _8: u32;
-                let mut _9: u32;
+                debug self => _17;
+                let mut _8: bool;
+                let _10: u32;
+                let mut _11: u32;
+                let mut _18: &u32;
+                let mut _19: &u32;
                 scope 6 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                    debug self => &_4;
-                    debug other => &_2;
-                    let mut _5: u32;
+                    debug self => _18;
+                    debug other => _19;
+                    let mut _6: u32;
+                    let mut _7: u32;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<u32> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<u32>{ .0 => _1, .1 => _2, };
+        debug self => _4;
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = _1;
+        _4 = std::ops::Range::<u32> { start: _1, end: _2 };
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_18);
+        StorageLive(_19);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: u32);
+        StorageLive(_7);
+        _7 = (_5.1: u32);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_19);
+        StorageDead(_18);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<u32>::None;
+        _9 = Option::<u32>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <u32 as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind unreachable];
+        _10 = (_5.0: u32);
+        StorageLive(_11);
+        _11 = <u32 as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<u32>::Some(_8);
+        (_5.0: u32) = move _11;
+        StorageDead(_11);
+        _9 = Option::<u32>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_3) -> [return: bb7, unwind unreachable];
     }
 
@@ -94,18 +107,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: u32);
-        StorageLive(_12);
-        _12 = &_3;
-        StorageLive(_13);
-        _13 = (_11,);
-        _14 = <impl Fn(u32) as Fn<(u32,)>>::call(move _12, move _13) -> [return: bb9, unwind unreachable];
+        _13 = ((_9 as Some).0: u32);
+        StorageLive(_14);
+        _14 = &_3;
+        StorageLive(_15);
+        _15 = (_13,);
+        _16 = <impl Fn(u32) as Fn<(u32,)>>::call(move _14, move _15) -> [return: bb9, unwind unreachable];
     }
 
     bb9: {
-        StorageDead(_13);
-        StorageDead(_12);
-        StorageDead(_7);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
index c4e56ea3b23..4d7c017dad4 100644
--- a/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.forward_loop.PreCodegen.after.panic-unwind.mir
@@ -5,87 +5,100 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     debug end => _2;
     debug f => _3;
     let mut _0: ();
-    let mut _4: u32;
-    let mut _7: std::option::Option<u32>;
-    let mut _10: isize;
-    let mut _12: &impl Fn(u32);
-    let mut _13: (u32,);
-    let _14: ();
+    let mut _4: std::ops::Range<u32>;
+    let mut _5: std::ops::Range<u32>;
+    let mut _9: std::option::Option<u32>;
+    let mut _12: isize;
+    let mut _14: &impl Fn(u32);
+    let mut _15: (u32,);
+    let _16: ();
+    let mut _17: &mut std::ops::Range<u32>;
     scope 1 {
-        debug iter => std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-        let _11: u32;
+        debug iter => _5;
+        let _13: u32;
         scope 2 {
-            debug x => _11;
+            debug x => _13;
         }
         scope 4 (inlined iter::range::<impl Iterator for std::ops::Range<u32>>::next) {
-            debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
+            debug self => _17;
             scope 5 (inlined <std::ops::Range<u32> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<u32>{ .0 => _4, .1 => _2, };
-                let mut _6: bool;
-                let _8: u32;
-                let mut _9: u32;
+                debug self => _17;
+                let mut _8: bool;
+                let _10: u32;
+                let mut _11: u32;
+                let mut _18: &u32;
+                let mut _19: &u32;
                 scope 6 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 7 {
                     }
                 }
                 scope 8 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                    debug self => &_4;
-                    debug other => &_2;
-                    let mut _5: u32;
+                    debug self => _18;
+                    debug other => _19;
+                    let mut _6: u32;
+                    let mut _7: u32;
                 }
             }
         }
     }
     scope 3 (inlined <std::ops::Range<u32> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<u32>{ .0 => _1, .1 => _2, };
+        debug self => _4;
     }
 
     bb0: {
-        StorageLive(_4);
-        _4 = _1;
+        _4 = std::ops::Range::<u32> { start: _1, end: _2 };
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_18);
+        StorageLive(_19);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _2);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: u32);
+        StorageLive(_7);
+        _7 = (_5.1: u32);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_19);
+        StorageDead(_18);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<u32>::None;
+        _9 = Option::<u32>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <u32 as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind: bb11];
+        _10 = (_5.0: u32);
+        StorageLive(_11);
+        _11 = <u32 as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb11];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<u32>::Some(_8);
+        (_5.0: u32) = move _11;
+        StorageDead(_11);
+        _9 = Option::<u32>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb10];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb10];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_3) -> [return: bb7, unwind continue];
     }
 
@@ -94,18 +107,18 @@ fn forward_loop(_1: u32, _2: u32, _3: impl Fn(u32)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: u32);
-        StorageLive(_12);
-        _12 = &_3;
-        StorageLive(_13);
-        _13 = (_11,);
-        _14 = <impl Fn(u32) as Fn<(u32,)>>::call(move _12, move _13) -> [return: bb9, unwind: bb11];
+        _13 = ((_9 as Some).0: u32);
+        StorageLive(_14);
+        _14 = &_3;
+        StorageLive(_15);
+        _15 = (_13,);
+        _16 = <impl Fn(u32) as Fn<(u32,)>>::call(move _14, move _15) -> [return: bb9, unwind: bb11];
     }
 
     bb9: {
-        StorageDead(_13);
-        StorageDead(_12);
-        StorageDead(_7);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
index 14fd049ede8..7360aa3e698 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-abort.mir
@@ -10,14 +10,16 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _4: bool;
             let _5: u32;
             let mut _6: u32;
+            let mut _7: &u32;
+            let mut _8: &u32;
             scope 3 {
                 debug old => _5;
                 scope 4 {
                 }
             }
             scope 5 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                debug self => &((*_1).0: u32);
-                debug other => &((*_1).1: u32);
+                debug self => _7;
+                debug other => _8;
                 let mut _2: u32;
                 let mut _3: u32;
             }
@@ -27,6 +29,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
     bb0: {
         StorageLive(_5);
         StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_2);
         _2 = ((*_1).0: u32);
         StorageLive(_3);
@@ -34,6 +38,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
         _4 = Lt(move _2, move _3);
         StorageDead(_3);
         StorageDead(_2);
+        StorageDead(_8);
+        StorageDead(_7);
         switchInt(move _4) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
index 668a2ac1e20..61957082d8b 100644
--- a/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/range_iter.range_iter_next.PreCodegen.after.panic-unwind.mir
@@ -10,14 +10,16 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
             let mut _4: bool;
             let _5: u32;
             let mut _6: u32;
+            let mut _7: &u32;
+            let mut _8: &u32;
             scope 3 {
                 debug old => _5;
                 scope 4 {
                 }
             }
             scope 5 (inlined cmp::impls::<impl PartialOrd for u32>::lt) {
-                debug self => &((*_1).0: u32);
-                debug other => &((*_1).1: u32);
+                debug self => _7;
+                debug other => _8;
                 let mut _2: u32;
                 let mut _3: u32;
             }
@@ -27,6 +29,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
     bb0: {
         StorageLive(_5);
         StorageLive(_4);
+        StorageLive(_7);
+        StorageLive(_8);
         StorageLive(_2);
         _2 = ((*_1).0: u32);
         StorageLive(_3);
@@ -34,6 +38,8 @@ fn range_iter_next(_1: &mut std::ops::Range<u32>) -> Option<u32> {
         _4 = Lt(move _2, move _3);
         StorageDead(_3);
         StorageDead(_2);
+        StorageDead(_8);
+        StorageDead(_7);
         switchInt(move _4) -> [0: bb1, otherwise: bb2];
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
index f9b0c85c852..1488779f93b 100644
--- a/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
+++ b/tests/mir-opt/pre-codegen/slice_filter.variant_a-{closure#0}.PreCodegen.after.mir
@@ -3,138 +3,206 @@
 fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2: &&(usize, usize, usize, usize)) -> bool {
     let mut _0: bool;
     let mut _3: &(usize, usize, usize, usize);
-    let mut _4: &(usize, usize, usize, usize);
+    let _4: &usize;
     let mut _5: &(usize, usize, usize, usize);
-    let mut _6: &(usize, usize, usize, usize);
-    let mut _9: bool;
-    let mut _10: bool;
-    let mut _13: bool;
+    let _6: &usize;
+    let mut _7: &(usize, usize, usize, usize);
+    let _8: &usize;
+    let mut _9: &(usize, usize, usize, usize);
+    let _10: &usize;
+    let _11: &usize;
     let mut _16: bool;
     let mut _17: bool;
-    let mut _20: bool;
+    let _18: &usize;
+    let mut _23: bool;
+    let _24: &usize;
+    let mut _29: bool;
+    let mut _30: bool;
+    let _31: &usize;
+    let mut _36: bool;
+    let mut _37: &&usize;
+    let mut _38: &&usize;
+    let mut _39: &&usize;
+    let mut _40: &&usize;
+    let mut _41: &&usize;
+    let mut _42: &&usize;
+    let mut _43: &&usize;
+    let mut _44: &&usize;
     scope 1 {
-        debug a => &((*_3).0: usize);
-        debug b => &((*_4).1: usize);
-        debug c => &((*_5).2: usize);
-        debug d => &((*_6).3: usize);
+        debug a => _4;
+        debug b => _6;
+        debug c => _8;
+        debug d => _10;
         scope 2 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_3).0: usize);
-            debug other => &&((*_5).2: usize);
+            debug self => _37;
+            debug other => _38;
+            let mut _12: &usize;
+            let mut _13: &usize;
             scope 3 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_3).0: usize);
-                debug other => &((*_5).2: usize);
-                let mut _7: usize;
-                let mut _8: usize;
+                debug self => _12;
+                debug other => _13;
+                let mut _14: usize;
+                let mut _15: usize;
             }
         }
         scope 4 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_5).2: usize);
-            debug other => &&((*_3).0: usize);
+            debug self => _41;
+            debug other => _42;
+            let mut _25: &usize;
+            let mut _26: &usize;
             scope 5 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_5).2: usize);
-                debug other => &((*_3).0: usize);
-                let mut _14: usize;
-                let mut _15: usize;
+                debug self => _25;
+                debug other => _26;
+                let mut _27: usize;
+                let mut _28: usize;
             }
         }
         scope 6 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_6).3: usize);
-            debug other => &&((*_4).1: usize);
+            debug self => _39;
+            debug other => _40;
+            let mut _19: &usize;
+            let mut _20: &usize;
             scope 7 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_6).3: usize);
-                debug other => &((*_4).1: usize);
-                let mut _11: usize;
-                let mut _12: usize;
+                debug self => _19;
+                debug other => _20;
+                let mut _21: usize;
+                let mut _22: usize;
             }
         }
         scope 8 (inlined cmp::impls::<impl PartialOrd for &usize>::le) {
-            debug self => &&((*_4).1: usize);
-            debug other => &&((*_6).3: usize);
+            debug self => _43;
+            debug other => _44;
+            let mut _32: &usize;
+            let mut _33: &usize;
             scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::le) {
-                debug self => &((*_4).1: usize);
-                debug other => &((*_6).3: usize);
-                let mut _18: usize;
-                let mut _19: usize;
+                debug self => _32;
+                debug other => _33;
+                let mut _34: usize;
+                let mut _35: usize;
             }
         }
     }
 
     bb0: {
+        StorageLive(_4);
         _3 = deref_copy (*_2);
-        _4 = deref_copy (*_2);
+        _4 = &((*_3).0: usize);
+        StorageLive(_6);
         _5 = deref_copy (*_2);
-        _6 = deref_copy (*_2);
-        StorageLive(_10);
-        StorageLive(_9);
-        StorageLive(_7);
-        _7 = ((*_3).0: usize);
+        _6 = &((*_5).1: usize);
         StorageLive(_8);
-        _8 = ((*_5).2: usize);
-        _9 = Le(move _7, move _8);
-        StorageDead(_8);
-        StorageDead(_7);
-        switchInt(move _9) -> [0: bb1, otherwise: bb2];
+        _7 = deref_copy (*_2);
+        _8 = &((*_7).2: usize);
+        StorageLive(_10);
+        _9 = deref_copy (*_2);
+        _10 = &((*_9).3: usize);
+        StorageLive(_17);
+        StorageLive(_16);
+        StorageLive(_37);
+        StorageLive(_38);
+        StorageLive(_11);
+        _11 = _8;
+        _12 = deref_copy _4;
+        _13 = deref_copy _11;
+        StorageLive(_14);
+        _14 = (*_12);
+        StorageLive(_15);
+        _15 = (*_13);
+        _16 = Le(move _14, move _15);
+        StorageDead(_15);
+        StorageDead(_14);
+        StorageDead(_11);
+        StorageDead(_38);
+        StorageDead(_37);
+        switchInt(move _16) -> [0: bb1, otherwise: bb2];
     }
 
     bb1: {
-        _10 = const false;
+        _17 = const false;
         goto -> bb3;
     }
 
     bb2: {
-        StorageLive(_13);
-        StorageLive(_11);
-        _11 = ((*_6).3: usize);
-        StorageLive(_12);
-        _12 = ((*_4).1: usize);
-        _13 = Le(move _11, move _12);
-        StorageDead(_12);
-        StorageDead(_11);
-        _10 = move _13;
+        StorageLive(_23);
+        StorageLive(_39);
+        StorageLive(_40);
+        StorageLive(_18);
+        _18 = _6;
+        _19 = deref_copy _10;
+        _20 = deref_copy _18;
+        StorageLive(_21);
+        _21 = (*_19);
+        StorageLive(_22);
+        _22 = (*_20);
+        _23 = Le(move _21, move _22);
+        StorageDead(_22);
+        StorageDead(_21);
+        StorageDead(_18);
+        StorageDead(_40);
+        StorageDead(_39);
+        _17 = move _23;
         goto -> bb3;
     }
 
     bb3: {
-        StorageDead(_13);
-        StorageDead(_9);
-        switchInt(move _10) -> [0: bb4, otherwise: bb8];
+        StorageDead(_23);
+        StorageDead(_16);
+        switchInt(move _17) -> [0: bb4, otherwise: bb8];
     }
 
     bb4: {
-        StorageLive(_17);
-        StorageLive(_16);
-        StorageLive(_14);
-        _14 = ((*_5).2: usize);
-        StorageLive(_15);
-        _15 = ((*_3).0: usize);
-        _16 = Le(move _14, move _15);
-        StorageDead(_15);
-        StorageDead(_14);
-        switchInt(move _16) -> [0: bb5, otherwise: bb6];
+        StorageLive(_30);
+        StorageLive(_29);
+        StorageLive(_41);
+        StorageLive(_42);
+        StorageLive(_24);
+        _24 = _4;
+        _25 = deref_copy _8;
+        _26 = deref_copy _24;
+        StorageLive(_27);
+        _27 = (*_25);
+        StorageLive(_28);
+        _28 = (*_26);
+        _29 = Le(move _27, move _28);
+        StorageDead(_28);
+        StorageDead(_27);
+        StorageDead(_24);
+        StorageDead(_42);
+        StorageDead(_41);
+        switchInt(move _29) -> [0: bb5, otherwise: bb6];
     }
 
     bb5: {
-        _17 = const false;
+        _30 = const false;
         goto -> bb7;
     }
 
     bb6: {
-        StorageLive(_20);
-        StorageLive(_18);
-        _18 = ((*_4).1: usize);
-        StorageLive(_19);
-        _19 = ((*_6).3: usize);
-        _20 = Le(move _18, move _19);
-        StorageDead(_19);
-        StorageDead(_18);
-        _17 = move _20;
+        StorageLive(_36);
+        StorageLive(_43);
+        StorageLive(_44);
+        StorageLive(_31);
+        _31 = _10;
+        _32 = deref_copy _6;
+        _33 = deref_copy _31;
+        StorageLive(_34);
+        _34 = (*_32);
+        StorageLive(_35);
+        _35 = (*_33);
+        _36 = Le(move _34, move _35);
+        StorageDead(_35);
+        StorageDead(_34);
+        StorageDead(_31);
+        StorageDead(_44);
+        StorageDead(_43);
+        _30 = move _36;
         goto -> bb7;
     }
 
     bb7: {
-        StorageDead(_20);
-        StorageDead(_16);
-        _0 = move _17;
+        StorageDead(_36);
+        StorageDead(_29);
+        _0 = move _30;
         goto -> bb9;
     }
 
@@ -144,8 +212,12 @@ fn variant_a::{closure#0}(_1: &mut [closure@$DIR/slice_filter.rs:7:25: 7:39], _2
     }
 
     bb9: {
+        StorageDead(_30);
         StorageDead(_17);
         StorageDead(_10);
+        StorageDead(_8);
+        StorageDead(_6);
+        StorageDead(_4);
         return;
     }
 }
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
index 901381f070b..4edf4b4fb44 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-abort.mir
@@ -5,95 +5,109 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _7: std::option::Option<usize>;
-    let mut _10: isize;
-    let mut _12: usize;
-    let mut _13: bool;
-    let mut _15: &impl Fn(usize, &T);
-    let mut _16: (usize, &T);
-    let _17: ();
-    let mut _18: usize;
+    let mut _4: std::ops::Range<usize>;
+    let mut _5: std::ops::Range<usize>;
+    let mut _9: std::option::Option<usize>;
+    let mut _12: isize;
+    let mut _14: usize;
+    let mut _15: bool;
+    let mut _17: &impl Fn(usize, &T);
+    let mut _18: (usize, &T);
+    let _19: ();
+    let mut _20: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-        let _11: usize;
+        debug iter => _5;
+        let _13: usize;
         scope 2 {
-            debug i => _11;
-            let _14: &T;
+            debug i => _13;
+            let _16: &T;
             scope 3 {
-                debug x => _14;
+                debug x => _16;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
+            debug self => _20;
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-                let mut _6: bool;
-                let _8: usize;
-                let mut _9: usize;
+                debug self => _20;
+                let mut _8: bool;
+                let _10: usize;
+                let mut _11: usize;
+                let mut _21: &usize;
+                let mut _22: &usize;
                 scope 7 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 8 {
                     }
                 }
                 scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_4;
-                    debug other => &_3;
-                    let mut _5: usize;
+                    debug self => _21;
+                    debug other => _22;
+                    let mut _6: usize;
+                    let mut _7: usize;
                 }
             }
         }
     }
     scope 4 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _18, .1 => _3, };
+        debug self => _4;
     }
 
     bb0: {
+        StorageLive(_3);
         _3 = Len((*_1));
-        StorageLive(_4);
-        _4 = const 0_usize;
+        _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _3 };
+        StorageDead(_3);
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_21);
+        StorageLive(_22);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _3);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: usize);
+        StorageLive(_7);
+        _7 = (_5.1: usize);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_22);
+        StorageDead(_21);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<usize>::None;
+        _9 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <usize as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind unreachable];
+        _10 = (_5.0: usize);
+        StorageLive(_11);
+        _11 = <usize as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind unreachable];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<usize>::Some(_8);
+        (_5.0: usize) = move _11;
+        StorageDead(_11);
+        _9 = Option::<usize>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_2) -> [return: bb7, unwind unreachable];
     }
 
@@ -102,25 +116,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: usize);
-        _12 = Len((*_1));
-        _13 = Lt(_11, _12);
-        assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb9, unwind unreachable];
+        _13 = ((_9 as Some).0: usize);
+        _14 = Len((*_1));
+        _15 = Lt(_13, _14);
+        assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind unreachable];
     }
 
     bb9: {
-        _14 = &(*_1)[_11];
-        StorageLive(_15);
-        _15 = &_2;
-        StorageLive(_16);
-        _16 = (_11, _14);
-        _17 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _15, move _16) -> [return: bb10, unwind unreachable];
+        _16 = &(*_1)[_13];
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (_13, _16);
+        _19 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _17, move _18) -> [return: bb10, unwind unreachable];
     }
 
     bb10: {
-        StorageDead(_16);
-        StorageDead(_15);
-        StorageDead(_7);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
index a47a73395cf..f7b19e80e44 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.range_loop.PreCodegen.after.panic-unwind.mir
@@ -5,95 +5,109 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     debug f => _2;
     let mut _0: ();
     let mut _3: usize;
-    let mut _4: usize;
-    let mut _7: std::option::Option<usize>;
-    let mut _10: isize;
-    let mut _12: usize;
-    let mut _13: bool;
-    let mut _15: &impl Fn(usize, &T);
-    let mut _16: (usize, &T);
-    let _17: ();
-    let mut _18: usize;
+    let mut _4: std::ops::Range<usize>;
+    let mut _5: std::ops::Range<usize>;
+    let mut _9: std::option::Option<usize>;
+    let mut _12: isize;
+    let mut _14: usize;
+    let mut _15: bool;
+    let mut _17: &impl Fn(usize, &T);
+    let mut _18: (usize, &T);
+    let _19: ();
+    let mut _20: &mut std::ops::Range<usize>;
     scope 1 {
-        debug iter => std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-        let _11: usize;
+        debug iter => _5;
+        let _13: usize;
         scope 2 {
-            debug i => _11;
-            let _14: &T;
+            debug i => _13;
+            let _16: &T;
             scope 3 {
-                debug x => _14;
+                debug x => _16;
             }
         }
         scope 5 (inlined iter::range::<impl Iterator for std::ops::Range<usize>>::next) {
-            debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
+            debug self => _20;
             scope 6 (inlined <std::ops::Range<usize> as iter::range::RangeIteratorImpl>::spec_next) {
-                debug self => &std::ops::Range<usize>{ .0 => _4, .1 => _3, };
-                let mut _6: bool;
-                let _8: usize;
-                let mut _9: usize;
+                debug self => _20;
+                let mut _8: bool;
+                let _10: usize;
+                let mut _11: usize;
+                let mut _21: &usize;
+                let mut _22: &usize;
                 scope 7 {
-                    debug old => _8;
+                    debug old => _10;
                     scope 8 {
                     }
                 }
                 scope 9 (inlined cmp::impls::<impl PartialOrd for usize>::lt) {
-                    debug self => &_4;
-                    debug other => &_3;
-                    let mut _5: usize;
+                    debug self => _21;
+                    debug other => _22;
+                    let mut _6: usize;
+                    let mut _7: usize;
                 }
             }
         }
     }
     scope 4 (inlined <std::ops::Range<usize> as IntoIterator>::into_iter) {
-        debug self => std::ops::Range<usize>{ .0 => _18, .1 => _3, };
+        debug self => _4;
     }
 
     bb0: {
+        StorageLive(_3);
         _3 = Len((*_1));
-        StorageLive(_4);
-        _4 = const 0_usize;
+        _4 = std::ops::Range::<usize> { start: const 0_usize, end: move _3 };
+        StorageDead(_3);
+        StorageLive(_5);
+        _5 = move _4;
         goto -> bb1;
     }
 
     bb1: {
-        StorageLive(_7);
+        StorageLive(_9);
+        StorageLive(_10);
         StorageLive(_8);
+        StorageLive(_21);
+        StorageLive(_22);
         StorageLive(_6);
-        StorageLive(_5);
-        _5 = _4;
-        _6 = Lt(move _5, _3);
-        StorageDead(_5);
-        switchInt(move _6) -> [0: bb2, otherwise: bb3];
+        _6 = (_5.0: usize);
+        StorageLive(_7);
+        _7 = (_5.1: usize);
+        _8 = Lt(move _6, move _7);
+        StorageDead(_7);
+        StorageDead(_6);
+        StorageDead(_22);
+        StorageDead(_21);
+        switchInt(move _8) -> [0: bb2, otherwise: bb3];
     }
 
     bb2: {
-        _7 = Option::<usize>::None;
+        _9 = Option::<usize>::None;
         goto -> bb5;
     }
 
     bb3: {
-        _8 = _4;
-        StorageLive(_9);
-        _9 = <usize as Step>::forward_unchecked(_8, const 1_usize) -> [return: bb4, unwind: bb12];
+        _10 = (_5.0: usize);
+        StorageLive(_11);
+        _11 = <usize as Step>::forward_unchecked(_10, const 1_usize) -> [return: bb4, unwind: bb12];
     }
 
     bb4: {
-        _4 = move _9;
-        StorageDead(_9);
-        _7 = Option::<usize>::Some(_8);
+        (_5.0: usize) = move _11;
+        StorageDead(_11);
+        _9 = Option::<usize>::Some(_10);
         goto -> bb5;
     }
 
     bb5: {
-        StorageDead(_6);
         StorageDead(_8);
-        _10 = discriminant(_7);
-        switchInt(move _10) -> [0: bb6, 1: bb8, otherwise: bb11];
+        StorageDead(_10);
+        _12 = discriminant(_9);
+        switchInt(move _12) -> [0: bb6, 1: bb8, otherwise: bb11];
     }
 
     bb6: {
-        StorageDead(_7);
-        StorageDead(_4);
+        StorageDead(_9);
+        StorageDead(_5);
         drop(_2) -> [return: bb7, unwind continue];
     }
 
@@ -102,25 +116,25 @@ fn range_loop(_1: &[T], _2: impl Fn(usize, &T)) -> () {
     }
 
     bb8: {
-        _11 = ((_7 as Some).0: usize);
-        _12 = Len((*_1));
-        _13 = Lt(_11, _12);
-        assert(move _13, "index out of bounds: the length is {} but the index is {}", move _12, _11) -> [success: bb9, unwind: bb12];
+        _13 = ((_9 as Some).0: usize);
+        _14 = Len((*_1));
+        _15 = Lt(_13, _14);
+        assert(move _15, "index out of bounds: the length is {} but the index is {}", move _14, _13) -> [success: bb9, unwind: bb12];
     }
 
     bb9: {
-        _14 = &(*_1)[_11];
-        StorageLive(_15);
-        _15 = &_2;
-        StorageLive(_16);
-        _16 = (_11, _14);
-        _17 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _15, move _16) -> [return: bb10, unwind: bb12];
+        _16 = &(*_1)[_13];
+        StorageLive(_17);
+        _17 = &_2;
+        StorageLive(_18);
+        _18 = (_13, _16);
+        _19 = <impl Fn(usize, &T) as Fn<(usize, &T)>>::call(move _17, move _18) -> [return: bb10, unwind: bb12];
     }
 
     bb10: {
-        StorageDead(_16);
-        StorageDead(_15);
-        StorageDead(_7);
+        StorageDead(_18);
+        StorageDead(_17);
+        StorageDead(_9);
         goto -> bb1;
     }
 
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
index a5df36ca388..549cb4f46a0 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-abort.mir
@@ -12,6 +12,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     let mut _20: &impl Fn(&T);
     let mut _21: (&T,);
     let _22: ();
+    let mut _23: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
     scope 1 {
         debug iter => _15;
         let _19: &T;
@@ -19,7 +20,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             debug x => _19;
         }
         scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => &_15;
+            debug self => _23;
             let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -48,15 +49,15 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                                     debug ptr => _9;
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) {
                                         debug self => _9;
-                                        let mut _23: *mut u8;
+                                        let mut _24: *mut u8;
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
+                                                debug ptr => _24;
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
+                                                    debug self => _24;
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
+                                                            debug self => _24;
                                                         }
                                                     }
                                                 }
@@ -131,10 +132,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageLive(_9);
         _9 = _4 as *mut T (PtrToPtr);
         StorageLive(_10);
-        StorageLive(_23);
+        StorageLive(_24);
         _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
         _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
+        StorageDead(_24);
         StorageDead(_10);
         StorageDead(_9);
         StorageLive(_12);
diff --git a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
index f681da4d275..43f8806e165 100644
--- a/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
+++ b/tests/mir-opt/pre-codegen/slice_iter.reverse_loop.PreCodegen.after.panic-unwind.mir
@@ -12,6 +12,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
     let mut _20: &impl Fn(&T);
     let mut _21: (&T,);
     let _22: ();
+    let mut _23: &mut std::iter::Rev<std::slice::Iter<'_, T>>;
     scope 1 {
         debug iter => _15;
         let _19: &T;
@@ -19,7 +20,7 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
             debug x => _19;
         }
         scope 25 (inlined <Rev<std::slice::Iter<'_, T>> as Iterator>::next) {
-            debug self => &_15;
+            debug self => _23;
             let mut _16: &mut std::slice::Iter<'_, T>;
         }
     }
@@ -48,15 +49,15 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
                                     debug ptr => _9;
                                     scope 16 (inlined ptr::mut_ptr::<impl *mut T>::is_null) {
                                         debug self => _9;
-                                        let mut _23: *mut u8;
+                                        let mut _24: *mut u8;
                                         scope 17 {
                                             scope 18 (inlined ptr::mut_ptr::<impl *mut T>::is_null::runtime_impl) {
-                                                debug ptr => _23;
+                                                debug ptr => _24;
                                                 scope 19 (inlined ptr::mut_ptr::<impl *mut u8>::addr) {
-                                                    debug self => _23;
+                                                    debug self => _24;
                                                     scope 20 {
                                                         scope 21 (inlined ptr::mut_ptr::<impl *mut u8>::cast::<()>) {
-                                                            debug self => _23;
+                                                            debug self => _24;
                                                         }
                                                     }
                                                 }
@@ -131,10 +132,10 @@ fn reverse_loop(_1: &[T], _2: impl Fn(&T)) -> () {
         StorageLive(_9);
         _9 = _4 as *mut T (PtrToPtr);
         StorageLive(_10);
-        StorageLive(_23);
+        StorageLive(_24);
         _10 = _9 as *const T (PointerCoercion(MutToConstPointer));
         _11 = NonNull::<T> { pointer: _10 };
-        StorageDead(_23);
+        StorageDead(_24);
         StorageDead(_10);
         StorageDead(_9);
         StorageLive(_12);
diff --git a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
index 132f66a1ad3..8fe361f2be4 100644
--- a/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.debuginfo.ReferencePropagation.diff
@@ -22,27 +22,23 @@
       let _24: &mut u8;
       let mut _25: debuginfo::T;
       scope 1 {
--         debug ref_mut_u8 => _1;
-+         debug ref_mut_u8 => &_2;
+          debug ref_mut_u8 => _1;
           let _3: &u8;
           let mut _28: &debuginfo::T;
           scope 2 {
--             debug field => _3;
-+             debug field => &((*_28).0: u8);
+              debug field => _3;
               let _5: &u8;
               scope 3 {
 -                 debug reborrow => _5;
-+                 debug reborrow => &_2;
++                 debug reborrow => _1;
                   let _9: &i32;
                   let _22: &&&mut u8;
                   let mut _27: &std::option::Option<i32>;
                   scope 4 {
--                     debug variant_field => _9;
-+                     debug variant_field => &(((*_27) as Some).0: i32);
+                      debug variant_field => _9;
                   }
                   scope 5 {
--                     debug constant_index => _19;
-+                     debug constant_index => &(*_11)[1 of 3];
+                      debug constant_index => _19;
                       debug subslice => _20;
                       debug constant_index_from_end => _21;
                       let _19: &i32;
@@ -51,21 +47,20 @@
                       let mut _26: &[i32; 10];
                   }
                   scope 6 {
--                     debug multiple_borrow => _22;
-+                     debug multiple_borrow => &&&(_25.0: u8);
+                      debug multiple_borrow => _22;
                   }
               }
           }
       }
   
       bb0: {
--         StorageLive(_1);
+          StorageLive(_1);
           StorageLive(_2);
           _2 = const 5_u8;
--         _1 = &mut _2;
--         StorageLive(_3);
+          _1 = &mut _2;
+          StorageLive(_3);
           _28 = const _;
--         _3 = &((*_28).0: u8);
+          _3 = &((*_28).0: u8);
 -         StorageLive(_5);
 -         _5 = &(*_1);
 -         StorageLive(_6);
@@ -76,11 +71,11 @@
       }
   
       bb1: {
--         StorageLive(_9);
+          StorageLive(_9);
           _27 = const _;
--         _9 = &(((*_27) as Some).0: i32);
+          _9 = &(((*_27) as Some).0: i32);
 -         _6 = const ();
--         StorageDead(_9);
+          StorageDead(_9);
           goto -> bb4;
       }
   
@@ -118,8 +113,8 @@
       }
   
       bb6: {
--         StorageLive(_19);
--         _19 = &(*_11)[1 of 3];
+          StorageLive(_19);
+          _19 = &(*_11)[1 of 3];
           StorageLive(_20);
           _20 = &(*_11)[2:-1];
           StorageLive(_21);
@@ -127,7 +122,7 @@
 -         _10 = const ();
           StorageDead(_21);
           StorageDead(_20);
--         StorageDead(_19);
+          StorageDead(_19);
           goto -> bb8;
       }
   
@@ -140,23 +135,23 @@
           StorageDead(_12);
           StorageDead(_11);
 -         StorageDead(_10);
--         StorageLive(_22);
--         StorageLive(_23);
--         StorageLive(_24);
+          StorageLive(_22);
+          StorageLive(_23);
+          StorageLive(_24);
           StorageLive(_25);
           _25 = T(const 6_u8);
--         _24 = &mut (_25.0: u8);
--         _23 = &_24;
--         _22 = &_23;
+          _24 = &mut (_25.0: u8);
+          _23 = &_24;
+          _22 = &_23;
           _0 = const ();
           StorageDead(_25);
--         StorageDead(_24);
--         StorageDead(_23);
--         StorageDead(_22);
+          StorageDead(_24);
+          StorageDead(_23);
+          StorageDead(_22);
 -         StorageDead(_5);
--         StorageDead(_3);
+          StorageDead(_3);
           StorageDead(_2);
--         StorageDead(_1);
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
index 9ec8f9d78bb..747028e128f 100644
--- a/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.mut_raw_then_mut_shr.ReferencePropagation.diff
@@ -13,16 +13,15 @@
           debug x => _1;
           let _2: &mut i32;
           scope 2 {
--             debug xref => _2;
-+             debug xref => &_1;
+              debug xref => _2;
               let _3: *mut i32;
               scope 3 {
 -                 debug xraw => _3;
-+                 debug xraw => &_1;
++                 debug xraw => _2;
                   let _6: &i32;
                   scope 4 {
 -                     debug xshr => _6;
-+                     debug xshr => &_1;
++                     debug xshr => _2;
                       let _7: i32;
                       scope 5 {
                           debug a => _7;
@@ -38,7 +37,7 @@
           StorageLive(_1);
           _1 = const 2_i32;
 -         StorageLive(_2);
--         _2 = &mut _1;
+          _2 = &mut _1;
 -         StorageLive(_3);
 -         StorageLive(_4);
 -         StorageLive(_5);
diff --git a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
index f1f77cffd20..1be2ce8d0bb 100644
--- a/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation.ReferencePropagation.diff
@@ -52,8 +52,7 @@
           debug a => _4;
           let _5: &usize;
           scope 2 {
--             debug b => _5;
-+             debug b => &_4;
+              debug b => _5;
               let _6: usize;
               scope 3 {
                   debug c => _6;
@@ -158,12 +157,10 @@
           debug a => _60;
           let _61: &usize;
           scope 30 {
--             debug b => _61;
-+             debug b => &_60;
+              debug b => _61;
               let _62: &&usize;
               scope 31 {
--                 debug d => _62;
-+                 debug d => &&_60;
+                  debug d => _62;
                   let _63: usize;
                   scope 32 {
                       debug c => _63;
@@ -175,12 +172,10 @@
           debug a => _66;
           let mut _67: &usize;
           scope 34 {
--             debug b => _67;
-+             debug b => &_66;
+              debug b => _67;
               let _68: &mut &usize;
               scope 35 {
--                 debug d => _68;
-+                 debug d => &&_66;
+                  debug d => _68;
                   let _69: usize;
                   scope 36 {
                       debug c => _69;
@@ -193,8 +188,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &_4;
+          StorageLive(_5);
+          _5 = &_4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -209,7 +204,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -394,13 +389,12 @@
 -         StorageLive(_59);
           StorageLive(_60);
           _60 = const 5_usize;
--         StorageLive(_61);
--         _61 = &_60;
--         StorageLive(_62);
--         _62 = &_61;
+          StorageLive(_61);
+          _61 = &_60;
+          StorageLive(_62);
+          _62 = &_61;
           StorageLive(_63);
--         _63 = (*_61);
-+         _63 = _60;
+          _63 = (*_61);
           StorageLive(_64);
           StorageLive(_65);
           _65 = ();
@@ -412,19 +406,18 @@
           StorageDead(_64);
 -         _59 = const ();
           StorageDead(_63);
--         StorageDead(_62);
--         StorageDead(_61);
+          StorageDead(_62);
+          StorageDead(_61);
           StorageDead(_60);
 -         StorageDead(_59);
           StorageLive(_66);
           _66 = const 5_usize;
--         StorageLive(_67);
--         _67 = &_66;
--         StorageLive(_68);
--         _68 = &mut _67;
+          StorageLive(_67);
+          _67 = &_66;
+          StorageLive(_68);
+          _68 = &mut _67;
           StorageLive(_69);
--         _69 = (*_67);
-+         _69 = _66;
+          _69 = (*_67);
           StorageLive(_70);
           StorageLive(_71);
           _71 = ();
@@ -436,8 +429,8 @@
           StorageDead(_70);
           _0 = const ();
           StorageDead(_69);
--         StorageDead(_68);
--         StorageDead(_67);
+          StorageDead(_68);
+          StorageDead(_67);
           StorageDead(_66);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
index 05eab7989df..ce5ddbfdd12 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_const_ptr.ReferencePropagation.diff
@@ -45,8 +45,7 @@
               debug a => _4;
               let _5: *const usize;
               scope 3 {
--                 debug b => _5;
-+                 debug b => &_4;
+                  debug b => _5;
                   let _6: usize;
                   scope 4 {
                       debug c => _6;
@@ -175,12 +174,10 @@
               debug a => _58;
               let _59: *const usize;
               scope 39 {
--                 debug b => _59;
-+                 debug b => &_58;
+                  debug b => _59;
                   let _60: *const usize;
                   scope 40 {
--                     debug c => _60;
-+                     debug c => &_58;
+                      debug c => _60;
                       let _61: usize;
                       scope 41 {
                           debug e => _61;
@@ -195,12 +192,10 @@
               debug a => _65;
               let _66: *const usize;
               scope 44 {
--                 debug b => _66;
-+                 debug b => &_65;
+                  debug b => _66;
                   let _67: &*const usize;
                   scope 45 {
--                     debug d => _67;
-+                     debug d => &&_65;
+                      debug d => _67;
                       let _68: usize;
                       scope 46 {
                           debug c => _68;
@@ -215,12 +210,10 @@
               debug a => _71;
               let mut _72: *const usize;
               scope 49 {
--                 debug b => _72;
-+                 debug b => &_71;
+                  debug b => _72;
                   let _73: &mut *const usize;
                   scope 50 {
--                     debug d => _73;
-+                     debug d => &&_71;
+                      debug d => _73;
                       let _74: usize;
                       scope 51 {
                           debug c => _74;
@@ -234,8 +227,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &raw const _4;
+          StorageLive(_5);
+          _5 = &raw const _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -250,7 +243,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -427,10 +420,11 @@
 -         StorageLive(_57);
           StorageLive(_58);
           _58 = const 13_usize;
--         StorageLive(_59);
--         _59 = &raw const _58;
--         StorageLive(_60);
+          StorageLive(_59);
+          _59 = &raw const _58;
+          StorageLive(_60);
 -         _60 = &raw const (*_59);
++         _60 = &raw const _58;
           StorageLive(_61);
 -         _61 = (*_60);
 +         _61 = _58;
@@ -445,20 +439,19 @@
           StorageDead(_62);
 -         _57 = const ();
           StorageDead(_61);
--         StorageDead(_60);
--         StorageDead(_59);
+          StorageDead(_60);
+          StorageDead(_59);
           StorageDead(_58);
 -         StorageDead(_57);
 -         StorageLive(_64);
           StorageLive(_65);
           _65 = const 5_usize;
--         StorageLive(_66);
--         _66 = &raw const _65;
--         StorageLive(_67);
--         _67 = &_66;
+          StorageLive(_66);
+          _66 = &raw const _65;
+          StorageLive(_67);
+          _67 = &_66;
           StorageLive(_68);
--         _68 = (*_66);
-+         _68 = _65;
+          _68 = (*_66);
           StorageLive(_69);
           StorageLive(_70);
           _70 = ();
@@ -470,19 +463,18 @@
           StorageDead(_69);
 -         _64 = const ();
           StorageDead(_68);
--         StorageDead(_67);
--         StorageDead(_66);
+          StorageDead(_67);
+          StorageDead(_66);
           StorageDead(_65);
 -         StorageDead(_64);
           StorageLive(_71);
           _71 = const 5_usize;
--         StorageLive(_72);
--         _72 = &raw const _71;
--         StorageLive(_73);
--         _73 = &mut _72;
+          StorageLive(_72);
+          _72 = &raw const _71;
+          StorageLive(_73);
+          _73 = &mut _72;
           StorageLive(_74);
--         _74 = (*_72);
-+         _74 = _71;
+          _74 = (*_72);
           StorageLive(_75);
           StorageLive(_76);
           _76 = ();
@@ -494,8 +486,8 @@
           StorageDead(_75);
           _0 = const ();
           StorageDead(_74);
--         StorageDead(_73);
--         StorageDead(_72);
+          StorageDead(_73);
+          StorageDead(_72);
           StorageDead(_71);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
index ee680fdb3f2..7c7f424bba2 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut.ReferencePropagation.diff
@@ -52,8 +52,7 @@
           debug a => _4;
           let _5: &mut usize;
           scope 2 {
--             debug b => _5;
-+             debug b => &_4;
+              debug b => _5;
               let _6: usize;
               scope 3 {
                   debug c => _6;
@@ -158,12 +157,10 @@
           debug a => _60;
           let _61: &mut usize;
           scope 30 {
--             debug b => _61;
-+             debug b => &_60;
+              debug b => _61;
               let _62: &&mut usize;
               scope 31 {
--                 debug d => _62;
-+                 debug d => &&_60;
+                  debug d => _62;
                   let _63: usize;
                   scope 32 {
                       debug c => _63;
@@ -175,12 +172,10 @@
           debug a => _66;
           let mut _67: &mut usize;
           scope 34 {
--             debug b => _67;
-+             debug b => &_66;
+              debug b => _67;
               let _68: &mut &mut usize;
               scope 35 {
--                 debug d => _68;
-+                 debug d => &&_66;
+                  debug d => _68;
                   let _69: usize;
                   scope 36 {
                       debug c => _69;
@@ -193,8 +188,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &mut _4;
+          StorageLive(_5);
+          _5 = &mut _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -209,7 +204,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -391,13 +386,12 @@
 -         StorageLive(_59);
           StorageLive(_60);
           _60 = const 5_usize;
--         StorageLive(_61);
--         _61 = &mut _60;
--         StorageLive(_62);
--         _62 = &_61;
+          StorageLive(_61);
+          _61 = &mut _60;
+          StorageLive(_62);
+          _62 = &_61;
           StorageLive(_63);
--         _63 = (*_61);
-+         _63 = _60;
+          _63 = (*_61);
           StorageLive(_64);
           StorageLive(_65);
           _65 = ();
@@ -409,19 +403,18 @@
           StorageDead(_64);
 -         _59 = const ();
           StorageDead(_63);
--         StorageDead(_62);
--         StorageDead(_61);
+          StorageDead(_62);
+          StorageDead(_61);
           StorageDead(_60);
 -         StorageDead(_59);
           StorageLive(_66);
           _66 = const 5_usize;
--         StorageLive(_67);
--         _67 = &mut _66;
--         StorageLive(_68);
--         _68 = &mut _67;
+          StorageLive(_67);
+          _67 = &mut _66;
+          StorageLive(_68);
+          _68 = &mut _67;
           StorageLive(_69);
--         _69 = (*_67);
-+         _69 = _66;
+          _69 = (*_67);
           StorageLive(_70);
           StorageLive(_71);
           _71 = ();
@@ -433,8 +426,8 @@
           StorageDead(_70);
           _0 = const ();
           StorageDead(_69);
--         StorageDead(_68);
--         StorageDead(_67);
+          StorageDead(_68);
+          StorageDead(_67);
           StorageDead(_66);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
index fb0ef3184f0..b6b2acc0b43 100644
--- a/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
+++ b/tests/mir-opt/reference_prop.reference_propagation_mut_ptr.ReferencePropagation.diff
@@ -42,8 +42,7 @@
               debug a => _4;
               let _5: *mut usize;
               scope 3 {
--                 debug b => _5;
-+                 debug b => &_4;
+                  debug b => _5;
                   let _6: usize;
                   scope 4 {
                       debug c => _6;
@@ -172,12 +171,10 @@
               debug a => _58;
               let _59: *mut usize;
               scope 39 {
--                 debug b => _59;
-+                 debug b => &_58;
+                  debug b => _59;
                   let _60: &*mut usize;
                   scope 40 {
--                     debug d => _60;
-+                     debug d => &&_58;
+                      debug d => _60;
                       let _61: usize;
                       scope 41 {
                           debug c => _61;
@@ -192,12 +189,10 @@
               debug a => _64;
               let mut _65: *mut usize;
               scope 44 {
--                 debug b => _65;
-+                 debug b => &_64;
+                  debug b => _65;
                   let _66: &mut *mut usize;
                   scope 45 {
--                     debug d => _66;
-+                     debug d => &&_64;
+                      debug d => _66;
                       let _67: usize;
                       scope 46 {
                           debug c => _67;
@@ -211,8 +206,8 @@
 -         StorageLive(_3);
           StorageLive(_4);
           _4 = const 5_usize;
--         StorageLive(_5);
--         _5 = &raw mut _4;
+          StorageLive(_5);
+          _5 = &raw mut _4;
           StorageLive(_6);
 -         _6 = (*_5);
 +         _6 = _4;
@@ -227,7 +222,7 @@
           StorageDead(_7);
 -         _3 = const ();
           StorageDead(_6);
--         StorageDead(_5);
+          StorageDead(_5);
           StorageDead(_4);
 -         StorageDead(_3);
 -         StorageLive(_9);
@@ -401,13 +396,12 @@
 -         StorageLive(_57);
           StorageLive(_58);
           _58 = const 5_usize;
--         StorageLive(_59);
--         _59 = &raw mut _58;
--         StorageLive(_60);
--         _60 = &_59;
+          StorageLive(_59);
+          _59 = &raw mut _58;
+          StorageLive(_60);
+          _60 = &_59;
           StorageLive(_61);
--         _61 = (*_59);
-+         _61 = _58;
+          _61 = (*_59);
           StorageLive(_62);
           StorageLive(_63);
           _63 = ();
@@ -419,19 +413,18 @@
           StorageDead(_62);
 -         _57 = const ();
           StorageDead(_61);
--         StorageDead(_60);
--         StorageDead(_59);
+          StorageDead(_60);
+          StorageDead(_59);
           StorageDead(_58);
 -         StorageDead(_57);
           StorageLive(_64);
           _64 = const 5_usize;
--         StorageLive(_65);
--         _65 = &raw mut _64;
--         StorageLive(_66);
--         _66 = &mut _65;
+          StorageLive(_65);
+          _65 = &raw mut _64;
+          StorageLive(_66);
+          _66 = &mut _65;
           StorageLive(_67);
--         _67 = (*_65);
-+         _67 = _64;
+          _67 = (*_65);
           StorageLive(_68);
           StorageLive(_69);
           _69 = ();
@@ -443,8 +436,8 @@
           StorageDead(_68);
           _0 = const ();
           StorageDead(_67);
--         StorageDead(_66);
--         StorageDead(_65);
+          StorageDead(_66);
+          StorageDead(_65);
           StorageDead(_64);
           return;
       }
diff --git a/tests/mir-opt/reference_prop.rs b/tests/mir-opt/reference_prop.rs
index 4083b45470b..610660131b1 100644
--- a/tests/mir-opt/reference_prop.rs
+++ b/tests/mir-opt/reference_prop.rs
@@ -426,7 +426,7 @@ fn multiple_storage() {
             // As there are multiple `StorageLive` statements for `x`, we cannot know if this `z`'s
             // pointer address is the address of `x`, so do nothing.
             let y = *z;
-            Call(RET, retblock, opaque(y))
+            Call(RET = opaque(y), retblock)
         }
 
         retblock = {
@@ -452,7 +452,7 @@ fn dominate_storage() {
         }
         bb1 = {
             let c = *r;
-            Call(RET, bb2, opaque(c))
+            Call(RET = opaque(c), bb2)
         }
         bb2 = {
             StorageDead(x);
@@ -486,18 +486,18 @@ fn maybe_dead(m: bool) {
         bb1 = {
             StorageDead(x);
             StorageDead(y);
-            Call(RET, bb2, opaque(u))
+            Call(RET = opaque(u), bb2)
         }
         bb2 = {
             // As `x` may be `StorageDead`, `a` may be dangling, so we do nothing.
             let z = *a;
-            Call(RET, bb3, opaque(z))
+            Call(RET = opaque(z), bb3)
         }
         bb3 = {
             // As `y` may be `StorageDead`, `b` may be dangling, so we do nothing.
             // This implies that we also do not substitute `b` in `bb0`.
             let t = *b;
-            Call(RET, retblock, opaque(t))
+            Call(RET = opaque(t), retblock)
         }
         retblock = {
             Return()
diff --git a/tests/run-make/optimization-remarks-dir-pgo/Makefile b/tests/run-make/optimization-remarks-dir-pgo/Makefile
index c88ec1e6cb3..3bc3d7d1428 100644
--- a/tests/run-make/optimization-remarks-dir-pgo/Makefile
+++ b/tests/run-make/optimization-remarks-dir-pgo/Makefile
@@ -1,5 +1,6 @@
 # needs-profiler-support
 # ignore-windows-gnu
+# ignore-cross-compile
 
 # FIXME(mati865): MinGW GCC miscompiles compiler-rt profiling library but with Clang it works
 # properly. Since we only have GCC on the CI ignore the test for now.
diff --git a/tests/run-make/panic-abort-eh_frame/Makefile b/tests/run-make/panic-abort-eh_frame/Makefile
index 1cb7bf575cb..7020455b742 100644
--- a/tests/run-make/panic-abort-eh_frame/Makefile
+++ b/tests/run-make/panic-abort-eh_frame/Makefile
@@ -6,5 +6,5 @@
 include ../tools.mk
 
 all:
-	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort
+	$(RUSTC) foo.rs --crate-type=lib --emit=obj=$(TMPDIR)/foo.o -Cpanic=abort --edition 2021 -Z validate-mir
 	objdump --dwarf=frames $(TMPDIR)/foo.o | $(CGREP) -v 'DW_CFA'
diff --git a/tests/run-make/panic-abort-eh_frame/foo.rs b/tests/run-make/panic-abort-eh_frame/foo.rs
index e1853529455..e2274d469e7 100644
--- a/tests/run-make/panic-abort-eh_frame/foo.rs
+++ b/tests/run-make/panic-abort-eh_frame/foo.rs
@@ -1,5 +1,13 @@
 #![no_std]
 
+use core::future::Future;
+
+pub struct NeedsDrop;
+
+impl Drop for NeedsDrop {
+    fn drop(&mut self) {}
+}
+
 #[panic_handler]
 fn handler(_: &core::panic::PanicInfo<'_>) -> ! {
     loop {}
@@ -8,3 +16,19 @@ fn handler(_: &core::panic::PanicInfo<'_>) -> ! {
 pub unsafe fn oops(x: *const u32) -> u32 {
     *x
 }
+
+pub async fn foo(_: NeedsDrop) {
+    async fn bar() {}
+    bar().await;
+}
+
+pub fn poll_foo(x: &mut core::task::Context<'_>) {
+    let _g = NeedsDrop;
+    let mut p = core::pin::pin!(foo(NeedsDrop));
+    let _ = p.as_mut().poll(x);
+    let _ = p.as_mut().poll(x);
+}
+
+pub fn drop_foo() {
+    drop(foo(NeedsDrop));
+}
diff --git a/tests/rustdoc-gui/docblock-table.goml b/tests/rustdoc-gui/docblock-table.goml
index 011451ef4f3..678b302f22e 100644
--- a/tests/rustdoc-gui/docblock-table.goml
+++ b/tests/rustdoc-gui/docblock-table.goml
@@ -36,17 +36,17 @@ define-function: (
 )
 
 call-function: ("check-colors", {
-    "theme": "dark",
-    "border_color": "rgb(224, 224, 224)",
-    "zebra_stripe_color": "rgb(42, 42, 42)",
+    "theme": "ayu",
+    "border_color": "#5c6773",
+    "zebra_stripe_color": "#191f26",
 })
 call-function: ("check-colors", {
-    "theme": "ayu",
-    "border_color": "rgb(92, 103, 115)",
-    "zebra_stripe_color": "rgb(25, 31, 38)",
+    "theme": "dark",
+    "border_color": "#e0e0e0",
+    "zebra_stripe_color": "#2a2a2a",
 })
 call-function: ("check-colors", {
     "theme": "light",
-    "border_color": "rgb(224, 224, 224)",
-    "zebra_stripe_color": "rgb(245, 245, 245)",
+    "border_color": "#e0e0e0",
+    "zebra_stripe_color": "#f5f5f5",
 })
diff --git a/tests/rustdoc-gui/search-form-elements.goml b/tests/rustdoc-gui/search-form-elements.goml
index 83c6980909c..a4e22364859 100644
--- a/tests/rustdoc-gui/search-form-elements.goml
+++ b/tests/rustdoc-gui/search-form-elements.goml
@@ -2,262 +2,138 @@
 go-to: "file://" + |DOC_PATH| + "/test_docs/index.html"
 show-text: true
 
-// Ayu theme
-set-local-storage: {
-    "rustdoc-theme": "ayu",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-        "color": "rgb(255, 255, 255)",
-    },
-)
-focus: ".search-input"
-// Nothing should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-        "color": "rgb(255, 255, 255)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(255, 255, 255)",
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(255, 255, 255)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(57, 175, 215)",
-    },
-)
-
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(92, 103, 115)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(197, 197, 197)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(20, 25, 32)",
-    },
-)
-
-// Dark theme
-set-local-storage: {
-    "rustdoc-theme": "dark",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-        "color": "rgb(17, 17, 17)",
-    },
-)
-focus: ".search-input"
-// Only "border-color" should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(0, 141, 253)",
-        "background-color": "rgb(240, 240, 240)",
-        "color": "rgb(17, 17, 17)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(255, 185, 0)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(210, 153, 29)",
+define-function: (
+    "check-search-colors",
+    (
+        theme, border, background, search_input_color, search_input_border_focus,
+        menu_button_border, menu_button_a_color, menu_button_a_border_hover, menu_a_color,
+    ),
+    block {
+        set-local-storage: {
+            "rustdoc-theme": |theme|,
+            "rustdoc-use-system-theme": "false",
+        }
+        reload:
+        assert-css: (
+            ".search-input",
+            {
+                "border-color": |border|,
+                "background-color": |background|,
+                "color": |search_input_color|,
+            },
+        )
+        // Focus on search input.
+        focus: ".search-input"
+        assert-css: (
+            ".search-input",
+            {
+                "border-color": |search_input_border_focus|,
+                "background-color": |background|,
+                "color": |search_input_color|,
+            },
+        )
+        assert-css: (
+            "#help-button",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#help-button > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |border|,
+                "background-color": |background|,
+            },
+        )
+        // Hover help button.
+        move-cursor-to: "#help-button"
+        assert-css: (
+            "#help-button:hover",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#help-button > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |menu_button_a_border_hover|,
+                "background-color": |background|,
+            },
+        )
+        // Link color inside
+        click: "#help-button"
+        assert-css: (
+            "#help a",
+            {
+                "color": |menu_a_color|,
+            },
+        )
+        assert-css: (
+            "#settings-menu",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#settings-menu > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |border|,
+                "background-color": |background|,
+            },
+        )
+        // Hover settings menu.
+        move-cursor-to: "#settings-menu"
+        assert-css: (
+            "#settings-menu:hover",
+            {"border-color": |menu_button_border|},
+        )
+        assert-css: (
+            "#settings-menu:hover > a",
+            {
+                "color": |menu_button_a_color|,
+                "border-color": |menu_button_a_border_hover|,
+                "background-color": |background|,
+            },
+        )
     },
 )
 
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(221, 221, 221)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(255, 185, 0)",
-        "background-color": "rgb(240, 240, 240)",
-    },
-)
-
-// Light theme
-set-local-storage: {
-    "rustdoc-theme": "light",
-    "rustdoc-use-system-theme": "false",
-}
-reload:
-
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-        "color": "rgb(0, 0, 0)",
-    },
-)
-focus: ".search-input"
-// Nothing should change.
-assert-css: (
-    ".search-input",
-    {
-        "border-color": "rgb(102, 175, 233)",
-        "background-color": "rgb(255, 255, 255)",
-        "color": "rgb(0, 0, 0)",
-    },
-)
-
-assert-css: (
-    "#help-button",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-assert-css: (
-    "#help-button > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-move-cursor-to: "#help-button"
-assert-css: (
-    "#help-button:hover",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#help-button:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(113, 113, 113)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-// Link color inside
-click: "#help-button"
-assert-css: (
-    "#help a",
-    {
-        "color": "rgb(56, 115, 173)",
-    },
-)
-
-assert-css: (
-    "#settings-menu",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-assert-css: (
-    "#settings-menu > a",
-    {
-        "border-color": "rgb(224, 224, 224)",
-        "background-color": "rgb(255, 255, 255)",
-    },
-)
-move-cursor-to: "#settings-menu"
-assert-css: (
-    "#settings-menu:hover",
-    {"border-color": "rgb(0, 0, 0)"},
-)
-// Only "border-color" should change.
-assert-css: (
-    "#settings-menu:hover > a",
-    {
-        "color": "rgb(0, 0, 0)",
-        "border-color": "rgb(113, 113, 113)",
-        "background-color": "rgb(255, 255, 255)",
-    },
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "ayu",
+        "border": "#5c6773",
+        "background": "#141920",
+        "search_input_color": "#fff",
+        "search_input_border_focus": "#5c6773",
+        "menu_button_border": "#c5c5c5",
+        "menu_button_a_color": "#fff",
+        "menu_button_a_border_hover": "#e0e0e0",
+        "menu_a_color": "#39afd7",
+    }
+)
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "dark",
+        "border": "#e0e0e0",
+        "background": "#f0f0f0",
+        "search_input_color": "#111",
+        "search_input_border_focus": "#008dfd",
+        "menu_button_border": "#ddd",
+        "menu_button_a_color": "#000",
+        "menu_button_a_border_hover": "#ffb900",
+        "menu_a_color": "#d2991d",
+    }
+)
+call-function: (
+    "check-search-colors",
+    {
+        "theme": "light",
+        "border": "#e0e0e0",
+        "background": "#fff",
+        "search_input_color": "#000",
+        "search_input_border_focus": "#66afe9",
+        "menu_button_border": "#000",
+        "menu_button_a_color": "#000",
+        "menu_button_a_border_hover": "#717171",
+        "menu_a_color": "#3873ad",
+    }
 )
diff --git a/tests/rustdoc-gui/src/test_docs/lib.rs b/tests/rustdoc-gui/src/test_docs/lib.rs
index 49484ee0869..38180aef762 100644
--- a/tests/rustdoc-gui/src/test_docs/lib.rs
+++ b/tests/rustdoc-gui/src/test_docs/lib.rs
@@ -65,6 +65,18 @@ impl Foo {
     pub fn must_use(&self) -> bool {
         true
     }
+
+    /// hello
+    ///
+    /// <div id="doc-warning-1" class="warning">this is a warning</div>
+    ///
+    /// done
+    pub fn warning1() {}
+
+    /// Checking there is no bottom margin if "warning" is the last element.
+    ///
+    /// <div id="doc-warning-2" class="warning">this is a warning</div>
+    pub fn warning2() {}
 }
 
 impl AsRef<str> for Foo {
diff --git a/tests/rustdoc-gui/warning-block.goml b/tests/rustdoc-gui/warning-block.goml
new file mode 100644
index 00000000000..2a935bd1a9b
--- /dev/null
+++ b/tests/rustdoc-gui/warning-block.goml
@@ -0,0 +1,45 @@
+// Test to check that the "warning blocks" are displayed as expected.
+go-to: "file://" + |DOC_PATH| + "/test_docs/struct.Foo.html"
+show-text: true
+
+define-function: (
+    "check-warning",
+    (theme, color, border_color, background_color),
+    block {
+        set-local-storage: {"rustdoc-theme": |theme|, "rustdoc-use-system-theme": "false"}
+        reload:
+
+        // The IDs are added directly into the DOM to make writing this test easier.
+        assert-css: ("#doc-warning-1", {
+            "margin-bottom": "12px",
+            "color": |color|,
+            "border-left": "2px solid " + |border_color|,
+            "background-color": |background_color|,
+        })
+        assert-css: ("#doc-warning-2", {
+            "margin-bottom": "0px",
+            "color": |color|,
+            "border-left": "2px solid " + |border_color|,
+            "background-color": |background_color|,
+        })
+    },
+)
+
+call-function: ("check-warning", {
+    "theme": "ayu",
+    "color": "rgb(197, 197, 197)",
+    "border_color": "rgb(255, 142, 0)",
+    "background_color": "rgba(0, 0, 0, 0)",
+})
+call-function: ("check-warning", {
+    "theme": "dark",
+    "color": "rgb(221, 221, 221)",
+    "border_color": "rgb(255, 142, 0)",
+    "background_color": "rgba(0, 0, 0, 0)",
+})
+call-function: ("check-warning", {
+    "theme": "light",
+    "color": "rgb(0, 0, 0)",
+    "border_color": "rgb(255, 142, 0)",
+    "background_color": "rgba(0, 0, 0, 0)",
+})
diff --git a/tests/rustdoc-ui/lints/inline-doc-link.rs b/tests/rustdoc-ui/lints/inline-doc-link.rs
new file mode 100644
index 00000000000..596f89be3d6
--- /dev/null
+++ b/tests/rustdoc-ui/lints/inline-doc-link.rs
@@ -0,0 +1,13 @@
+// Regression test for <https://github.com/rust-lang/rust/pull/113167>
+
+// check-pass
+#![deny(rustdoc::redundant_explicit_links)]
+
+mod m {
+    pub enum ValueEnum {}
+}
+mod m2 {
+    /// [`ValueEnum`]
+    pub use crate::m::ValueEnum;
+}
+pub use m2::ValueEnum;
diff --git a/tests/rustdoc-ui/lints/no-redundancy.rs b/tests/rustdoc-ui/lints/no-redundancy.rs
new file mode 100644
index 00000000000..e3358728b1b
--- /dev/null
+++ b/tests/rustdoc-ui/lints/no-redundancy.rs
@@ -0,0 +1,7 @@
+// check-pass
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+/// [Vec][std::vec::Vec#examples] should not warn, because it's not actually redundant!
+/// [This is just an `Option`][std::option::Option] has different display content to actual link!
+pub fn func() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
new file mode 100644
index 00000000000..fecefb7b25f
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links-utf8.rs
@@ -0,0 +1,18 @@
+// check-pass
+
+/// [`…foo`] [`…bar`] [`Err`]
+pub struct Broken {}
+
+/// [`…`] [`…`] [`Err`]
+pub struct Broken2 {}
+
+/// [`…`][…] [`…`][…] [`Err`]
+pub struct Broken3 {}
+
+/// […………………………][Broken3]
+pub struct Broken4 {}
+
+/// [Broken3][…………………………]
+pub struct Broken5 {}
+
+pub struct Err;
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.fixed b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
new file mode 100644
index 00000000000..900234e31e9
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.fixed
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`]
+//~^ ERROR redundant explicit link target
+///
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.rs b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
new file mode 100644
index 00000000000..13feb85e051
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.rs
@@ -0,0 +1,158 @@
+// run-rustfix
+
+#![deny(rustdoc::redundant_explicit_links)]
+
+pub fn dummy_target() {}
+
+/// [dummy_target](dummy_target)
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target)
+//~^ ERROR redundant explicit link target
+///
+/// [Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](Vec)
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`](std::vec::Vec)
+//~^ ERROR redundant explicit link target
+///
+/// [usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](usize)
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`](std::primitive::usize)
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`](dummy_target) TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_inline() {}
+
+/// [`Vec<T>`](Vec)
+/// [`Vec<T>`](std::vec::Vec)
+pub fn should_not_warn_inline() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+pub fn should_warn_reference_unknown() {}
+
+/// [`Vec<T>`][Vec]
+/// [`Vec<T>`][std::vec::Vec]
+pub fn should_not_warn_reference_unknown() {}
+
+/// [dummy_target][dummy_target]
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target]
+//~^ ERROR redundant explicit link target
+///
+/// [Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][Vec]
+//~^ ERROR redundant explicit link target
+/// [std::vec::Vec][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+/// [`std::vec::Vec`][std::vec::Vec]
+//~^ ERROR redundant explicit link target
+///
+/// [usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][usize]
+//~^ ERROR redundant explicit link target
+/// [std::primitive::usize][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+/// [`std::primitive::usize`][std::primitive::usize]
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+/// [`dummy_target`][dummy_target] TEXT
+//~^ ERROR redundant explicit link target
+///
+/// [dummy_target]: dummy_target
+/// [Vec]: Vec
+/// [std::vec::Vec]: Vec
+/// [usize]: usize
+/// [std::primitive::usize]: usize
+pub fn should_warn_reference() {}
+
+/// [`Vec<T>`]: Vec
+/// [`Vec<T>`]: std::vec::Vec
+pub fn should_not_warn_reference() {}
diff --git a/tests/rustdoc-ui/lints/redundant_explicit_links.stderr b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
new file mode 100644
index 00000000000..34ec9be6646
--- /dev/null
+++ b/tests/rustdoc-ui/lints/redundant_explicit_links.stderr
@@ -0,0 +1,1007 @@
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:7:20
+   |
+LL | /// [dummy_target](dummy_target)
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+note: the lint level is defined here
+  --> $DIR/redundant_explicit_links.rs:3:9
+   |
+LL | #![deny(rustdoc::redundant_explicit_links)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:9:22
+   |
+LL | /// [`dummy_target`](dummy_target)
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:12:11
+   |
+LL | /// [Vec](Vec)
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:14:13
+   |
+LL | /// [`Vec`](Vec)
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:16:11
+   |
+LL | /// [Vec](std::vec::Vec)
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:18:13
+   |
+LL | /// [`Vec`](std::vec::Vec)
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:20:21
+   |
+LL | /// [std::vec::Vec](Vec)
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:22:23
+   |
+LL | /// [`std::vec::Vec`](Vec)
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:24:21
+   |
+LL | /// [std::vec::Vec](std::vec::Vec)
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:26:23
+   |
+LL | /// [`std::vec::Vec`](std::vec::Vec)
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:29:13
+   |
+LL | /// [usize](usize)
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:31:15
+   |
+LL | /// [`usize`](usize)
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:33:13
+   |
+LL | /// [usize](std::primitive::usize)
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:35:15
+   |
+LL | /// [`usize`](std::primitive::usize)
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:37:29
+   |
+LL | /// [std::primitive::usize](usize)
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:39:31
+   |
+LL | /// [`std::primitive::usize`](usize)
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:41:29
+   |
+LL | /// [std::primitive::usize](std::primitive::usize)
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:43:31
+   |
+LL | /// [`std::primitive::usize`](std::primitive::usize)
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:46:20
+   |
+LL | /// [dummy_target](dummy_target) TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:48:22
+   |
+LL | /// [`dummy_target`](dummy_target) TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:56:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:58:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:61:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:63:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:65:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:67:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:69:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:71:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:73:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:75:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:78:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:80:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:82:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:84:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:86:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:88:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:90:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:92:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:95:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:97:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:105:20
+   |
+LL | /// [dummy_target][dummy_target]
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target]
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:107:22
+   |
+LL | /// [`dummy_target`][dummy_target]
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`]
+   |     ~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:110:11
+   |
+LL | /// [Vec][Vec]
+   |      ---  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:112:13
+   |
+LL | /// [`Vec`][Vec]
+   |      -----  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:114:11
+   |
+LL | /// [Vec][std::vec::Vec]
+   |      ---  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [Vec]
+   |     ~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:116:13
+   |
+LL | /// [`Vec`][std::vec::Vec]
+   |      -----  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`Vec`]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:118:21
+   |
+LL | /// [std::vec::Vec][Vec]
+   |      -------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:120:23
+   |
+LL | /// [`std::vec::Vec`][Vec]
+   |      ---------------  ^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:150:12
+   |
+LL | /// [Vec]: Vec
+   |            ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:122:21
+   |
+LL | /// [std::vec::Vec][std::vec::Vec]
+   |      -------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::vec::Vec]
+   |     ~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:124:23
+   |
+LL | /// [`std::vec::Vec`][std::vec::Vec]
+   |      ---------------  ^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:151:22
+   |
+LL | /// [std::vec::Vec]: Vec
+   |                      ^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::vec::Vec`]
+   |     ~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:127:13
+   |
+LL | /// [usize][usize]
+   |      -----  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:129:15
+   |
+LL | /// [`usize`][usize]
+   |      -------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:131:13
+   |
+LL | /// [usize][std::primitive::usize]
+   |      -----  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [usize]
+   |     ~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:133:15
+   |
+LL | /// [`usize`][std::primitive::usize]
+   |      -------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`usize`]
+   |     ~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:135:29
+   |
+LL | /// [std::primitive::usize][usize]
+   |      ---------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:137:31
+   |
+LL | /// [`std::primitive::usize`][usize]
+   |      -----------------------  ^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:152:14
+   |
+LL | /// [usize]: usize
+   |              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:139:29
+   |
+LL | /// [std::primitive::usize][std::primitive::usize]
+   |      ---------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [std::primitive::usize]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:141:31
+   |
+LL | /// [`std::primitive::usize`][std::primitive::usize]
+   |      -----------------------  ^^^^^^^^^^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:153:30
+   |
+LL | /// [std::primitive::usize]: usize
+   |                              ^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`std::primitive::usize`]
+   |     ~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:144:20
+   |
+LL | /// [dummy_target][dummy_target] TEXT
+   |      ------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [dummy_target] TEXT
+   |     ~~~~~~~~~~~~~~
+
+error: redundant explicit link target
+  --> $DIR/redundant_explicit_links.rs:146:22
+   |
+LL | /// [`dummy_target`][dummy_target] TEXT
+   |      --------------  ^^^^^^^^^^^^ explicit target is redundant
+   |      |
+   |      because label contains path that resolves to same destination
+   |
+note: referenced explicit link target defined here
+  --> $DIR/redundant_explicit_links.rs:149:21
+   |
+LL | /// [dummy_target]: dummy_target
+   |                     ^^^^^^^^^^^^
+   = note: when a link's destination is not specified,
+           the label is used to resolve intra-doc links
+help: remove explicit link target
+   |
+LL | /// [`dummy_target`] TEXT
+   |     ~~~~~~~~~~~~~~~~
+
+error: aborting due to 60 previous errors
+
diff --git a/tests/rustdoc-ui/unescaped_backticks.rs b/tests/rustdoc-ui/unescaped_backticks.rs
index e99cd1f3d58..e960e9f59e9 100644
--- a/tests/rustdoc-ui/unescaped_backticks.rs
+++ b/tests/rustdoc-ui/unescaped_backticks.rs
@@ -1,6 +1,7 @@
 #![deny(rustdoc::unescaped_backticks)]
 #![allow(rustdoc::broken_intra_doc_links)]
 #![allow(rustdoc::invalid_html_tags)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 ///
 pub fn empty() {}
diff --git a/tests/rustdoc-ui/unescaped_backticks.stderr b/tests/rustdoc-ui/unescaped_backticks.stderr
index bf1f18889c4..83822f778d0 100644
--- a/tests/rustdoc-ui/unescaped_backticks.stderr
+++ b/tests/rustdoc-ui/unescaped_backticks.stderr
@@ -1,5 +1,5 @@
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:186:70
+  --> $DIR/unescaped_backticks.rs:187:70
    |
 LL | /// if you want your MIR to be modified by the full MIR pipeline, or `#![custom_mir(dialect =
    |                                                                      ^
@@ -19,7 +19,7 @@ LL | /// if you want your MIR to be modified by the full MIR pipeline, or \`#![c
    |                                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:231:13
+  --> $DIR/unescaped_backticks.rs:232:13
    |
 LL |         //! `#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kind="post-lto")]
    |             ^
@@ -34,7 +34,7 @@ LL |         //! \`#![rustc_expected_cgu_reuse(module="spike", cfg="rpass2", kin
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:236:13
+  --> $DIR/unescaped_backticks.rs:237:13
    |
 LL |         /// `cfg=...
    |             ^
@@ -49,7 +49,7 @@ LL |         /// \`cfg=...
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:240:42
+  --> $DIR/unescaped_backticks.rs:241:42
    |
 LL |         /// `cfg=... and not `#[cfg_attr]`
    |                                          ^
@@ -64,7 +64,7 @@ LL |         /// `cfg=... and not `#[cfg_attr]\`
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:192:91
+  --> $DIR/unescaped_backticks.rs:193:91
    |
 LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug` with the given `msg to
    |                                                                                           ^
@@ -79,7 +79,7 @@ LL |     /// Constructs a `TyKind::Error` type and registers a `delay_span_bug`
    |                                                                                           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:201:34
+  --> $DIR/unescaped_backticks.rs:202:34
    |
 LL |         /// in `nt_to_tokenstream`
    |                                  ^
@@ -94,7 +94,7 @@ LL |         /// in `nt_to_tokenstream\`
    |                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:207:62
+  --> $DIR/unescaped_backticks.rs:208:62
    |
 LL |     /// that `Option<Symbol>` only takes up 4 bytes, because `newtype_index! reserves
    |                                                              ^
@@ -109,7 +109,7 @@ LL |     /// that `Option<Symbol>` only takes up 4 bytes, because \`newtype_inde
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:215:52
+  --> $DIR/unescaped_backticks.rs:216:52
    |
 LL |     /// also avoids the need to import `OpenOptions`.
    |                                                    ^
@@ -124,7 +124,7 @@ LL |     /// also avoids the need to import `OpenOptions\`.
    |                                                    +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:220:46
+  --> $DIR/unescaped_backticks.rs:221:46
    |
 LL |     /// `HybridBitSet`. Has no effect if `row` does not exist.
    |                                              ^
@@ -139,7 +139,7 @@ LL |     /// `HybridBitSet`. Has no effect if `row\` does not exist.
    |                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:246:12
+  --> $DIR/unescaped_backticks.rs:247:12
    |
 LL |     /// RWU`s can get very large, so it uses a more compact representation.
    |            ^
@@ -154,7 +154,7 @@ LL |     /// RWU\`s can get very large, so it uses a more compact representation
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:253:15
+  --> $DIR/unescaped_backticks.rs:254:15
    |
 LL |     /// in `U2`.
    |               ^
@@ -169,7 +169,7 @@ LL |     /// in `U2\`.
    |               +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:270:42
+  --> $DIR/unescaped_backticks.rs:271:42
    |
 LL |     /// because it contains `[type error]`. Yuck! (See issue #29857 for
    |                                          ^
@@ -184,7 +184,7 @@ LL |     /// because it contains `[type error]\`. Yuck! (See issue #29857 for
    |                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:280:53
+  --> $DIR/unescaped_backticks.rs:281:53
    |
 LL |     /// well as the second instance of `A: AutoTrait`) to suppress
    |                                                     ^
@@ -199,7 +199,7 @@ LL |     /// well as the second instance of `A: AutoTrait\`) to suppress
    |                                                     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:290:40
+  --> $DIR/unescaped_backticks.rs:291:40
    |
 LL |     /// `'a` with `'b` and not `'static`. But it will have to do for
    |                                        ^
@@ -211,7 +211,7 @@ LL |     /// `'a` with `'b` and not `'static\`. But it will have to do for
    |                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:299:54
+  --> $DIR/unescaped_backticks.rs:300:54
    |
 LL | /// `None`. Otherwise, it will return `Some(Dispatch)`.
    |                                                      ^
@@ -226,7 +226,7 @@ LL | /// `None`. Otherwise, it will return `Some(Dispatch)\`.
    |                                                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:303:13
+  --> $DIR/unescaped_backticks.rs:304:13
    |
 LL | /// or `None` if it isn't.
    |             ^
@@ -238,7 +238,7 @@ LL | /// or `None\` if it isn't.
    |             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:307:14
+  --> $DIR/unescaped_backticks.rs:308:14
    |
 LL | /// `on_event` should be called.
    |              ^
@@ -253,7 +253,7 @@ LL | /// `on_event\` should be called.
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:312:29
+  --> $DIR/unescaped_backticks.rs:313:29
    |
 LL | /// [`rebuild_interest_cache`][rebuild] is called after the value of the max
    |                             ^
@@ -268,7 +268,7 @@ LL | /// [`rebuild_interest_cache\`][rebuild] is called after the value of the m
    |                             +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -287,7 +287,7 @@ LL | |     /// level changes.
            to this: `None`. Otherwise, it will return `Some(Dispatch)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -304,7 +304,7 @@ LL | |     /// level changes.
            to this: or `None\` if it isn't.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -323,7 +323,7 @@ LL | |     /// level changes.
            to this: `on_event\` should be called.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:322:5
+  --> $DIR/unescaped_backticks.rs:323:5
    |
 LL | /     /// The Subscriber` may be accessed by calling [`WeakDispatch::upgrade`],
 LL | |
@@ -342,7 +342,7 @@ LL | |     /// level changes.
            to this: [`rebuild_interest_cache\`][rebuild] is called after the value of the max
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:348:56
+  --> $DIR/unescaped_backticks.rs:349:56
    |
 LL |     /// instead and use [`CloneCounterObserver::counter`] to increment.
    |                                                        ^
@@ -354,7 +354,7 @@ LL |     /// instead and use [`CloneCounterObserver::counter\`] to increment.
    |                                                        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:11:5
+  --> $DIR/unescaped_backticks.rs:12:5
    |
 LL | /// `
    |     ^
@@ -366,7 +366,7 @@ LL | /// \`
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:18:7
+  --> $DIR/unescaped_backticks.rs:19:7
    |
 LL | /// \`
    |       ^
@@ -381,7 +381,7 @@ LL | /// \\`
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:25:6
+  --> $DIR/unescaped_backticks.rs:26:6
    |
 LL | /// [`link1]
    |      ^
@@ -396,7 +396,7 @@ LL | /// [\`link1]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:29:11
+  --> $DIR/unescaped_backticks.rs:30:11
    |
 LL | /// [link2`]
    |           ^
@@ -411,7 +411,7 @@ LL | /// [link2\`]
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:33:6
+  --> $DIR/unescaped_backticks.rs:34:6
    |
 LL | /// [`link_long](link_long)
    |      ^
@@ -426,7 +426,7 @@ LL | /// [\`link_long](link_long)
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:37:6
+  --> $DIR/unescaped_backticks.rs:38:6
    |
 LL | /// [`broken-link]
    |      ^
@@ -441,7 +441,7 @@ LL | /// [\`broken-link]
    |      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:44:8
+  --> $DIR/unescaped_backticks.rs:45:8
    |
 LL | /// <x:`>
    |        ^
@@ -456,7 +456,7 @@ LL | /// <x:\`>
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:54:6
+  --> $DIR/unescaped_backticks.rs:55:6
    |
 LL | /// 🦀`🦀
    |       ^
@@ -475,7 +475,7 @@ LL | /// 🦀\`🦀
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:58:5
+  --> $DIR/unescaped_backticks.rs:59:5
    |
 LL | /// `foo(
    |     ^
@@ -490,7 +490,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:64:14
+  --> $DIR/unescaped_backticks.rs:65:14
    |
 LL | /// `foo `bar`
    |              ^
@@ -505,7 +505,7 @@ LL | /// `foo `bar\`
    |              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:70:5
+  --> $DIR/unescaped_backticks.rs:71:5
    |
 LL | /// `foo(
    |     ^
@@ -520,7 +520,7 @@ LL | /// \`foo(
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:75:83
+  --> $DIR/unescaped_backticks.rs:76:83
    |
 LL | /// Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`.
    |                                                                                   ^
@@ -535,7 +535,7 @@ LL | /// Addition is commutative, which means that add(a, b)` is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:79:51
+  --> $DIR/unescaped_backticks.rs:80:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, b)`)!
    |                                                   ^
@@ -550,7 +550,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, b)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:83:83
+  --> $DIR/unescaped_backticks.rs:84:83
    |
 LL | /// Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`.
    |                                                                                   ^
@@ -565,7 +565,7 @@ LL | /// Addition is commutative, which means that `add(a, b) is the same as `ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:87:51
+  --> $DIR/unescaped_backticks.rs:88:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -580,7 +580,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:91:83
+  --> $DIR/unescaped_backticks.rs:92:83
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`.
    |                                                                                   ^
@@ -595,7 +595,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as ad
    |                                                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:95:50
+  --> $DIR/unescaped_backticks.rs:96:50
    |
 LL | /// or even to add a number `n` to 42 (add(42, n)`)!
    |                                                  ^
@@ -610,7 +610,7 @@ LL | /// or even to add a number `n` to 42 (add(42, n)\`)!
    |                                                  +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:99:74
+  --> $DIR/unescaped_backticks.rs:100:74
    |
 LL | /// Addition is commutative, which means that `add(a, b)` is the same as `add(b, a).
    |                                                                          ^
@@ -625,7 +625,7 @@ LL | /// Addition is commutative, which means that `add(a, b)` is the same as \`
    |                                                                          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:103:51
+  --> $DIR/unescaped_backticks.rs:104:51
    |
 LL | /// or even to add a number `n` to 42 (`add(42, n)`)!
    |                                                   ^
@@ -640,7 +640,7 @@ LL | /// or even to add a number `n` to 42 (`add(42, n)\`)!
    |                                                   +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:107:1
+  --> $DIR/unescaped_backticks.rs:108:1
    |
 LL | #[doc = "`"]
    | ^^^^^^^^^^^^
@@ -651,7 +651,7 @@ LL | #[doc = "`"]
            to this: \`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:114:1
+  --> $DIR/unescaped_backticks.rs:115:1
    |
 LL | #[doc = concat!("\\", "`")]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -664,7 +664,7 @@ LL | #[doc = concat!("\\", "`")]
            to this: \\`
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:118:1
+  --> $DIR/unescaped_backticks.rs:119:1
    |
 LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -677,7 +677,7 @@ LL | #[doc = "Addition is commutative, which means that add(a, b)` is the same a
            to this: Addition is commutative, which means that add(a, b)` is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:122:1
+  --> $DIR/unescaped_backticks.rs:123:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same as `add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -690,7 +690,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b) is the same a
            to this: Addition is commutative, which means that `add(a, b) is the same as `add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:126:1
+  --> $DIR/unescaped_backticks.rs:127:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as add(b, a)`."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -703,7 +703,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as add(b, a)\`.
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:130:1
+  --> $DIR/unescaped_backticks.rs:131:1
    |
 LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same as `add(b, a)."]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -716,7 +716,7 @@ LL | #[doc = "Addition is commutative, which means that `add(a, b)` is the same
            to this: Addition is commutative, which means that `add(a, b)` is the same as \`add(b, a).
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:135:5
+  --> $DIR/unescaped_backticks.rs:136:5
    |
 LL | /// `foo
    |     ^
@@ -731,7 +731,7 @@ LL | /// \`foo
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:139:7
+  --> $DIR/unescaped_backticks.rs:140:7
    |
 LL | /// # `(heading
    |       ^
@@ -746,7 +746,7 @@ LL | /// # \`(heading
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:141:17
+  --> $DIR/unescaped_backticks.rs:142:17
    |
 LL | /// ## heading2)`
    |                 ^
@@ -761,7 +761,7 @@ LL | /// ## heading2)\`
    |                 +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:144:11
+  --> $DIR/unescaped_backticks.rs:145:11
    |
 LL | /// multi `(
    |           ^
@@ -776,7 +776,7 @@ LL | /// multi \`(
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:150:10
+  --> $DIR/unescaped_backticks.rs:151:10
    |
 LL | /// para)`(graph
    |          ^
@@ -795,7 +795,7 @@ LL | /// para)\`(graph
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:153:10
+  --> $DIR/unescaped_backticks.rs:154:10
    |
 LL | /// para)`(graph2
    |          ^
@@ -814,7 +814,7 @@ LL | /// para)\`(graph2
    |          +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:156:12
+  --> $DIR/unescaped_backticks.rs:157:12
    |
 LL | /// 1. foo)`
    |            ^
@@ -829,7 +829,7 @@ LL | /// 1. foo)\`
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:158:8
+  --> $DIR/unescaped_backticks.rs:159:8
    |
 LL | /// 2. `(bar
    |        ^
@@ -844,7 +844,7 @@ LL | /// 2. \`(bar
    |        +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:160:11
+  --> $DIR/unescaped_backticks.rs:161:11
    |
 LL | /// * baz)`
    |           ^
@@ -859,7 +859,7 @@ LL | /// * baz)\`
    |           +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:162:7
+  --> $DIR/unescaped_backticks.rs:163:7
    |
 LL | /// * `(quux
    |       ^
@@ -874,7 +874,7 @@ LL | /// * \`(quux
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:165:5
+  --> $DIR/unescaped_backticks.rs:166:5
    |
 LL | /// `#![this_is_actually_an_image(and(not), an = "attribute")]
    |     ^
@@ -889,7 +889,7 @@ LL | /// \`#![this_is_actually_an_image(and(not), an = "attribute")]
    |     +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:168:62
+  --> $DIR/unescaped_backticks.rs:169:62
    |
 LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]`
    |                                                              ^
@@ -904,7 +904,7 @@ LL | /// #![this_is_actually_an_image(and(not), an = "attribute")]\`
    |                                                              +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:7
+  --> $DIR/unescaped_backticks.rs:174:7
    |
 LL | /// | `table( | )head` |
    |       ^
@@ -919,7 +919,7 @@ LL | /// | \`table( | )head` |
    |       +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:173:22
+  --> $DIR/unescaped_backticks.rs:174:22
    |
 LL | /// | `table( | )head` |
    |                      ^
@@ -934,7 +934,7 @@ LL | /// | `table( | )head\` |
    |                      +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:12
+  --> $DIR/unescaped_backticks.rs:178:12
    |
 LL | /// | table`( | )`body |
    |            ^
@@ -949,7 +949,7 @@ LL | /// | table\`( | )`body |
    |            +
 
 error: unescaped backtick
-  --> $DIR/unescaped_backticks.rs:177:18
+  --> $DIR/unescaped_backticks.rs:178:18
    |
 LL | /// | table`( | )`body |
    |                  ^
diff --git a/tests/rustdoc/description.rs b/tests/rustdoc/description.rs
index 43cd59ebd09..aabbb4c4c8f 100644
--- a/tests/rustdoc/description.rs
+++ b/tests/rustdoc/description.rs
@@ -1,4 +1,5 @@
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 //! # Description test crate
 //!
 //! This is the contents of the test crate docstring.
diff --git a/tests/rustdoc/intra-doc/basic.rs b/tests/rustdoc/intra-doc/basic.rs
index 96e21137b2d..c88a7887f11 100644
--- a/tests/rustdoc/intra-doc/basic.rs
+++ b/tests/rustdoc/intra-doc/basic.rs
@@ -1,3 +1,5 @@
+#![allow(rustdoc::redundant_explicit_links)]
+
 // @has basic/index.html
 // @has - '//a/@href' 'struct.ThisType.html'
 // @has - '//a/@title' 'struct basic::ThisType'
diff --git a/tests/rustdoc/intra-doc/generic-params.rs b/tests/rustdoc/intra-doc/generic-params.rs
index fbc9fc6a9bc..359f775f97f 100644
--- a/tests/rustdoc/intra-doc/generic-params.rs
+++ b/tests/rustdoc/intra-doc/generic-params.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 
 #![crate_name = "foo"]
+#![allow(rustdoc::redundant_explicit_links)]
 
 //! Here's a link to [`Vec<T>`] and one to [`Box<Vec<Option<T>>>`].
 //! Here's a link to [`Iterator<Box<T>>::Item`].
diff --git a/tests/rustdoc/intra-doc/issue-108459.rs b/tests/rustdoc/intra-doc/issue-108459.rs
index eb1c7a05e54..b8cd478b4df 100644
--- a/tests/rustdoc/intra-doc/issue-108459.rs
+++ b/tests/rustdoc/intra-doc/issue-108459.rs
@@ -1,4 +1,5 @@
 #![deny(rustdoc::broken_intra_doc_links)]
+#![allow(rustdoc::redundant_explicit_links)]
 
 pub struct S;
 pub mod char {}
diff --git a/tests/ui/abi/relocation_model_pic.rs b/tests/ui/abi/relocation_model_pic.rs
new file mode 100644
index 00000000000..0cfc44cd09d
--- /dev/null
+++ b/tests/ui/abi/relocation_model_pic.rs
@@ -0,0 +1,9 @@
+// run-pass
+// compile-flags: -C relocation-model=pic
+// ignore-emscripten no pic
+// ignore-wasm
+
+#![feature(cfg_relocation_model)]
+
+#[cfg(relocation_model = "pic")]
+fn main() {}
diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
index 40896c32e11..1e0b77b0d3b 100644
--- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
+++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.rs
@@ -5,6 +5,8 @@ trait Trait {
 impl Trait for () {
     const ASSOC: &dyn Fn(_) = 1i32;
     //~^ ERROR the placeholder `_` is not allowed within types on item signatures for associated constants
+    //~| WARN `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
 }
 
 fn main() {}
diff --git a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
index 993a08faba9..f8c02420f96 100644
--- a/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
+++ b/tests/ui/associated-consts/infer-placeholder-in-non-suggestable-pos.stderr
@@ -1,9 +1,23 @@
+warning: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:18
+   |
+LL |     const ASSOC: &dyn Fn(_) = 1i32;
+   |                  ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+   = note: `#[warn(elided_lifetimes_in_associated_constant)]` on by default
+help: use the `'static` lifetime
+   |
+LL |     const ASSOC: &'static dyn Fn(_) = 1i32;
+   |                   +++++++
+
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
   --> $DIR/infer-placeholder-in-non-suggestable-pos.rs:6:26
    |
 LL |     const ASSOC: &dyn Fn(_) = 1i32;
    |                          ^ not allowed in type signatures
 
-error: aborting due to previous error
+error: aborting due to previous error; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs
new file mode 100644
index 00000000000..3853bc8594f
--- /dev/null
+++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.rs
@@ -0,0 +1,12 @@
+#![allow(bare_trait_objects)]
+#![feature(associated_type_bounds)]
+trait Item {
+    type Core;
+}
+pub struct Flatten<I> {
+    inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
+    //~^ ERROR E0191
+    //~| ERROR E0223
+}
+
+fn main() {}
diff --git a/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
new file mode 100644
index 00000000000..61299550e98
--- /dev/null
+++ b/tests/ui/associated-type-bounds/overlaping-bound-suggestion.stderr
@@ -0,0 +1,24 @@
+error[E0191]: the value of the associated types `IntoIter` (from trait `IntoIterator`), `IntoIter` (from trait `IntoIterator`), `Item` (from trait `IntoIterator`), `Item` (from trait `IntoIterator`) must be specified
+  --> $DIR/overlaping-bound-suggestion.rs:7:13
+   |
+LL |     inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |             |                  |
+   |             |                  associated types `Item`, `IntoIter` must be specified
+   |             associated types `Item`, `IntoIter` must be specified
+
+error[E0223]: ambiguous associated type
+  --> $DIR/overlaping-bound-suggestion.rs:7:13
+   |
+LL |     inner: <IntoIterator<Item: IntoIterator<Item: >>::IntoIterator as Item>::Core,
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+help: if there were a trait named `Example` with associated type `IntoIterator` implemented for `(dyn IntoIterator + 'static)`, you could use the fully-qualified path
+   |
+LL |     inner: <<(dyn IntoIterator + 'static) as Example>::IntoIterator as Item>::Core,
+   |             ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0191, E0223.
+For more information about an error, try `rustc --explain E0191`.
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed b/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
deleted file mode 100644
index ec4165cc71e..00000000000
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.fixed
+++ /dev/null
@@ -1,13 +0,0 @@
-// run-rustfix
-
-use std::fmt::Debug;
-
-pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
-where
-    I::Item: Eq + Debug,
-{
-    debug_assert_eq!(iter.next().as_ref(), Some(value));
-    //~^ ERROR mismatched types
-}
-
-fn main() {}
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
index 0b4df08783d..0848b4c559b 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.rs
@@ -1,5 +1,3 @@
-// run-rustfix
-
 use std::fmt::Debug;
 
 pub fn foo<I: Iterator>(mut iter: I, value: &I::Item)
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
index 65d18761b18..3ecac9c83e5 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
@@ -1,15 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/dont-suggest-cyclic-constraint.rs:9:35
+  --> $DIR/dont-suggest-cyclic-constraint.rs:7:35
    |
 LL |     debug_assert_eq!(iter.next(), Some(value));
    |                                   ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
    |
    = note: expected enum `Option<<I as Iterator>::Item>`
               found enum `Option<&<I as Iterator>::Item>`
-help: use `Option::as_ref` to convert `Option<<I as Iterator>::Item>` to `Option<&<I as Iterator>::Item>`
-   |
-LL |     debug_assert_eq!(iter.next().as_ref(), Some(value));
-   |                                 +++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/async-await/deep-futures-are-freeze.rs b/tests/ui/async-await/deep-futures-are-freeze.rs
new file mode 100644
index 00000000000..dd676d5e18c
--- /dev/null
+++ b/tests/ui/async-await/deep-futures-are-freeze.rs
@@ -0,0 +1,179 @@
+// build-pass
+// compile-flags: -Copt-level=s -Clto=fat
+// no-prefer-dynamic
+// edition: 2021
+
+#![recursion_limit = "256"]
+
+fn main() {
+    spawn(move || main0())
+}
+
+fn spawn<F>(future: impl FnOnce() -> F) {
+    future();
+}
+
+async fn main0() {
+    main1().await;
+    main2().await;
+}
+async fn main1() {
+    main2().await;
+    main3().await;
+}
+async fn main2() {
+    main3().await;
+    main4().await;
+}
+async fn main3() {
+    main4().await;
+    main5().await;
+}
+async fn main4() {
+    main5().await;
+    main6().await;
+}
+async fn main5() {
+    main6().await;
+    main7().await;
+}
+async fn main6() {
+    main7().await;
+    main8().await;
+}
+async fn main7() {
+    main8().await;
+    main9().await;
+}
+async fn main8() {
+    main9().await;
+    main10().await;
+}
+async fn main9() {
+    main10().await;
+    main11().await;
+}
+async fn main10() {
+    main11().await;
+    main12().await;
+}
+async fn main11() {
+    main12().await;
+    main13().await;
+}
+async fn main12() {
+    main13().await;
+    main14().await;
+}
+async fn main13() {
+    main14().await;
+    main15().await;
+}
+async fn main14() {
+    main15().await;
+    main16().await;
+}
+async fn main15() {
+    main16().await;
+    main17().await;
+}
+async fn main16() {
+    main17().await;
+    main18().await;
+}
+async fn main17() {
+    main18().await;
+    main19().await;
+}
+async fn main18() {
+    main19().await;
+    main20().await;
+}
+async fn main19() {
+    main20().await;
+    main21().await;
+}
+async fn main20() {
+    main21().await;
+    main22().await;
+}
+async fn main21() {
+    main22().await;
+    main23().await;
+}
+async fn main22() {
+    main23().await;
+    main24().await;
+}
+async fn main23() {
+    main24().await;
+    main25().await;
+}
+async fn main24() {
+    main25().await;
+    main26().await;
+}
+async fn main25() {
+    main26().await;
+    main27().await;
+}
+async fn main26() {
+    main27().await;
+    main28().await;
+}
+async fn main27() {
+    main28().await;
+    main29().await;
+}
+async fn main28() {
+    main29().await;
+    main30().await;
+}
+async fn main29() {
+    main30().await;
+    main31().await;
+}
+async fn main30() {
+    main31().await;
+    main32().await;
+}
+async fn main31() {
+    main32().await;
+    main33().await;
+}
+async fn main32() {
+    main33().await;
+    main34().await;
+}
+async fn main33() {
+    main34().await;
+    main35().await;
+}
+async fn main34() {
+    main35().await;
+    main36().await;
+}
+async fn main35() {
+    main36().await;
+    main37().await;
+}
+async fn main36() {
+    main37().await;
+    main38().await;
+}
+async fn main37() {
+    main38().await;
+    main39().await;
+}
+async fn main38() {
+    main39().await;
+    main40().await;
+}
+async fn main39() {
+    main40().await;
+}
+async fn main40() {
+    boom(&mut ()).await;
+}
+
+async fn boom(f: &mut ()) {}
diff --git a/tests/ui/async-await/normalize-output-in-signature-deduction.rs b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
new file mode 100644
index 00000000000..960065a83a4
--- /dev/null
+++ b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
@@ -0,0 +1,19 @@
+// edition:2021
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
+// check-pass
+
+#![feature(type_alias_impl_trait)]
+
+struct Foo;
+
+impl Trait for Foo {}
+pub trait Trait {}
+
+pub type TAIT<T> = impl Trait;
+
+async fn foo<T>() -> TAIT<T> {
+    Foo
+}
+
+fn main() {}
diff --git a/tests/ui/consts/assert-type-intrinsics.stderr b/tests/ui/consts/assert-type-intrinsics.stderr
index 70aec91e226..3c03b03deee 100644
--- a/tests/ui/consts/assert-type-intrinsics.stderr
+++ b/tests/ui/consts/assert-type-intrinsics.stderr
@@ -2,19 +2,19 @@ error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:12:9
    |
 LL |         MaybeUninit::<!>::uninit().assume_init();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to instantiate uninhabited type `!`
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to instantiate uninhabited type `!`', $DIR/assert-type-intrinsics.rs:12:36
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:16:9
    |
 LL |         intrinsics::assert_mem_uninitialized_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to leave type `&i32` uninitialized, which is invalid
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to leave type `&i32` uninitialized, which is invalid', $DIR/assert-type-intrinsics.rs:16:9
 
 error[E0080]: evaluation of constant value failed
   --> $DIR/assert-type-intrinsics.rs:20:9
    |
 LL |         intrinsics::assert_zero_valid::<&'static i32>();
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ aborted execution: attempted to zero-initialize type `&i32`, which is invalid
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the evaluated program panicked at 'aborted execution: attempted to zero-initialize type `&i32`, which is invalid', $DIR/assert-type-intrinsics.rs:20:9
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/consts/assoc-const-elided-lifetime.rs b/tests/ui/consts/assoc-const-elided-lifetime.rs
new file mode 100644
index 00000000000..10cd33a8fed
--- /dev/null
+++ b/tests/ui/consts/assoc-const-elided-lifetime.rs
@@ -0,0 +1,19 @@
+#![deny(elided_lifetimes_in_associated_constant)]
+
+use std::marker::PhantomData;
+
+struct Foo<'a> {
+    x: PhantomData<&'a ()>,
+}
+
+impl<'a> Foo<'a> {
+    const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
+    //~^ ERROR `'_` cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+
+    const BAR: &() = &();
+    //~^ ERROR `&` without an explicit lifetime name cannot be used here
+    //~| WARN this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+}
+
+fn main() {}
diff --git a/tests/ui/consts/assoc-const-elided-lifetime.stderr b/tests/ui/consts/assoc-const-elided-lifetime.stderr
new file mode 100644
index 00000000000..a1eeaff4ba8
--- /dev/null
+++ b/tests/ui/consts/assoc-const-elided-lifetime.stderr
@@ -0,0 +1,33 @@
+error: `'_` cannot be used here
+  --> $DIR/assoc-const-elided-lifetime.rs:10:20
+   |
+LL |     const FOO: Foo<'_> = Foo { x: PhantomData::<&()> };
+   |                    ^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+note: the lint level is defined here
+  --> $DIR/assoc-const-elided-lifetime.rs:1:9
+   |
+LL | #![deny(elided_lifetimes_in_associated_constant)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use the `'static` lifetime
+   |
+LL |     const FOO: Foo<'static> = Foo { x: PhantomData::<&()> };
+   |                    ~~~~~~~
+
+error: `&` without an explicit lifetime name cannot be used here
+  --> $DIR/assoc-const-elided-lifetime.rs:14:16
+   |
+LL |     const BAR: &() = &();
+   |                ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #115010 <https://github.com/rust-lang/rust/issues/115010>
+help: use the `'static` lifetime
+   |
+LL |     const BAR: &'static () = &();
+   |                 +++++++
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
index 85e88287094..659b5465522 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.fixed
@@ -6,4 +6,6 @@ fn main() {
     let _foo = str::trim_start("   aoeu"); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
 
     let _bar = "   aoeu".trim_start(); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+
+    let _baz = ["a", "b"].join(" "); //~ ERROR use of deprecated method `std::slice::<impl [T]>::connect`: renamed to join [deprecated]
 }
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
index 246de2f5e4b..cfc6c4450b4 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.rs
@@ -6,4 +6,6 @@ fn main() {
     let _foo = str::trim_left("   aoeu"); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
 
     let _bar = "   aoeu".trim_left(); //~ ERROR use of deprecated method `core::str::<impl str>::trim_left`: superseded by `trim_start` [deprecated]
+
+    let _baz = ["a", "b"].connect(" "); //~ ERROR use of deprecated method `std::slice::<impl [T]>::connect`: renamed to join [deprecated]
 }
diff --git a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
index 3b518d1802b..d1f5ea3602a 100644
--- a/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
+++ b/tests/ui/deprecation/issue-84637-deprecated-associated-function.stderr
@@ -25,5 +25,16 @@ help: replace the use of the deprecated method
 LL |     let _bar = "   aoeu".trim_start();
    |                          ~~~~~~~~~~
 
-error: aborting due to 2 previous errors
+error: use of deprecated method `std::slice::<impl [T]>::connect`: renamed to join
+  --> $DIR/issue-84637-deprecated-associated-function.rs:10:27
+   |
+LL |     let _baz = ["a", "b"].connect(" ");
+   |                           ^^^^^^^
+   |
+help: replace the use of the deprecated method
+   |
+LL |     let _baz = ["a", "b"].join(" ");
+   |                           ~~~~
+
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
new file mode 100644
index 00000000000..7529014ece2
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.rs
@@ -0,0 +1,4 @@
+#[cfg(relocation_model = "pic")] //~ ERROR
+fn _foo() {}
+
+fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
new file mode 100644
index 00000000000..592768a4203
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-cfg-relocation-model.stderr
@@ -0,0 +1,12 @@
+error[E0658]: `cfg(relocation_model)` is experimental and subject to change
+  --> $DIR/feature-gate-cfg-relocation-model.rs:1:7
+   |
+LL | #[cfg(relocation_model = "pic")]
+   |       ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #114929 <https://github.com/rust-lang/rust/issues/114929> for more information
+   = help: add `#![feature(cfg_relocation_model)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs b/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs
new file mode 100644
index 00000000000..e0df96b0de8
--- /dev/null
+++ b/tests/ui/implied-bounds/implied_bounds_entailment_alias_var.rs
@@ -0,0 +1,32 @@
+// check-pass
+
+trait Data {
+    type Elem;
+}
+
+impl<F, S: Data<Elem = F>> Data for ArrayBase<S> {
+    type Elem = F;
+}
+
+struct DatasetIter<'a, R: Data> {
+    data: &'a R::Elem,
+}
+
+pub struct ArrayBase<S> {
+    data: S,
+}
+
+trait Trait {
+    type Item;
+    fn next() -> Option<Self::Item>;
+}
+
+impl<'a, D: Data> Trait for DatasetIter<'a, ArrayBase<D>> {
+    type Item = ();
+
+    fn next() -> Option<Self::Item> {
+        None
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/inference/str-as-char.fixed b/tests/ui/inference/str-as-char.fixed
index 6aea809cbdb..911b067c4d1 100644
--- a/tests/ui/inference/str-as-char.fixed
+++ b/tests/ui/inference/str-as-char.fixed
@@ -7,4 +7,5 @@ fn main() {
     let _: &str = "a";   //~ ERROR mismatched types
     let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
     let _: &str = "\"\"\""; //~ ERROR character literal may only contain one codepoint
+    let _: &str = "\"\"\\\"\\\"\\\\\""; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/tests/ui/inference/str-as-char.rs b/tests/ui/inference/str-as-char.rs
index eaa8d788c34..832bc871a9e 100644
--- a/tests/ui/inference/str-as-char.rs
+++ b/tests/ui/inference/str-as-char.rs
@@ -7,4 +7,5 @@ fn main() {
     let _: &str = 'a';   //~ ERROR mismatched types
     let _: &str = '"""'; //~ ERROR character literal may only contain one codepoint
     let _: &str = '\"\"\"'; //~ ERROR character literal may only contain one codepoint
+    let _: &str = '"\"\\"\\\"\\\\"'; //~ ERROR character literal may only contain one codepoint
 }
diff --git a/tests/ui/inference/str-as-char.stderr b/tests/ui/inference/str-as-char.stderr
index 2c84dac8e0c..216f4cda698 100644
--- a/tests/ui/inference/str-as-char.stderr
+++ b/tests/ui/inference/str-as-char.stderr
@@ -20,6 +20,17 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let _: &str = "\"\"\"";
    |                   ~~~~~~~~
 
+error: character literal may only contain one codepoint
+  --> $DIR/str-as-char.rs:10:19
+   |
+LL |     let _: &str = '"\"\"\\"\\"';
+   |                   ^^^^^^^^^^^^^^^^^
+   |
+help: if you meant to write a `str` literal, use double quotes
+   |
+LL |     let _: &str = "\"\"\\"\\"\\\"";
+   |                   ~~~~~~~~~~~~~~~~~~~~
+
 error[E0308]: mismatched types
   --> $DIR/str-as-char.rs:7:19
    |
@@ -33,6 +44,6 @@ help: if you meant to write a `str` literal, use double quotes
 LL |     let _: &str = "a";
    |                   ~~~
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inline-const/required-const.rs b/tests/ui/inline-const/required-const.rs
new file mode 100644
index 00000000000..0483410662b
--- /dev/null
+++ b/tests/ui/inline-const/required-const.rs
@@ -0,0 +1,13 @@
+// build-fail
+// compile-flags: -Zmir-opt-level=3
+#![feature(inline_const)]
+
+fn foo<T>() {
+    if false {
+        const { panic!() } //~ ERROR E0080
+    }
+}
+
+fn main() {
+    foo::<i32>();
+}
diff --git a/tests/ui/inline-const/required-const.stderr b/tests/ui/inline-const/required-const.stderr
new file mode 100644
index 00000000000..d6948e7acc0
--- /dev/null
+++ b/tests/ui/inline-const/required-const.stderr
@@ -0,0 +1,11 @@
+error[E0080]: evaluation of `foo::<i32>::{constant#0}` failed
+  --> $DIR/required-const.rs:7:17
+   |
+LL |         const { panic!() }
+   |                 ^^^^^^^^ the evaluated program panicked at 'explicit panic', $DIR/required-const.rs:7:17
+   |
+   = note: this error originates in the macro `$crate::panic::panic_2015` which comes from the expansion of the macro `panic` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/macros/macro-interpolation.rs b/tests/ui/macros/macro-interpolation.rs
index 35003a79ad7..48c1f19e777 100644
--- a/tests/ui/macros/macro-interpolation.rs
+++ b/tests/ui/macros/macro-interpolation.rs
@@ -1,5 +1,3 @@
-// run-pass
-
 macro_rules! overly_complicated {
     ($fnname:ident, $arg:ident, $ty:ty, $body:block, $val:expr, $pat:pat, $res:path) =>
     ({
@@ -21,12 +19,14 @@ macro_rules! qpath {
 
     (ty, <$type:ty as $trait:ty>::$name:ident) => {
         <$type as $trait>::$name
+        //~^ ERROR expected identifier, found `!`
     };
 }
 
 pub fn main() {
     let _: qpath!(path, <str as ToOwned>::Owned);
     let _: qpath!(ty, <str as ToOwned>::Owned);
+    let _: qpath!(ty, <str as !>::Owned);
 
     assert!(overly_complicated!(f, x, Option<usize>, { return Some(x); },
                                Some(8), Some(y), y) == 8)
diff --git a/tests/ui/macros/macro-interpolation.stderr b/tests/ui/macros/macro-interpolation.stderr
new file mode 100644
index 00000000000..7ef1fcbbce3
--- /dev/null
+++ b/tests/ui/macros/macro-interpolation.stderr
@@ -0,0 +1,16 @@
+error: expected identifier, found `!`
+  --> $DIR/macro-interpolation.rs:21:19
+   |
+LL |         <$type as $trait>::$name
+   |                   ^^^^^^ expected identifier
+...
+LL |     let _: qpath!(ty, <str as !>::Owned);
+   |            -----------------------------
+   |            |
+   |            this macro call doesn't expand to a type
+   |            in this macro invocation
+   |
+   = note: this error originates in the macro `qpath` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to previous error
+
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
new file mode 100644
index 00000000000..9cc572c23a1
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.rs
@@ -0,0 +1,14 @@
+#![feature(macro_metavar_expr)]
+
+macro_rules! foo {
+    ( $( $($t:ident),* );* ) => { ${count(t,)} }
+    //~^ ERROR `count` followed by a comma must have an associated
+    //~| ERROR expected expression, found `$`
+}
+
+fn test() {
+    foo!(a, a; b, b);
+}
+
+fn main() {
+}
diff --git a/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
new file mode 100644
index 00000000000..e9317a5c347
--- /dev/null
+++ b/tests/ui/macros/rfc-3086-metavar-expr/issue-111904.stderr
@@ -0,0 +1,19 @@
+error: `count` followed by a comma must have an associated index indicating its depth
+  --> $DIR/issue-111904.rs:4:37
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                     ^^^^^
+
+error: expected expression, found `$`
+  --> $DIR/issue-111904.rs:4:35
+   |
+LL |     ( $( $($t:ident),* );* ) => { ${count(t,)} }
+   |                                   ^ expected expression
+...
+LL |     foo!(a, a; b, b);
+   |     ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `foo` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/mir/debug-ref-undef.rs b/tests/ui/mir/debug-ref-undef.rs
new file mode 100644
index 00000000000..37fd22a9dd2
--- /dev/null
+++ b/tests/ui/mir/debug-ref-undef.rs
@@ -0,0 +1,57 @@
+// run-pass
+// compile-flags: -g -O -Zmir-opt-level=0 -Zinline-mir=y -Zmir-enable-passes=+ReferencePropagation
+
+#![allow(dead_code)]
+
+use std::marker::PhantomData;
+
+struct RawTable<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T> RawTable<T> {
+    fn iter(&self) -> RawIter<T> {
+        RawIter { marker: PhantomData }
+    }
+}
+
+struct RawIter<T> {
+    marker: PhantomData<T>,
+}
+
+impl<T> Iterator for RawIter<T> {
+    type Item = ();
+    fn next(&mut self) -> Option<()> {
+        None
+    }
+}
+
+struct HashMap<T> {
+    table: RawTable<T>,
+}
+
+struct Iter<T> {
+    inner: RawIter<T>, // Removing this breaks the reproducer
+}
+
+impl<T> IntoIterator for &HashMap<T> {
+    type Item = T;
+    type IntoIter = Iter<T>;
+    fn into_iter(self) -> Iter<T> {
+        Iter { inner: self.table.iter() }
+    }
+}
+
+impl<T> Iterator for Iter<T> {
+    type Item = T;
+    fn next(&mut self) -> Option<T> {
+        None
+    }
+}
+
+pub fn main() {
+    let maybe_hash_set: Option<HashMap<()>> = None;
+    for _ in maybe_hash_set.as_ref().unwrap_or(&HashMap { table: RawTable { marker: PhantomData } })
+    {
+    }
+}
diff --git a/tests/ui/or-patterns/missing-bindings.stderr b/tests/ui/or-patterns/missing-bindings.stderr
index 8fafa275b5c..4457b7893d5 100644
--- a/tests/ui/or-patterns/missing-bindings.stderr
+++ b/tests/ui/or-patterns/missing-bindings.stderr
@@ -79,6 +79,14 @@ LL |     let (A(A(..) | B(a), _) | B(A(a, _) | B(a))) = Y;
    |            |
    |            pattern doesn't bind `a`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:45:12
+   |
+LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
+   |            ^^^^^^^     - variable not in all patterns
+   |            |
+   |            pattern doesn't bind `c`
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:22
    |
@@ -96,12 +104,12 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 variable not in all patterns
 
 error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:12
+  --> $DIR/missing-bindings.rs:45:33
    |
 LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |            ^^^^^^^     - variable not in all patterns
-   |            |
-   |            pattern doesn't bind `c`
+   |                        -        ^^^^ pattern doesn't bind `c`
+   |                        |
+   |                        variable not in all patterns
 
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/missing-bindings.rs:45:33
@@ -135,14 +143,6 @@ LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
    |                 |
    |                 variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:45:33
-   |
-LL |     let (A(A(a, b) | B(c), d) | B(e)) = Y;
-   |                        -        ^^^^ pattern doesn't bind `c`
-   |                        |
-   |                        variable not in all patterns
-
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:61:29
    |
@@ -185,6 +185,28 @@ LL |                     B(b),
 LL |                 B(_)
    |                 ^^^^ pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/missing-bindings.rs:57:13
+   |
+LL | /             V1(
+LL | |
+LL | |
+LL | |                 A(
+...  |
+LL | |                 B(Ok(a) | Err(a))
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL | /             V2(
+LL | |                 A(
+LL | |                     A(_, a) |
+LL | |                     B(b),
+...  |
+LL | |
+LL | |             ) |
+   | |_____________^ pattern doesn't bind `c`
+LL |               V3(c),
+   |                  - variable not in all patterns
+
 error[E0408]: variable `a` is not bound in all patterns
   --> $DIR/missing-bindings.rs:76:13
    |
@@ -215,28 +237,6 @@ LL |                       B(b),
 LL |               V3(c),
    |               ^^^^^ pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/missing-bindings.rs:57:13
-   |
-LL | /             V1(
-LL | |
-LL | |
-LL | |                 A(
-...  |
-LL | |                 B(Ok(a) | Err(a))
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL | /             V2(
-LL | |                 A(
-LL | |                     A(_, a) |
-LL | |                     B(b),
-...  |
-LL | |
-LL | |             ) |
-   | |_____________^ pattern doesn't bind `c`
-LL |               V3(c),
-   |                  - variable not in all patterns
-
 error: aborting due to 26 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/parser/trait-object-delimiters.rs b/tests/ui/parser/trait-object-delimiters.rs
index c41cda18743..e9b13defe03 100644
--- a/tests/ui/parser/trait-object-delimiters.rs
+++ b/tests/ui/parser/trait-object-delimiters.rs
@@ -3,9 +3,9 @@
 fn foo1(_: &dyn Drop + AsRef<str>) {} //~ ERROR ambiguous `+` in a type
 //~^ ERROR only auto traits can be used as additional traits in a trait object
 
-fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+fn foo2(_: &dyn (Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
 
-fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect braces around trait bounds
+fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {} //~ ERROR incorrect parentheses around trait bounds
 
 fn foo3(_: &dyn {Drop + AsRef<str>}) {} //~ ERROR expected parameter name, found `{`
 //~^ ERROR expected one of `!`, `(`, `)`, `*`, `,`, `?`, `for`, `~`, lifetime, or path, found `{`
diff --git a/tests/ui/parser/trait-object-delimiters.stderr b/tests/ui/parser/trait-object-delimiters.stderr
index ccce3a8053e..51954675093 100644
--- a/tests/ui/parser/trait-object-delimiters.stderr
+++ b/tests/ui/parser/trait-object-delimiters.stderr
@@ -4,28 +4,28 @@ error: ambiguous `+` in a type
 LL | fn foo1(_: &dyn Drop + AsRef<str>) {}
    |             ^^^^^^^^^^^^^^^^^^^^^ help: use parentheses to disambiguate: `(dyn Drop + AsRef<str>)`
 
-error: incorrect braces around trait bounds
+error: incorrect parentheses around trait bounds
   --> $DIR/trait-object-delimiters.rs:6:17
    |
 LL | fn foo2(_: &dyn (Drop + AsRef<str>)) {}
    |                 ^                 ^
    |
-help: remove the parentheses
+help: fix the parentheses
    |
 LL - fn foo2(_: &dyn (Drop + AsRef<str>)) {}
-LL + fn foo2(_: &dyn  Drop + AsRef<str>) {}
+LL + fn foo2(_: &(dyn Drop + AsRef<str>)) {}
    |
 
-error: incorrect braces around trait bounds
+error: incorrect parentheses around trait bounds
   --> $DIR/trait-object-delimiters.rs:8:25
    |
 LL | fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
    |                         ^                 ^
    |
-help: remove the parentheses
+help: fix the parentheses
    |
 LL - fn foo2_no_space(_: &dyn(Drop + AsRef<str>)) {}
-LL + fn foo2_no_space(_: &dyn Drop + AsRef<str>) {}
+LL + fn foo2_no_space(_: &(dyn Drop + AsRef<str>)) {}
    |
 
 error: expected parameter name, found `{`
diff --git a/tests/ui/resolve/resolve-inconsistent-names.stderr b/tests/ui/resolve/resolve-inconsistent-names.stderr
index 023db303dd0..42b7281d7b0 100644
--- a/tests/ui/resolve/resolve-inconsistent-names.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-names.stderr
@@ -14,6 +14,15 @@ LL |        a | b => {}
    |        |
    |        pattern doesn't bind `b`
 
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/resolve-inconsistent-names.rs:19:9
+   |
+LL |         (A, B) | (ref B, c) | (c, A) => ()
+   |         ^^^^^^           -     - variable not in all patterns
+   |         |                |
+   |         |                variable not in all patterns
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `A` is not bound in all patterns
   --> $DIR/resolve-inconsistent-names.rs:19:18
    |
@@ -37,15 +46,6 @@ LL |         (A, B) | (ref B, c) | (c, A) => ()
    |             |         variable not in all patterns
    |             variable not in all patterns
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/resolve-inconsistent-names.rs:19:9
-   |
-LL |         (A, B) | (ref B, c) | (c, A) => ()
-   |         ^^^^^^           -     - variable not in all patterns
-   |         |                |
-   |         |                variable not in all patterns
-   |         pattern doesn't bind `c`
-
 error[E0409]: variable `B` is bound inconsistently across alternatives separated by `|`
   --> $DIR/resolve-inconsistent-names.rs:19:23
    |
diff --git a/tests/ui/span/issue-39698.stderr b/tests/ui/span/issue-39698.stderr
index 25c35fd5479..81211b20a01 100644
--- a/tests/ui/span/issue-39698.stderr
+++ b/tests/ui/span/issue-39698.stderr
@@ -1,3 +1,13 @@
+error[E0408]: variable `c` is not bound in all patterns
+  --> $DIR/issue-39698.rs:10:9
+   |
+LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
+   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
+   |         |             |                   |
+   |         |             |                   variable not in all patterns
+   |         |             pattern doesn't bind `c`
+   |         pattern doesn't bind `c`
+
 error[E0408]: variable `d` is not bound in all patterns
   --> $DIR/issue-39698.rs:10:37
    |
@@ -28,16 +38,6 @@ LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}
    |         |                      variable not in all patterns
    |         pattern doesn't bind `b`
 
-error[E0408]: variable `c` is not bound in all patterns
-  --> $DIR/issue-39698.rs:10:9
-   |
-LL |         T::T1(a, d) | T::T2(d, b) | T::T3(c) | T::T4(a) => { println!("{:?}", a); }
-   |         ^^^^^^^^^^^   ^^^^^^^^^^^         -    ^^^^^^^^ pattern doesn't bind `c`
-   |         |             |                   |
-   |         |             |                   variable not in all patterns
-   |         |             pattern doesn't bind `c`
-   |         pattern doesn't bind `c`
-
 error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0408`.
diff --git a/tests/ui/suggestions/copied-and-cloned.fixed b/tests/ui/suggestions/copied-and-cloned.fixed
index 77159d5075a..4cecf9e26f9 100644
--- a/tests/ui/suggestions/copied-and-cloned.fixed
+++ b/tests/ui/suggestions/copied-and-cloned.fixed
@@ -2,6 +2,16 @@
 
 fn expect<T>(_: T) {}
 
+struct Issue114925 {
+    x: Option<String>,
+}
+
+fn issue_114925(lol: &mut Issue114925, x: Option<&String>) {
+    lol.x = x.clone().cloned();
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+}
+
 fn main() {
     let x = Some(&());
     expect::<Option<()>>(x.copied());
@@ -24,10 +34,10 @@ fn main() {
     let s = String::new();
     let x = Some(s.clone());
     let y = Some(&s);
-    println!("{}", x.as_ref() == y);
+    println!("{}", x == y.cloned());
     //~^ ERROR mismatched types
-    //~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
-
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    //FIXME(#114050) ~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
 
     let mut s = ();
     let x = Some(s);
@@ -42,4 +52,6 @@ fn main() {
     println!("{}", x == y.cloned());
     //~^ ERROR mismatched types
     //~| HELP use `Option::cloned` to clone the value inside the `Option`
+
+    issue_114925(&mut Issue114925 { x: None }, None);
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.rs b/tests/ui/suggestions/copied-and-cloned.rs
index c506494ee14..a79928c50d5 100644
--- a/tests/ui/suggestions/copied-and-cloned.rs
+++ b/tests/ui/suggestions/copied-and-cloned.rs
@@ -2,6 +2,16 @@
 
 fn expect<T>(_: T) {}
 
+struct Issue114925 {
+    x: Option<String>,
+}
+
+fn issue_114925(lol: &mut Issue114925, x: Option<&String>) {
+    lol.x = x.clone();
+    //~^ ERROR mismatched types
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+}
+
 fn main() {
     let x = Some(&());
     expect::<Option<()>>(x);
@@ -26,8 +36,8 @@ fn main() {
     let y = Some(&s);
     println!("{}", x == y);
     //~^ ERROR mismatched types
-    //~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
-
+    //~| HELP use `Option::cloned` to clone the value inside the `Option`
+    //FIXME(#114050) ~| HELP use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
 
     let mut s = ();
     let x = Some(s);
@@ -42,4 +52,6 @@ fn main() {
     println!("{}", x == y);
     //~^ ERROR mismatched types
     //~| HELP use `Option::cloned` to clone the value inside the `Option`
+
+    issue_114925(&mut Issue114925 { x: None }, None);
 }
diff --git a/tests/ui/suggestions/copied-and-cloned.stderr b/tests/ui/suggestions/copied-and-cloned.stderr
index f8712d0a39e..87b0624d48b 100644
--- a/tests/ui/suggestions/copied-and-cloned.stderr
+++ b/tests/ui/suggestions/copied-and-cloned.stderr
@@ -1,5 +1,20 @@
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:7:26
+  --> $DIR/copied-and-cloned.rs:10:13
+   |
+LL |     lol.x = x.clone();
+   |     -----   ^^^^^^^^^ expected `Option<String>`, found `Option<&String>`
+   |     |
+   |     expected due to the type of this binding
+   |
+   = note: expected enum `Option<String>`
+              found enum `Option<&String>`
+help: use `Option::cloned` to clone the value inside the `Option`
+   |
+LL |     lol.x = x.clone().cloned();
+   |                      +++++++++
+
+error[E0308]: mismatched types
+  --> $DIR/copied-and-cloned.rs:17:26
    |
 LL |     expect::<Option<()>>(x);
    |     -------------------- ^ expected `Option<()>`, found `Option<&()>`
@@ -19,7 +34,7 @@ LL |     expect::<Option<()>>(x.copied());
    |                           +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:11:30
+  --> $DIR/copied-and-cloned.rs:21:30
    |
 LL |     expect::<Result<(), ()>>(x);
    |     ------------------------ ^ expected `Result<(), ()>`, found `Result<&(), _>`
@@ -39,7 +54,7 @@ LL |     expect::<Result<(), ()>>(x.copied());
    |                               +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:16:30
+  --> $DIR/copied-and-cloned.rs:26:30
    |
 LL |     expect::<Option<String>>(x);
    |     ------------------------ ^ expected `Option<String>`, found `Option<&String>`
@@ -59,7 +74,7 @@ LL |     expect::<Option<String>>(x.cloned());
    |                               +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:20:34
+  --> $DIR/copied-and-cloned.rs:30:34
    |
 LL |     expect::<Result<String, ()>>(x);
    |     ---------------------------- ^ expected `Result<String, ()>`, found `Result<&String, _>`
@@ -79,20 +94,20 @@ LL |     expect::<Result<String, ()>>(x.cloned());
    |                                   +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:27:25
+  --> $DIR/copied-and-cloned.rs:37:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<String>`, found `Option<&String>`
    |
    = note: expected enum `Option<String>`
               found enum `Option<&String>`
-help: use `Option::as_ref` to convert `Option<String>` to `Option<&String>`
+help: use `Option::cloned` to clone the value inside the `Option`
    |
-LL |     println!("{}", x.as_ref() == y);
-   |                     +++++++++
+LL |     println!("{}", x == y.cloned());
+   |                          +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:35:25
+  --> $DIR/copied-and-cloned.rs:45:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<()>`, found `Option<&mut ()>`
@@ -105,7 +120,7 @@ LL |     println!("{}", x == y.copied());
    |                          +++++++++
 
 error[E0308]: mismatched types
-  --> $DIR/copied-and-cloned.rs:42:25
+  --> $DIR/copied-and-cloned.rs:52:25
    |
 LL |     println!("{}", x == y);
    |                         ^ expected `Option<String>`, found `Option<&mut String>`
@@ -117,6 +132,6 @@ help: use `Option::cloned` to clone the value inside the `Option`
 LL |     println!("{}", x == y.cloned());
    |                          +++++++++
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
new file mode 100644
index 00000000000..57387936a4c
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.fixed
@@ -0,0 +1,17 @@
+//run-rustfix
+#![allow(dead_code)]
+
+trait Trait {}
+
+fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+    //~^ ERROR incorrect parentheses around trait bounds
+    ptr as _
+}
+
+fn foo2(_: &(dyn Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn foo3(_: &(dyn Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
new file mode 100644
index 00000000000..8a1939bcfe9
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.rs
@@ -0,0 +1,17 @@
+//run-rustfix
+#![allow(dead_code)]
+
+trait Trait {}
+
+fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+    //~^ ERROR incorrect parentheses around trait bounds
+    ptr as _
+}
+
+fn foo2(_: &dyn (Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn foo3(_: &dyn(Trait + Send)) {}
+//~^ ERROR incorrect parentheses around trait bounds
+
+fn main() {}
diff --git a/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
new file mode 100644
index 00000000000..2d1abe91a1e
--- /dev/null
+++ b/tests/ui/suggestions/issue-114797-bad-parentheses-dyn-trait.stderr
@@ -0,0 +1,38 @@
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:6:49
+   |
+LL | fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+   |                                                 ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn assert_send(ptr: *mut dyn Trait) -> *mut dyn (Trait + Send) {
+LL + fn assert_send(ptr: *mut dyn Trait) -> *mut (dyn Trait + Send) {
+   |
+
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:11:17
+   |
+LL | fn foo2(_: &dyn (Trait + Send)) {}
+   |                 ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn foo2(_: &dyn (Trait + Send)) {}
+LL + fn foo2(_: &(dyn Trait + Send)) {}
+   |
+
+error: incorrect parentheses around trait bounds
+  --> $DIR/issue-114797-bad-parentheses-dyn-trait.rs:14:16
+   |
+LL | fn foo3(_: &dyn(Trait + Send)) {}
+   |                ^            ^
+   |
+help: fix the parentheses
+   |
+LL - fn foo3(_: &dyn(Trait + Send)) {}
+LL + fn foo3(_: &(dyn Trait + Send)) {}
+   |
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
new file mode 100644
index 00000000000..b0b9b6bbd20
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-1.rs
@@ -0,0 +1,73 @@
+// compile-flags: -Ztrait-solver=next
+// check-pass
+
+// A minimization of an ambiguity when using typenum. See
+// https://github.com/rust-lang/trait-system-refactor-initiative/issues/55
+// for more details.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+impl<Ul: ?Sized, Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Wrapper<Ul>
+where
+    Ul: WithAssoc<Ur>,
+{
+    type Assoc = <<Ul as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+// normalize self type to `Wrapper<Leaf>`
+//   This succeeds, HOWEVER, instantiating the query response previously
+//   incremented the universe index counter.
+// equate impl headers:
+//      <Wrapper<Leaf> as WithAssoc<<Wrapper<Leaf> as Id>::Assoc>>
+//      <Wrapper<?2t> as WithAssoc<Wrapper<?3t>>>
+// ~> AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+// add where bounds:
+// ~> Leaf: WithAssoc<?3t>
+// equate with assoc type:
+//      ?0t
+//      <Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc
+// ~> AliasRelate(
+//      <<Leaf as WithAssoc<?3t>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// We do not reuse `?3t` during generalization because `?0t` cannot name `?4t` as we created
+// it after incrementing the universe index while normalizing the self type.
+//
+// evaluate_added_goals_and_make_query_response:
+//    AliasRelate(<Wrapper<Leaf> as Id>::Assoc, Equate, Wrapper<?3t>)
+//      YES, constrains ?3t to Leaf
+//    AliasRelate(
+//      <<Leaf as WithAssoc<Leaf>>::Assoc as Id>::Assoc,
+//      Equate,
+//      <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc,
+//    )
+//
+// Normalizing <<Leaf as WithAssoc<?4t>>::Assoc as Id>::Assoc then *correctly*
+// results in ambiguity.
+fn main() {
+    bound::<<Wrapper<Leaf> as Id>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
new file mode 100644
index 00000000000..94d645a9859
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
@@ -0,0 +1,75 @@
+// compile-flags: -Ztrait-solver=next
+// known-bug: trait-system-refactor-initiative#60
+
+// Generalizing a projection containing an inference variable
+// which cannot be named by the `root_vid` can result in ambiguity.
+//
+// Because we do not decrement the universe index when exiting a forall,
+// this can cause unexpected failures.
+//
+// See generalize-proj-new-universe-index-1.rs for more details.
+
+// For this reproduction we need:
+// - an inference variable with a lower universe
+// - enter a binder to increment the current universe
+// - create a new inference variable which is constrained by proving a goal
+// - equate a projection containing the new variable with the first variable
+// - generalization creates yet another inference variable which is then
+//   part of an alias-relate, resulting this to fail with ambiguity.
+//
+// Because we need to enter the binder in-between the creation of the first
+// and second inference variable, this is easiest via
+// `assemble_candidates_after_normalizing_self_ty` because eagerly call
+// `try_evaluate_added_goals` there before creating the inference variables
+// for the impl parameters.
+trait Id {
+    type Assoc: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Assoc = T;
+}
+
+// By adding an higher ranked bound to the impl we currently
+// propagate this bound to the caller, forcing us to create a new
+// universe.
+trait IdHigherRankedBound {
+    type Assoc: ?Sized;
+}
+
+impl<T: ?Sized> IdHigherRankedBound for T
+where
+    for<'a> T: 'a,
+{
+    type Assoc = T;
+}
+
+trait WithAssoc<T: ?Sized> {
+    type Assoc: ?Sized;
+}
+
+
+struct Leaf;
+struct Wrapper<U: ?Sized>(U);
+struct Rigid;
+
+impl<U: ?Sized> WithAssoc<U> for Leaf {
+    type Assoc = U;
+}
+
+
+impl<Ur: ?Sized> WithAssoc<Wrapper<Ur>> for Rigid
+where
+    Leaf: WithAssoc<Ur>,
+{
+    type Assoc = <<Leaf as WithAssoc<Ur>>::Assoc as Id>::Assoc;
+}
+
+fn bound<T: ?Sized, U: ?Sized, V: ?Sized>()
+where
+    T: WithAssoc<U, Assoc = V>,
+{
+}
+
+fn main() {
+    bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+}
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
new file mode 100644
index 00000000000..9a8060133b8
--- /dev/null
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.stderr
@@ -0,0 +1,9 @@
+error[E0282]: type annotations needed
+  --> $DIR/generalize-proj-new-universe-index-2.rs:74:5
+   |
+LL |     bound::<<Rigid as IdHigherRankedBound>::Assoc, <Wrapper<Leaf> as Id>::Assoc, _>()
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot infer type of the type parameter `V` declared on the function `bound`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index d48d9b89d1d..b612005fcb0 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -2,22 +2,8 @@ error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
   --> $DIR/type-checking-test-1.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-1.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo`
-   |
-   = note: required for the cast from `&&dyn Foo` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index 7c7beec0809..afea8521e87 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -18,7 +18,6 @@ fn test_specific(x: &dyn Foo) {
 fn test_unknown_version(x: &dyn Foo) {
     let _ = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //[current]~^^ ERROR the trait bound `&dyn Foo: Bar<_>` is not satisfied
 }
 
 fn test_infer_version(x: &dyn Foo) {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
index 36b11dffdb1..b024b27750b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -18,13 +18,11 @@ fn test_specific2(x: &dyn Foo<u32>) {
 fn test_specific3(x: &dyn Foo<i32>) {
     let _ = x as &dyn Bar<u32>; // Error
                                 //~^ ERROR non-primitive cast
-                                //~^^ ERROR the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
 }
 
 fn test_infer_arg(x: &dyn Foo<u32>) {
     let a = x as &dyn Bar<_>; // Ambiguous
                               //~^ ERROR non-primitive cast
-                              //~^^ ERROR the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
     let _ = a.bar();
 }
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index 856303ef4dd..3e59b9d3363 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -2,41 +2,14 @@ error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
   --> $DIR/type-checking-test-2.rs:19:13
    |
 LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^^^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let _ = &x as &dyn Bar<u32>; // Error
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<i32>: Bar<u32>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:19:13
-   |
-LL |     let _ = x as &dyn Bar<u32>; // Error
-   |             ^ the trait `Bar<u32>` is not implemented for `&dyn Foo<i32>`
-   |
-   = note: required for the cast from `&&dyn Foo<i32>` to `&dyn Bar<u32>`
+   |             ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-2.rs:25:13
+  --> $DIR/type-checking-test-2.rs:24:13
    |
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^^^^^^^^^^^^^^^^ invalid cast
-   |
-help: consider borrowing the value
-   |
-LL |     let a = &x as &dyn Bar<_>; // Ambiguous
-   |             +
-
-error[E0277]: the trait bound `&dyn Foo<u32>: Bar<_>` is not satisfied
-  --> $DIR/type-checking-test-2.rs:25:13
-   |
-LL |     let a = x as &dyn Bar<_>; // Ambiguous
-   |             ^ the trait `Bar<_>` is not implemented for `&dyn Foo<u32>`
-   |
-   = note: required for the cast from `&&dyn Foo<u32>` to `&dyn Bar<_>`
+   |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0277, E0605.
-For more information about an error, try `rustc --explain E0277`.
+For more information about this error, try `rustc --explain E0605`.
diff --git a/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs
new file mode 100644
index 00000000000..54a22510066
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs
@@ -0,0 +1,21 @@
+// crate foo
+
+#![feature(type_alias_impl_trait)]
+
+type Tait = impl Sized;
+fn _constrain() -> Tait {}
+
+struct WrapperWithDrop<T>(T);
+impl<T> Drop for WrapperWithDrop<T> {
+    fn drop(&mut self) {}
+}
+
+pub struct Foo(WrapperWithDrop<Tait>);
+
+trait Id {
+    type Id: ?Sized;
+}
+impl<T: ?Sized> Id for T {
+    type Id = T;
+}
+pub struct Bar(WrapperWithDrop<<Tait as Id>::Id>);
diff --git a/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs b/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs
new file mode 100644
index 00000000000..51d28704972
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/drop-shim-relates-opaque-issue-114375.rs
@@ -0,0 +1,10 @@
+// aux-build:drop-shim-relates-opaque-aux.rs
+// compile-flags: -Zvalidate-mir --crate-type=lib
+// build-pass
+
+extern crate drop_shim_relates_opaque_aux;
+
+pub fn drop_foo(_: drop_shim_relates_opaque_aux::Foo) {}
+pub fn drop_bar(_: drop_shim_relates_opaque_aux::Bar) {}
+
+fn main() {}
diff --git a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
index aa73b824a57..32f8d2f45dc 100644
--- a/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
+++ b/tests/ui/unknown-unstable-lints/deny-unstable-lint-command-line.stderr
@@ -1,18 +1,18 @@
 error: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
    = note: requested on the command line with `-D unknown-lints`
 
 error: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
 
 error: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
index 82851c80064..dd9ecf02fa6 100644
--- a/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
+++ b/tests/ui/unknown-unstable-lints/warn-unknown-unstable-lint-command-line.stderr
@@ -1,18 +1,18 @@
 warning: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
    = note: requested on the command line with `-W unknown-lints`
 
 warning: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
 
 warning: unknown lint: `test_unstable_lint`
    |
    = note: the `test_unstable_lint` lint is unstable
-   = help: add `#![feature(test_unstable_lint)]` to the crate attributes to enable
+   = help: add `-Zcrate-attr="feature(test_unstable_lint)"` to the command-line options to enable
 
 warning: 3 warnings emitted
 
diff --git a/triagebot.toml b/triagebot.toml
index e4bcb9361af..aef5b5bb8dc 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -562,6 +562,10 @@ Otherwise, you can ignore this comment.
 [mentions."src/tools/x"]
 message = "`src/tools/x` was changed. Bump version of Cargo.toml in `src/tools/x` so tidy will suggest installing the new version."
 
+[mentions."src/tools/tidy/src/deps.rs"]
+message = "Third-party dependency whitelist may have been modified! You must ensure that any new dependencies have compatible licenses before merging."
+cc = ["@davidtwco", "@wesleywiser"]
+
 [mentions."src/bootstrap/defaults/config.compiler.toml"]
 message = "This PR changes src/bootstrap/defaults/config.compiler.toml. If appropriate, please also update `config.codegen.toml` so the defaults are in sync."
 [mentions."src/bootstrap/defaults/config.codegen.toml"]
@@ -581,7 +585,7 @@ cc = ["@nnethercote"]
 [assign]
 warn_non_default_branch = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"
-users_on_vacation = ["jyn514", "WaffleLapkin", "clubby789", "oli-obk"]
+users_on_vacation = ["jyn514", "clubby789", "oli-obk"]
 
 [assign.adhoc_groups]
 compiler-team = [
@@ -597,7 +601,6 @@ compiler-team-contributors = [
     "@TaKO8Ki",
     "@WaffleLapkin",
     "@b-naber",
-    "@fee1-dead",
 ]
 compiler = [
     "compiler-team",