about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml12
-rw-r--r--Cargo.lock2
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs31
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/polonius.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/common.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/metadata.rs19
-rw-r--r--compiler/rustc_const_eval/src/const_eval/machine.rs12
-rw-r--r--compiler/rustc_const_eval/src/interpret/eval_context.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/intern.rs2
-rw-r--r--compiler/rustc_const_eval/src/interpret/machine.rs30
-rw-r--r--compiler/rustc_const_eval/src/interpret/mod.rs1
-rw-r--r--compiler/rustc_const_eval/src/interpret/operand.rs8
-rw-r--r--compiler/rustc_const_eval/src/interpret/place.rs32
-rw-r--r--compiler/rustc_const_eval/src/interpret/terminator.rs157
-rw-r--r--compiler/rustc_const_eval/src/interpret/visitor.rs4
-rw-r--r--compiler/rustc_driver_impl/src/lib.rs27
-rw-r--r--compiler/rustc_hir/src/def.rs7
-rw-r--r--compiler/rustc_hir/src/target.rs11
-rw-r--r--compiler/rustc_hir_analysis/src/astconv/mod.rs4
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs18
-rw-r--r--compiler/rustc_hir_analysis/src/collect/item_bounds.rs8
-rw-r--r--compiler/rustc_hir_analysis/src/impl_wf_check.rs15
-rw-r--r--compiler/rustc_hir_analysis/src/variance/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/lib.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/method/mod.rs10
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs12
-rw-r--r--compiler/rustc_infer/src/infer/error_reporting/suggest.rs77
-rw-r--r--compiler/rustc_infer/src/infer/mod.rs38
-rw-r--r--compiler/rustc_lint/messages.ftl3
-rw-r--r--compiler/rustc_lint/src/fn_null_check.rs112
-rw-r--r--compiler/rustc_lint/src/lib.rs3
-rw-r--r--compiler/rustc_lint/src/lints.rs6
-rw-r--r--compiler/rustc_lint_defs/src/builtin.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp11
-rw-r--r--compiler/rustc_metadata/src/rmeta/encoder.rs31
-rw-r--r--compiler/rustc_metadata/src/rmeta/table.rs1
-rw-r--r--compiler/rustc_middle/src/hir/map/mod.rs8
-rw-r--r--compiler/rustc_middle/src/mir/syntax.rs14
-rw-r--r--compiler/rustc_middle/src/ty/consts/kind.rs4
-rw-r--r--compiler/rustc_middle/src/ty/context.rs14
-rw-r--r--compiler/rustc_middle/src/ty/list.rs11
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs25
-rw-r--r--compiler/rustc_middle/src/ty/relate.rs12
-rw-r--r--compiler/rustc_middle/src/ty/structural_impls.rs191
-rw-r--r--compiler/rustc_middle/src/ty/sty.rs28
-rw-r--r--compiler/rustc_middle/src/ty/subst.rs11
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs11
-rw-r--r--compiler/rustc_mir_dataflow/src/impls/mod.rs8
-rw-r--r--compiler/rustc_mir_dataflow/src/lib.rs1
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/builder.rs125
-rw-r--r--compiler/rustc_mir_dataflow/src/move_paths/mod.rs72
-rw-r--r--compiler/rustc_mir_dataflow/src/un_derefer.rs100
-rw-r--r--compiler/rustc_mir_transform/src/const_prop.rs6
-rw-r--r--compiler/rustc_mir_transform/src/dataflow_const_prop.rs4
-rw-r--r--compiler/rustc_monomorphize/src/polymorphize.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs1
-rw-r--r--compiler/rustc_privacy/src/lib.rs15
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs1
-rw-r--r--compiler/rustc_resolve/src/late.rs8
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs66
-rw-r--r--compiler/rustc_session/src/options.rs3
-rw-r--r--compiler/rustc_smir/Cargo.toml6
-rw-r--r--compiler/rustc_smir/rust-toolchain.toml2
-rw-r--r--compiler/rustc_smir/src/lib.rs11
-rw-r--r--compiler/rustc_smir/src/rustc_internal/mod.rs10
-rw-r--r--compiler/rustc_smir/src/rustc_smir/mod.rs201
-rw-r--r--compiler/rustc_smir/src/stable_mir/mir/body.rs181
-rw-r--r--compiler/rustc_span/src/symbol.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/project.rs155
-rw-r--r--compiler/rustc_ty_utils/src/assoc.rs108
-rw-r--r--compiler/rustc_ty_utils/src/implied_bounds.rs1
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs1
-rw-r--r--compiler/rustc_ty_utils/src/ty.rs10
-rw-r--r--compiler/rustc_type_ir/src/lib.rs41
-rw-r--r--compiler/rustc_type_ir/src/structural_impls.rs161
-rw-r--r--compiler/rustc_type_ir/src/sty.rs79
-rw-r--r--library/core/src/mem/transmutability.rs1
-rw-r--r--library/core/src/ptr/const_ptr.rs1
-rw-r--r--library/core/src/ptr/mut_ptr.rs1
-rw-r--r--library/std/src/fs.rs97
-rw-r--r--library/std/src/io/readbuf.rs7
-rw-r--r--library/std/src/os/android/raw.rs105
-rw-r--r--src/bootstrap/builder.rs10
-rw-r--r--src/bootstrap/compile.rs4
-rw-r--r--src/bootstrap/config.rs38
-rw-r--r--src/bootstrap/dist.rs6
-rw-r--r--src/bootstrap/download.rs36
-rw-r--r--src/bootstrap/lib.rs5
-rw-r--r--src/bootstrap/test.rs2
-rw-r--r--src/ci/github-actions/ci.yml2
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/embedded-book0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
m---------src/doc/rustc-dev-guide0
-rw-r--r--src/doc/style-guide/src/expressions.md17
-rw-r--r--src/librustdoc/formats/item_type.rs1
-rw-r--r--src/librustdoc/passes/collect_intra_doc_links.rs4
-rw-r--r--src/tools/clippy/clippy_lints/src/declared_lints.rs1
-rw-r--r--src/tools/clippy/clippy_lints/src/fn_null_check.rs102
-rw-r--r--src/tools/clippy/clippy_lints/src/lib.rs2
-rw-r--r--src/tools/clippy/clippy_lints/src/renamed_lints.rs1
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs3
-rw-r--r--src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs3
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.rs22
-rw-r--r--src/tools/clippy/tests/ui/fn_null_check.stderr43
-rw-r--r--src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs3
-rw-r--r--src/tools/clippy/tests/ui/rename.fixed2
-rw-r--r--src/tools/clippy/tests/ui/rename.rs2
-rw-r--r--src/tools/clippy/tests/ui/rename.stderr112
-rw-r--r--src/tools/lint-docs/src/groups.rs1
-rw-r--r--src/tools/lint-docs/src/lib.rs6
-rw-r--r--src/tools/miri/src/borrow_tracker/mod.rs6
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs4
-rw-r--r--src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs32
-rw-r--r--src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs61
-rw-r--r--src/tools/miri/src/lib.rs1
-rw-r--r--src/tools/miri/src/machine.rs53
-rw-r--r--src/tools/miri/src/shims/mod.rs8
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs34
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr37
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr39
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs27
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr22
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr20
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs34
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr37
-rw-r--r--src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr39
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr20
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs (renamed from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.rs)10
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr (renamed from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr)13
-rw-r--r--src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr (renamed from src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr)13
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs7
-rw-r--r--src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr4
-rw-r--r--src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs25
-rw-r--r--src/tools/rls/Cargo.toml1
-rw-r--r--src/tools/rls/src/main.rs9
-rw-r--r--src/tools/tidy/src/pal.rs1
-rw-r--r--tests/ui-fulldeps/missing-rustc-driver-error.rs4
-rw-r--r--tests/ui-fulldeps/missing-rustc-driver-error.stderr12
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs2
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr48
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/basic.rs14
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.rs2
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/equality.stderr17
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.rs2
-rw-r--r--tests/ui/async-await/edition-deny-async-fns-2015.stderr98
-rw-r--r--tests/ui/async-await/in-trait/async-associated-types.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-default-fn-overridden.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr17
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-extra.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-manual.stderr11
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics-and-bounds.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-generics.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-generics.stderr37
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-lifetimes.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-recursive-generic.stderr12
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.rs2
-rw-r--r--tests/ui/async-await/in-trait/async-recursive.stderr12
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.rs2
-rw-r--r--tests/ui/async-await/in-trait/bad-signatures.stderr17
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs2
-rw-r--r--tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr25
-rw-r--r--tests/ui/async-await/in-trait/early-bound-1.rs2
-rw-r--r--tests/ui/async-await/in-trait/early-bound-2.rs2
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.rs2
-rw-r--r--tests/ui/async-await/in-trait/fn-not-async-err2.stderr12
-rw-r--r--tests/ui/async-await/in-trait/implied-bounds.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-102138.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-102219.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-102310.rs2
-rw-r--r--tests/ui/async-await/in-trait/issue-104678.rs2
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.rs2
-rw-r--r--tests/ui/async-await/in-trait/lifetime-mismatch.stderr12
-rw-r--r--tests/ui/async-await/in-trait/missing-feature-flag.rs2
-rw-r--r--tests/ui/async-await/in-trait/missing-feature-flag.stderr30
-rw-r--r--tests/ui/async-await/in-trait/missing-send-bound.rs2
-rw-r--r--tests/ui/async-await/in-trait/missing-send-bound.stderr20
-rw-r--r--tests/ui/async-await/in-trait/object-safety.rs2
-rw-r--r--tests/ui/async-await/in-trait/object-safety.stderr18
-rw-r--r--tests/ui/async-await/in-trait/return-not-existing-pair.rs2
-rw-r--r--tests/ui/async-await/in-trait/return-not-existing-pair.stderr39
-rw-r--r--tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs2
-rw-r--r--tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr9
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.rs2
-rw-r--r--tests/ui/async-await/in-trait/return-type-suggestion.stderr14
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-early.stderr37
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-late.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/issue-110963-late.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/supertrait-bound.stderr11
-rw-r--r--tests/ui/async-await/return-type-notation/ty-or-ct-params.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr29
-rw-r--r--tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr9
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.rs24
-rw-r--r--tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs29
-rw-r--r--tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr53
-rw-r--r--tests/ui/hygiene/extern-prelude-from-opaque-fail.rs1
-rw-r--r--tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr20
-rw-r--r--tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs6
-rw-r--r--tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/deep-match-works.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/deep-match.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/deep-match.stderr15
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr11
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-type-err.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr24
-rw-r--r--tests/ui/impl-trait/in-trait/default-body.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/default-method-constraint.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr17
-rw-r--r--tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/early.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/encode.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr2
-rw-r--r--tests/ui/impl-trait/in-trait/foreign.rs6
-rw-r--r--tests/ui/impl-trait/in-trait/generics-mismatch.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/generics-mismatch.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102140.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102140.stderr29
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102301.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/issue-102571.stderr14
-rw-r--r--tests/ui/impl-trait/in-trait/nested-rpitit.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/object-safety.stderr49
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr17
-rw-r--r--tests/ui/impl-trait/in-trait/opaque-in-impl.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr16
-rw-r--r--tests/ui/impl-trait/in-trait/reveal.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/signature-mismatch.stderr61
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.stderr31
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-substs-remap.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/success.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs3
-rw-r--r--tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr12
-rw-r--r--tests/ui/impl-trait/in-trait/unconstrained-lt.rs7
-rw-r--r--tests/ui/impl-trait/in-trait/unconstrained-lt.stderr9
-rw-r--r--tests/ui/impl-trait/in-trait/variances-of-gat.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.rs2
-rw-r--r--tests/ui/impl-trait/in-trait/wf-bounds.stderr57
-rw-r--r--tests/ui/impl-trait/in-trait/where-clause.rs2
-rw-r--r--tests/ui/inference/issue-113354.fixed4
-rw-r--r--tests/ui/inference/issue-113354.rs4
-rw-r--r--tests/ui/inference/issue-113354.stderr14
-rw-r--r--tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs12
-rw-r--r--tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr14
-rw-r--r--tests/ui/lint/fn_null_check.rs30
-rw-r--r--tests/ui/lint/fn_null_check.stderr67
-rw-r--r--tests/ui/macros/builtin-prelude-no-accidents.stderr4
-rw-r--r--tests/ui/panics/abort-on-panic.rs2
-rw-r--r--tests/ui/resolve/112590-2.fixed34
-rw-r--r--tests/ui/resolve/112590-2.rs26
-rw-r--r--tests/ui/resolve/112590-2.stderr71
-rw-r--r--tests/ui/resolve/export-fully-qualified-2018.stderr5
-rw-r--r--tests/ui/resolve/export-fully-qualified.stderr5
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs3
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr15
-rw-r--r--tests/ui/sanitize/address.rs3
-rw-r--r--tests/ui/sanitize/badfree.rs1
-rw-r--r--tests/ui/sanitize/issue-72154-lifetime-markers.rs1
-rw-r--r--tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs1
-rw-r--r--tests/ui/sanitize/use-after-scope.rs1
-rw-r--r--tests/ui/suggestions/crate-or-module-typo.stderr16
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs5
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr25
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types.rs5
-rw-r--r--tests/ui/transmutability/references/recursive-wrapper-types.stderr25
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed (renamed from tests/ui/parser/type-alias-where-fixable.fixed)0
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs (renamed from tests/ui/parser/type-alias-where-fixable.rs)0
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr (renamed from tests/ui/parser/type-alias-where-fixable.stderr)6
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed15
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs15
-rw-r--r--tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr29
-rw-r--r--tests/ui/where-clauses/where-clause-placement-type-alias.rs (renamed from tests/ui/parser/type-alias-where.rs)0
-rw-r--r--tests/ui/where-clauses/where-clause-placement-type-alias.stderr (renamed from tests/ui/parser/type-alias-where.stderr)4
-rw-r--r--triagebot.toml7
303 files changed, 3848 insertions, 1609 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 3929b064c26..0842b69c219 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -315,7 +315,7 @@ jobs:
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
               DIST_REQUIRE_ALL_TOOLS: 1
-            os: macos-latest
+            os: macos-13
           - name: dist-apple-various
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --host='' --target=aarch64-apple-ios,x86_64-apple-ios,aarch64-apple-ios-sim"
@@ -326,7 +326,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-13
           - name: dist-x86_64-apple-alt
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths"
@@ -337,7 +337,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-13
           - name: x86_64-apple-1
             env:
               SCRIPT: "./x.py --stage 2 test --exclude tests/ui --exclude tests/rustdoc --exclude tests/run-make-fulldeps"
@@ -348,7 +348,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-13
           - name: x86_64-apple-2
             env:
               SCRIPT: "./x.py --stage 2 test tests/ui tests/rustdoc tests/run-make-fulldeps"
@@ -359,7 +359,7 @@ jobs:
               NO_LLVM_ASSERTIONS: 1
               NO_DEBUG_ASSERTIONS: 1
               NO_OVERFLOW_CHECKS: 1
-            os: macos-latest
+            os: macos-13
           - name: dist-aarch64-apple
             env:
               SCRIPT: "./x.py dist bootstrap --include-default-paths --stage 2"
@@ -374,7 +374,7 @@ jobs:
               NO_OVERFLOW_CHECKS: 1
               DIST_REQUIRE_ALL_TOOLS: 1
               JEMALLOC_SYS_WITH_LG_PAGE: 14
-            os: macos-latest
+            os: macos-13
           - name: x86_64-msvc
             env:
               RUST_CONFIGURE_ARGS: "--build=x86_64-pc-windows-msvc --enable-profiler"
diff --git a/Cargo.lock b/Cargo.lock
index 96eda77abb2..fcd58d8a866 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3021,7 +3021,6 @@ dependencies = [
 name = "rls"
 version = "2.0.0"
 dependencies = [
- "serde",
  "serde_json",
 ]
 
@@ -4234,6 +4233,7 @@ dependencies = [
  "rustc_hir",
  "rustc_middle",
  "rustc_span",
+ "rustc_target",
  "scoped-tls",
  "tracing",
 ]
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 096cea945b0..418e1df5857 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -1300,14 +1300,7 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         });
                     }
                 }
-                AssocItemKind::Type(box TyAlias {
-                    generics,
-                    where_clauses,
-                    where_predicates_split,
-                    bounds,
-                    ty,
-                    ..
-                }) => {
+                AssocItemKind::Type(box TyAlias { bounds, ty, .. }) => {
                     if ty.is_none() {
                         self.session.emit_err(errors::AssocTypeWithoutBody {
                             span: item.span,
@@ -1315,18 +1308,26 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                         });
                     }
                     self.check_type_no_bounds(bounds, "`impl`s");
-                    if ty.is_some() {
-                        self.check_gat_where(
-                            item.id,
-                            generics.where_clause.predicates.split_at(*where_predicates_split).0,
-                            *where_clauses,
-                        );
-                    }
                 }
                 _ => {}
             }
         }
 
+        if let AssocItemKind::Type(box TyAlias {
+            generics,
+            where_clauses,
+            where_predicates_split,
+            ty: Some(_),
+            ..
+        }) = &item.kind
+        {
+            self.check_gat_where(
+                item.id,
+                generics.where_clause.predicates.split_at(*where_predicates_split).0,
+                *where_clauses,
+            );
+        }
+
         if ctxt == AssocCtxt::Trait || self.in_trait_impl {
             self.visibility_not_permitted(&item.vis, errors::VisibilityNotPermittedNote::TraitImpl);
             if let AssocItemKind::Fn(box Fn { sig, .. }) = &item.kind {
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
index b344ab46adb..012075d7114 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/polonius.rs
@@ -20,7 +20,7 @@ struct UseFactsExtractor<'me, 'tcx> {
 }
 
 // A Visitor to walk through the MIR and extract point-wise facts
-impl UseFactsExtractor<'_, '_> {
+impl<'tcx> UseFactsExtractor<'_, 'tcx> {
     fn location_to_index(&self, location: Location) -> LocationIndex {
         self.location_table.mid_index(location)
     }
@@ -45,7 +45,7 @@ impl UseFactsExtractor<'_, '_> {
         self.path_accessed_at_base.push((path, self.location_to_index(location)));
     }
 
-    fn place_to_mpi(&self, place: &Place<'_>) -> Option<MovePathIndex> {
+    fn place_to_mpi(&self, place: &Place<'tcx>) -> Option<MovePathIndex> {
         match self.move_data.rev_lookup.find(place.as_ref()) {
             LookupResult::Exact(mpi) => Some(mpi),
             LookupResult::Parent(mmpi) => mmpi,
diff --git a/compiler/rustc_codegen_llvm/src/common.rs b/compiler/rustc_codegen_llvm/src/common.rs
index a2db59bd6c4..4d879fbdcb7 100644
--- a/compiler/rustc_codegen_llvm/src/common.rs
+++ b/compiler/rustc_codegen_llvm/src/common.rs
@@ -290,7 +290,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
                     }
                 };
                 let llval = unsafe {
-                    llvm::LLVMRustConstInBoundsGEP2(
+                    llvm::LLVMConstInBoundsGEP2(
                         self.type_i8(),
                         self.const_bitcast(base_addr, self.type_i8p_ext(base_addr_space)),
                         &self.const_usize(offset.bytes()),
@@ -320,7 +320,7 @@ impl<'ll, 'tcx> ConstMethods<'tcx> for CodegenCx<'ll, 'tcx> {
 
     fn const_ptr_byte_offset(&self, base_addr: Self::Value, offset: abi::Size) -> Self::Value {
         unsafe {
-            llvm::LLVMRustConstInBoundsGEP2(
+            llvm::LLVMConstInBoundsGEP2(
                 self.type_i8(),
                 self.const_bitcast(base_addr, self.type_i8p()),
                 &self.const_usize(offset.bytes()),
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 3ad546b61e9..e1dfc1b2dd6 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -1155,7 +1155,7 @@ extern "C" {
     pub fn LLVMConstVector(ScalarConstantVals: *const &Value, Size: c_uint) -> &Value;
 
     // Constant expressions
-    pub fn LLVMRustConstInBoundsGEP2<'a>(
+    pub fn LLVMConstInBoundsGEP2<'a>(
         ty: &'a Type,
         ConstantVal: &'a Value,
         ConstantIndices: *const &'a Value,
diff --git a/compiler/rustc_codegen_ssa/src/back/metadata.rs b/compiler/rustc_codegen_ssa/src/back/metadata.rs
index 00e6acb5c1a..1f827a2375d 100644
--- a/compiler/rustc_codegen_ssa/src/back/metadata.rs
+++ b/compiler/rustc_codegen_ssa/src/back/metadata.rs
@@ -12,7 +12,6 @@ use object::{
 
 use snap::write::FrameEncoder;
 
-use object::elf::NT_GNU_PROPERTY_TYPE_0;
 use rustc_data_structures::memmap::Mmap;
 use rustc_data_structures::owned_slice::{try_slice_owned, OwnedSlice};
 use rustc_metadata::fs::METADATA_FILENAME;
@@ -124,7 +123,7 @@ fn add_gnu_property_note(
     let mut data: Vec<u8> = Vec::new();
     let n_namsz: u32 = 4; // Size of the n_name field
     let n_descsz: u32 = 16; // Size of the n_desc field
-    let n_type: u32 = NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor
+    let n_type: u32 = object::elf::NT_GNU_PROPERTY_TYPE_0; // Type of note descriptor
     let header_values = [n_namsz, n_descsz, n_type];
     header_values.iter().for_each(|v| {
         data.extend_from_slice(&match endianness {
@@ -134,8 +133,8 @@ fn add_gnu_property_note(
     });
     data.extend_from_slice(b"GNU\0"); // Owner of the program property note
     let pr_type: u32 = match architecture {
-        Architecture::X86_64 => 0xc0000002,
-        Architecture::Aarch64 => 0xc0000000,
+        Architecture::X86_64 => object::elf::GNU_PROPERTY_X86_FEATURE_1_AND,
+        Architecture::Aarch64 => object::elf::GNU_PROPERTY_AARCH64_FEATURE_1_AND,
         _ => unreachable!(),
     };
     let pr_datasz: u32 = 4; //size of the pr_data field
@@ -243,8 +242,16 @@ pub(crate) fn create_object_file(sess: &Session) -> Option<write::Object<'static
                 s if s.contains("r6") => elf::EF_MIPS_ARCH_32R6,
                 _ => elf::EF_MIPS_ARCH_32R2,
             };
-            // The only ABI LLVM supports for 32-bit MIPS CPUs is o32.
-            let mut e_flags = elf::EF_MIPS_CPIC | elf::EF_MIPS_ABI_O32 | arch;
+
+            let mut e_flags = elf::EF_MIPS_CPIC | arch;
+
+            // If the ABI is explicitly given, use it or default to O32.
+            match sess.target.options.llvm_abiname.to_lowercase().as_str() {
+                "n32" => e_flags |= elf::EF_MIPS_ABI2,
+                "o32" => e_flags |= elf::EF_MIPS_ABI_O32,
+                _ => e_flags |= elf::EF_MIPS_ABI_O32,
+            };
+
             if sess.target.options.relocation_model != RelocModel::Static {
                 e_flags |= elf::EF_MIPS_PIC;
             }
diff --git a/compiler/rustc_const_eval/src/const_eval/machine.rs b/compiler/rustc_const_eval/src/const_eval/machine.rs
index f9f645af41f..a20f0276b3e 100644
--- a/compiler/rustc_const_eval/src/const_eval/machine.rs
+++ b/compiler/rustc_const_eval/src/const_eval/machine.rs
@@ -22,7 +22,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
 
 use crate::errors::{LongRunning, LongRunningWarn};
 use crate::interpret::{
-    self, compile_time_machine, AllocId, ConstAllocation, FnVal, Frame, ImmTy, InterpCx,
+    self, compile_time_machine, AllocId, ConstAllocation, FnArg, FnVal, Frame, ImmTy, InterpCx,
     InterpResult, OpTy, PlaceTy, Pointer, Scalar,
 };
 use crate::{errors, fluent_generated as fluent};
@@ -201,7 +201,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
     fn hook_special_const_fn(
         &mut self,
         instance: ty::Instance<'tcx>,
-        args: &[OpTy<'tcx>],
+        args: &[FnArg<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
     ) -> InterpResult<'tcx, Option<ty::Instance<'tcx>>> {
@@ -210,6 +210,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
         if Some(def_id) == self.tcx.lang_items().panic_display()
             || Some(def_id) == self.tcx.lang_items().begin_panic_fn()
         {
+            let args = self.copy_fn_args(args)?;
             // &str or &&str
             assert!(args.len() == 1);
 
@@ -236,8 +237,9 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
 
             return Ok(Some(new_instance));
         } else if Some(def_id) == self.tcx.lang_items().align_offset_fn() {
+            let args = self.copy_fn_args(args)?;
             // For align_offset, we replace the function call if the pointer has no address.
-            match self.align_offset(instance, args, dest, ret)? {
+            match self.align_offset(instance, &args, dest, ret)? {
                 ControlFlow::Continue(()) => return Ok(Some(instance)),
                 ControlFlow::Break(()) => return Ok(None),
             }
@@ -293,7 +295,7 @@ impl<'mir, 'tcx: 'mir> CompileTimeEvalContext<'mir, 'tcx> {
                     self.eval_fn_call(
                         FnVal::Instance(instance),
                         (CallAbi::Rust, fn_abi),
-                        &[addr, align],
+                        &[FnArg::Copy(addr), FnArg::Copy(align)],
                         /* with_caller_location = */ false,
                         dest,
                         ret,
@@ -427,7 +429,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for CompileTimeInterpreter<'mir,
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         _abi: CallAbi,
-        args: &[OpTy<'tcx>],
+        args: &[FnArg<'tcx>],
         dest: &PlaceTy<'tcx>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction, // unwinding is not supported in consts
diff --git a/compiler/rustc_const_eval/src/interpret/eval_context.rs b/compiler/rustc_const_eval/src/interpret/eval_context.rs
index 36606ff69a6..5e5ad31d8c2 100644
--- a/compiler/rustc_const_eval/src/interpret/eval_context.rs
+++ b/compiler/rustc_const_eval/src/interpret/eval_context.rs
@@ -682,11 +682,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         return_to_block: StackPopCleanup,
     ) -> InterpResult<'tcx> {
         trace!("body: {:#?}", body);
-        // Clobber previous return place contents, nobody is supposed to be able to see them any more
-        // This also checks dereferenceable, but not align. We rely on all constructed places being
-        // sufficiently aligned (in particular we rely on `deref_operand` checking alignment).
-        self.write_uninit(return_place)?;
-        // first push a stack frame so we have access to the local substs
+        // First push a stack frame so we have access to the local substs
         let pre_frame = Frame {
             body,
             loc: Right(body.span), // Span used for errors caused during preamble.
@@ -805,6 +801,8 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
             throw_ub_custom!(fluent::const_eval_unwind_past_top);
         }
 
+        M::before_stack_pop(self, self.frame())?;
+
         // Copy return value. Must of course happen *before* we deallocate the locals.
         let copy_ret_result = if !unwinding {
             let op = self
diff --git a/compiler/rustc_const_eval/src/interpret/intern.rs b/compiler/rustc_const_eval/src/interpret/intern.rs
index 7b11ad33091..107e5bec614 100644
--- a/compiler/rustc_const_eval/src/interpret/intern.rs
+++ b/compiler/rustc_const_eval/src/interpret/intern.rs
@@ -30,7 +30,7 @@ use super::{
 use crate::const_eval;
 use crate::errors::{DanglingPtrInFinal, UnsupportedUntypedPointer};
 
-pub trait CompileTimeMachine<'mir, 'tcx, T> = Machine<
+pub trait CompileTimeMachine<'mir, 'tcx: 'mir, T> = Machine<
         'mir,
         'tcx,
         MemoryKind = T,
diff --git a/compiler/rustc_const_eval/src/interpret/machine.rs b/compiler/rustc_const_eval/src/interpret/machine.rs
index b448e3a24c6..e101785b6e2 100644
--- a/compiler/rustc_const_eval/src/interpret/machine.rs
+++ b/compiler/rustc_const_eval/src/interpret/machine.rs
@@ -17,7 +17,7 @@ use rustc_target::spec::abi::Abi as CallAbi;
 use crate::const_eval::CheckAlignment;
 
 use super::{
-    AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, Frame, ImmTy, InterpCx,
+    AllocBytes, AllocId, AllocRange, Allocation, ConstAllocation, FnArg, Frame, ImmTy, InterpCx,
     InterpResult, MemoryKind, OpTy, Operand, PlaceTy, Pointer, Provenance, Scalar,
 };
 
@@ -84,7 +84,7 @@ pub trait AllocMap<K: Hash + Eq, V> {
 
 /// Methods of this trait signifies a point where CTFE evaluation would fail
 /// and some use case dependent behaviour can instead be applied.
-pub trait Machine<'mir, 'tcx>: Sized {
+pub trait Machine<'mir, 'tcx: 'mir>: Sized {
     /// Additional memory kinds a machine wishes to distinguish from the builtin ones
     type MemoryKind: Debug + std::fmt::Display + MayLeak + Eq + 'static;
 
@@ -182,7 +182,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         instance: ty::Instance<'tcx>,
         abi: CallAbi,
-        args: &[OpTy<'tcx, Self::Provenance>],
+        args: &[FnArg<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -194,7 +194,7 @@ pub trait Machine<'mir, 'tcx>: Sized {
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
         fn_val: Self::ExtraFnVal,
         abi: CallAbi,
-        args: &[OpTy<'tcx, Self::Provenance>],
+        args: &[FnArg<'tcx, Self::Provenance>],
         destination: &PlaceTy<'tcx, Self::Provenance>,
         target: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -418,6 +418,18 @@ pub trait Machine<'mir, 'tcx>: Sized {
         Ok(())
     }
 
+    /// Called on places used for in-place function argument and return value handling.
+    ///
+    /// These places need to be protected to make sure the program cannot tell whether the
+    /// argument/return value was actually copied or passed in-place..
+    fn protect_in_place_function_argument(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        place: &PlaceTy<'tcx, Self::Provenance>,
+    ) -> InterpResult<'tcx> {
+        // Without an aliasing model, all we can do is put `Uninit` into the place.
+        ecx.write_uninit(place)
+    }
+
     /// Called immediately before a new stack frame gets pushed.
     fn init_frame_extra(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -439,6 +451,14 @@ pub trait Machine<'mir, 'tcx>: Sized {
         Ok(())
     }
 
+    /// Called just before the return value is copied to the caller-provided return place.
+    fn before_stack_pop(
+        _ecx: &InterpCx<'mir, 'tcx, Self>,
+        _frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
+    ) -> InterpResult<'tcx> {
+        Ok(())
+    }
+
     /// Called immediately after a stack frame got popped, but before jumping back to the caller.
     /// The `locals` have already been destroyed!
     fn after_stack_pop(
@@ -484,7 +504,7 @@ pub macro compile_time_machine(<$mir: lifetime, $tcx: lifetime>) {
         _ecx: &mut InterpCx<$mir, $tcx, Self>,
         fn_val: !,
         _abi: CallAbi,
-        _args: &[OpTy<$tcx>],
+        _args: &[FnArg<$tcx>],
         _destination: &PlaceTy<$tcx, Self::Provenance>,
         _target: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
diff --git a/compiler/rustc_const_eval/src/interpret/mod.rs b/compiler/rustc_const_eval/src/interpret/mod.rs
index 898d62361ab..f657f954f9c 100644
--- a/compiler/rustc_const_eval/src/interpret/mod.rs
+++ b/compiler/rustc_const_eval/src/interpret/mod.rs
@@ -26,6 +26,7 @@ pub use self::machine::{compile_time_machine, AllocMap, Machine, MayLeak, StackP
 pub use self::memory::{AllocKind, AllocRef, AllocRefMut, FnVal, Memory, MemoryKind};
 pub use self::operand::{ImmTy, Immediate, OpTy, Operand};
 pub use self::place::{MPlaceTy, MemPlace, MemPlaceMeta, Place, PlaceTy};
+pub use self::terminator::FnArg;
 pub use self::validity::{CtfeValidationMode, RefTracking};
 pub use self::visitor::{MutValueVisitor, Value, ValueVisitor};
 
diff --git a/compiler/rustc_const_eval/src/interpret/operand.rs b/compiler/rustc_const_eval/src/interpret/operand.rs
index 5f89d652fab..6727937363e 100644
--- a/compiler/rustc_const_eval/src/interpret/operand.rs
+++ b/compiler/rustc_const_eval/src/interpret/operand.rs
@@ -575,14 +575,6 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(op)
     }
 
-    /// Evaluate a bunch of operands at once
-    pub(super) fn eval_operands(
-        &self,
-        ops: &[mir::Operand<'tcx>],
-    ) -> InterpResult<'tcx, Vec<OpTy<'tcx, M::Provenance>>> {
-        ops.iter().map(|op| self.eval_operand(op, None)).collect()
-    }
-
     fn eval_ty_constant(
         &self,
         val: ty::Const<'tcx>,
diff --git a/compiler/rustc_const_eval/src/interpret/place.rs b/compiler/rustc_const_eval/src/interpret/place.rs
index ca1106384fd..c2fb61753fe 100644
--- a/compiler/rustc_const_eval/src/interpret/place.rs
+++ b/compiler/rustc_const_eval/src/interpret/place.rs
@@ -328,7 +328,8 @@ where
         };
 
         let mplace = MemPlace { ptr: ptr.to_pointer(self)?, meta };
-        // When deref'ing a pointer, the *static* alignment given by the type is what matters.
+        // `ref_to_mplace` is called on raw pointers even if they don't actually get dereferenced;
+        // we hence can't call `size_and_align_of` since that asserts more validity than we want.
         let align = layout.align.abi;
         Ok(MPlaceTy { mplace, layout, align })
     }
@@ -354,34 +355,37 @@ where
     #[inline]
     pub(super) fn get_place_alloc(
         &self,
-        place: &MPlaceTy<'tcx, M::Provenance>,
+        mplace: &MPlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Option<AllocRef<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
     {
-        assert!(place.layout.is_sized());
-        assert!(!place.meta.has_meta());
-        let size = place.layout.size;
-        self.get_ptr_alloc(place.ptr, size, place.align)
+        let (size, _align) = self
+            .size_and_align_of_mplace(&mplace)?
+            .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+        // Due to packed places, only `mplace.align` matters.
+        self.get_ptr_alloc(mplace.ptr, size, mplace.align)
     }
 
     #[inline]
     pub(super) fn get_place_alloc_mut(
         &mut self,
-        place: &MPlaceTy<'tcx, M::Provenance>,
+        mplace: &MPlaceTy<'tcx, M::Provenance>,
     ) -> InterpResult<'tcx, Option<AllocRefMut<'_, 'tcx, M::Provenance, M::AllocExtra, M::Bytes>>>
     {
-        assert!(place.layout.is_sized());
-        assert!(!place.meta.has_meta());
-        let size = place.layout.size;
-        self.get_ptr_alloc_mut(place.ptr, size, place.align)
+        let (size, _align) = self
+            .size_and_align_of_mplace(&mplace)?
+            .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
+        // Due to packed places, only `mplace.align` matters.
+        self.get_ptr_alloc_mut(mplace.ptr, size, mplace.align)
     }
 
     /// Check if this mplace is dereferenceable and sufficiently aligned.
     pub fn check_mplace(&self, mplace: MPlaceTy<'tcx, M::Provenance>) -> InterpResult<'tcx> {
-        let (size, align) = self
+        let (size, _align) = self
             .size_and_align_of_mplace(&mplace)?
             .unwrap_or((mplace.layout.size, mplace.layout.align.abi));
-        assert!(mplace.align <= align, "dynamic alignment less strict than static one?");
-        let align = if M::enforce_alignment(self).should_check() { align } else { Align::ONE };
+        // Due to packed places, only `mplace.align` matters.
+        let align =
+            if M::enforce_alignment(self).should_check() { mplace.align } else { Align::ONE };
         self.check_ptr_access_align(mplace.ptr, size, align, CheckInAllocMsg::DerefTest)?;
         Ok(())
     }
diff --git a/compiler/rustc_const_eval/src/interpret/terminator.rs b/compiler/rustc_const_eval/src/interpret/terminator.rs
index 15823a5975e..97d7a68e190 100644
--- a/compiler/rustc_const_eval/src/interpret/terminator.rs
+++ b/compiler/rustc_const_eval/src/interpret/terminator.rs
@@ -1,7 +1,8 @@
 use std::borrow::Cow;
 
+use either::Either;
 use rustc_ast::ast::InlineAsmOptions;
-use rustc_middle::ty::layout::{FnAbiOf, LayoutOf};
+use rustc_middle::ty::layout::{FnAbiOf, LayoutOf, TyAndLayout};
 use rustc_middle::ty::Instance;
 use rustc_middle::{
     mir,
@@ -12,12 +13,63 @@ use rustc_target::abi::call::{ArgAbi, ArgAttribute, ArgAttributes, FnAbi, PassMo
 use rustc_target::spec::abi::Abi;
 
 use super::{
-    FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy, Operand,
-    PlaceTy, Scalar, StackPopCleanup,
+    AllocId, FnVal, ImmTy, Immediate, InterpCx, InterpResult, MPlaceTy, Machine, MemoryKind, OpTy,
+    Operand, PlaceTy, Provenance, Scalar, StackPopCleanup,
 };
 use crate::fluent_generated as fluent;
 
+/// An argment passed to a function.
+#[derive(Clone, Debug)]
+pub enum FnArg<'tcx, Prov: Provenance = AllocId> {
+    /// Pass a copy of the given operand.
+    Copy(OpTy<'tcx, Prov>),
+    /// Allow for the argument to be passed in-place: destroy the value originally stored at that place and
+    /// make the place inaccessible for the duration of the function call.
+    InPlace(PlaceTy<'tcx, Prov>),
+}
+
+impl<'tcx, Prov: Provenance> FnArg<'tcx, Prov> {
+    pub fn layout(&self) -> &TyAndLayout<'tcx> {
+        match self {
+            FnArg::Copy(op) => &op.layout,
+            FnArg::InPlace(place) => &place.layout,
+        }
+    }
+}
+
 impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
+    /// Make a copy of the given fn_arg. Any `InPlace` are degenerated to copies, no protection of the
+    /// original memory occurs.
+    pub fn copy_fn_arg(
+        &self,
+        arg: &FnArg<'tcx, M::Provenance>,
+    ) -> InterpResult<'tcx, OpTy<'tcx, M::Provenance>> {
+        match arg {
+            FnArg::Copy(op) => Ok(op.clone()),
+            FnArg::InPlace(place) => self.place_to_op(&place),
+        }
+    }
+
+    /// Make a copy of the given fn_args. Any `InPlace` are degenerated to copies, no protection of the
+    /// original memory occurs.
+    pub fn copy_fn_args(
+        &self,
+        args: &[FnArg<'tcx, M::Provenance>],
+    ) -> InterpResult<'tcx, Vec<OpTy<'tcx, M::Provenance>>> {
+        args.iter().map(|fn_arg| self.copy_fn_arg(fn_arg)).collect()
+    }
+
+    pub fn fn_arg_field(
+        &mut self,
+        arg: &FnArg<'tcx, M::Provenance>,
+        field: usize,
+    ) -> InterpResult<'tcx, FnArg<'tcx, M::Provenance>> {
+        Ok(match arg {
+            FnArg::Copy(op) => FnArg::Copy(self.operand_field(op, field)?),
+            FnArg::InPlace(place) => FnArg::InPlace(self.place_field(place, field)?),
+        })
+    }
+
     pub(super) fn eval_terminator(
         &mut self,
         terminator: &mir::Terminator<'tcx>,
@@ -68,14 +120,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 let old_stack = self.frame_idx();
                 let old_loc = self.frame().loc;
                 let func = self.eval_operand(func, None)?;
-                let args = self.eval_operands(args)?;
+                let args = self.eval_fn_call_arguments(args)?;
 
                 let fn_sig_binder = func.layout.ty.fn_sig(*self.tcx);
                 let fn_sig =
                     self.tcx.normalize_erasing_late_bound_regions(self.param_env, fn_sig_binder);
                 let extra_args = &args[fn_sig.inputs().len()..];
                 let extra_args =
-                    self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout.ty));
+                    self.tcx.mk_type_list_from_iter(extra_args.iter().map(|arg| arg.layout().ty));
 
                 let (fn_val, fn_abi, with_caller_location) = match *func.layout.ty.kind() {
                     ty::FnPtr(_sig) => {
@@ -185,6 +237,21 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         Ok(())
     }
 
+    /// Evaluate the arguments of a function call
+    pub(super) fn eval_fn_call_arguments(
+        &mut self,
+        ops: &[mir::Operand<'tcx>],
+    ) -> InterpResult<'tcx, Vec<FnArg<'tcx, M::Provenance>>> {
+        ops.iter()
+            .map(|op| {
+                Ok(match op {
+                    mir::Operand::Move(place) => FnArg::InPlace(self.eval_place(*place)?),
+                    _ => FnArg::Copy(self.eval_operand(op, None)?),
+                })
+            })
+            .collect()
+    }
+
     fn check_argument_compat(
         caller_abi: &ArgAbi<'tcx, Ty<'tcx>>,
         callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
@@ -275,7 +342,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
     fn pass_argument<'x, 'y>(
         &mut self,
         caller_args: &mut impl Iterator<
-            Item = (&'x OpTy<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>),
+            Item = (&'x FnArg<'tcx, M::Provenance>, &'y ArgAbi<'tcx, Ty<'tcx>>),
         >,
         callee_abi: &ArgAbi<'tcx, Ty<'tcx>>,
         callee_arg: &PlaceTy<'tcx, M::Provenance>,
@@ -295,21 +362,25 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // Now, check
         if !Self::check_argument_compat(caller_abi, callee_abi) {
             let callee_ty = format!("{}", callee_arg.layout.ty);
-            let caller_ty = format!("{}", caller_arg.layout.ty);
+            let caller_ty = format!("{}", caller_arg.layout().ty);
             throw_ub_custom!(
                 fluent::const_eval_incompatible_types,
                 callee_ty = callee_ty,
                 caller_ty = caller_ty,
             )
         }
+        // We work with a copy of the argument for now; if this is in-place argument passing, we
+        // will later protect the source it comes from. This means the callee cannot observe if we
+        // did in-place of by-copy argument passing, except for pointer equality tests.
+        let caller_arg_copy = self.copy_fn_arg(&caller_arg)?;
         // Special handling for unsized parameters.
-        if caller_arg.layout.is_unsized() {
+        if caller_arg_copy.layout.is_unsized() {
             // `check_argument_compat` ensures that both have the same type, so we know they will use the metadata the same way.
-            assert_eq!(caller_arg.layout.ty, callee_arg.layout.ty);
+            assert_eq!(caller_arg_copy.layout.ty, callee_arg.layout.ty);
             // We have to properly pre-allocate the memory for the callee.
-            // So let's tear down some wrappers.
+            // So let's tear down some abstractions.
             // This all has to be in memory, there are no immediate unsized values.
-            let src = caller_arg.assert_mem_place();
+            let src = caller_arg_copy.assert_mem_place();
             // The destination cannot be one of these "spread args".
             let (dest_frame, dest_local) = callee_arg.assert_local();
             // We are just initializing things, so there can't be anything here yet.
@@ -331,7 +402,12 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         // FIXME: Depending on the PassMode, this should reset some padding to uninitialized. (This
         // is true for all `copy_op`, but there are a lot of special cases for argument passing
         // specifically.)
-        self.copy_op(&caller_arg, callee_arg, /*allow_transmute*/ true)
+        self.copy_op(&caller_arg_copy, callee_arg, /*allow_transmute*/ true)?;
+        // If this was an in-place pass, protect the place it comes from for the duration of the call.
+        if let FnArg::InPlace(place) = caller_arg {
+            M::protect_in_place_function_argument(self, place)?;
+        }
+        Ok(())
     }
 
     /// Call this function -- pushing the stack frame and initializing the arguments.
@@ -346,7 +422,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         &mut self,
         fn_val: FnVal<'tcx, M::ExtraFnVal>,
         (caller_abi, caller_fn_abi): (Abi, &FnAbi<'tcx, Ty<'tcx>>),
-        args: &[OpTy<'tcx, M::Provenance>],
+        args: &[FnArg<'tcx, M::Provenance>],
         with_caller_location: bool,
         destination: &PlaceTy<'tcx, M::Provenance>,
         target: Option<mir::BasicBlock>,
@@ -372,8 +448,15 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         match instance.def {
             ty::InstanceDef::Intrinsic(def_id) => {
                 assert!(self.tcx.is_intrinsic(def_id));
-                // caller_fn_abi is not relevant here, we interpret the arguments directly for each intrinsic.
-                M::call_intrinsic(self, instance, args, destination, target, unwind)
+                // FIXME: Should `InPlace` arguments be reset to uninit?
+                M::call_intrinsic(
+                    self,
+                    instance,
+                    &self.copy_fn_args(args)?,
+                    destination,
+                    target,
+                    unwind,
+                )
             }
             ty::InstanceDef::VTableShim(..)
             | ty::InstanceDef::ReifyShim(..)
@@ -428,7 +511,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                         "caller ABI: {:?}, args: {:#?}",
                         caller_abi,
                         args.iter()
-                            .map(|arg| (arg.layout.ty, format!("{:?}", **arg)))
+                            .map(|arg| (
+                                arg.layout().ty,
+                                match arg {
+                                    FnArg::Copy(op) => format!("copy({:?})", *op),
+                                    FnArg::InPlace(place) => format!("in-place({:?})", *place),
+                                }
+                            ))
                             .collect::<Vec<_>>()
                     );
                     trace!(
@@ -449,7 +538,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                     // last incoming argument. These two iterators do not have the same type,
                     // so to keep the code paths uniform we accept an allocation
                     // (for RustCall ABI only).
-                    let caller_args: Cow<'_, [OpTy<'tcx, M::Provenance>]> =
+                    let caller_args: Cow<'_, [FnArg<'tcx, M::Provenance>]> =
                         if caller_abi == Abi::RustCall && !args.is_empty() {
                             // Untuple
                             let (untuple_arg, args) = args.split_last().unwrap();
@@ -458,11 +547,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                                 args.iter()
                                     .map(|a| Ok(a.clone()))
                                     .chain(
-                                        (0..untuple_arg.layout.fields.count())
-                                            .map(|i| self.operand_field(untuple_arg, i)),
+                                        (0..untuple_arg.layout().fields.count())
+                                            .map(|i| self.fn_arg_field(untuple_arg, i)),
                                     )
-                                    .collect::<InterpResult<'_, Vec<OpTy<'tcx, M::Provenance>>>>(
-                                    )?,
+                                    .collect::<InterpResult<'_, Vec<_>>>()?,
                             )
                         } else {
                             // Plain arg passing
@@ -523,6 +611,14 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                             caller_ty = caller_ty,
                         )
                     }
+                    // Ensure the return place is aligned and dereferenceable, and protect it for
+                    // in-place return value passing.
+                    if let Either::Left(mplace) = destination.as_mplace_or_local() {
+                        self.check_mplace(mplace)?;
+                    } else {
+                        // Nothing to do for locals, they are always properly allocated and aligned.
+                    }
+                    M::protect_in_place_function_argument(self, destination)?;
                 };
                 match res {
                     Err(err) => {
@@ -538,7 +634,10 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 // We have to implement all "object safe receivers". So we have to go search for a
                 // pointer or `dyn Trait` type, but it could be wrapped in newtypes. So recursively
                 // unwrap those newtypes until we are there.
-                let mut receiver = args[0].clone();
+                // An `InPlace` does nothing here, we keep the original receiver intact. We can't
+                // really pass the argument in-place anyway, and we are constructing a new
+                // `Immediate` receiver.
+                let mut receiver = self.copy_fn_arg(&args[0])?;
                 let receiver_place = loop {
                     match receiver.layout.ty.kind() {
                         ty::Ref(..) | ty::RawPtr(..) => {
@@ -648,11 +747,13 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
                 }
 
                 // Adjust receiver argument. Layout can be any (thin) ptr.
-                args[0] = ImmTy::from_immediate(
-                    Scalar::from_maybe_pointer(adjusted_receiver, self).into(),
-                    self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, dyn_ty))?,
-                )
-                .into();
+                args[0] = FnArg::Copy(
+                    ImmTy::from_immediate(
+                        Scalar::from_maybe_pointer(adjusted_receiver, self).into(),
+                        self.layout_of(Ty::new_mut_ptr(self.tcx.tcx, dyn_ty))?,
+                    )
+                    .into(),
+                );
                 trace!("Patched receiver operand to {:#?}", args[0]);
                 // recurse with concrete function
                 self.eval_fn_call(
@@ -710,7 +811,7 @@ impl<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>> InterpCx<'mir, 'tcx, M> {
         self.eval_fn_call(
             FnVal::Instance(instance),
             (Abi::Rust, fn_abi),
-            &[arg.into()],
+            &[FnArg::Copy(arg.into())],
             false,
             &ret.into(),
             Some(target),
diff --git a/compiler/rustc_const_eval/src/interpret/visitor.rs b/compiler/rustc_const_eval/src/interpret/visitor.rs
index 7a14459399c..879ae198f7e 100644
--- a/compiler/rustc_const_eval/src/interpret/visitor.rs
+++ b/compiler/rustc_const_eval/src/interpret/visitor.rs
@@ -13,7 +13,7 @@ use super::{InterpCx, MPlaceTy, Machine, OpTy, PlaceTy};
 /// A thing that we can project into, and that has a layout.
 /// This wouldn't have to depend on `Machine` but with the current type inference,
 /// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
-pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized {
+pub trait Value<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
     /// Gets this value's layout.
     fn layout(&self) -> TyAndLayout<'tcx>;
 
@@ -54,7 +54,7 @@ pub trait Value<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized {
 /// A thing that we can project into given *mutable* access to `ecx`, and that has a layout.
 /// This wouldn't have to depend on `Machine` but with the current type inference,
 /// that's just more convenient to work with (avoids repeating all the `Machine` bounds).
-pub trait ValueMut<'mir, 'tcx, M: Machine<'mir, 'tcx>>: Sized {
+pub trait ValueMut<'mir, 'tcx: 'mir, M: Machine<'mir, 'tcx>>: Sized {
     /// Gets this value's layout.
     fn layout(&self) -> TyAndLayout<'tcx>;
 
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 9352fe3147e..2e26ce111f0 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -1453,13 +1453,13 @@ mod signal_handler {
     /// When an error signal (such as SIGABRT or SIGSEGV) is delivered to the
     /// process, print a stack trace and then exit.
     pub(super) fn install() {
+        use std::alloc::{alloc, Layout};
+
         unsafe {
-            const ALT_STACK_SIZE: usize = libc::MINSIGSTKSZ + 64 * 1024;
+            let alt_stack_size: usize = min_sigstack_size() + 64 * 1024;
             let mut alt_stack: libc::stack_t = std::mem::zeroed();
-            alt_stack.ss_sp =
-                std::alloc::alloc(std::alloc::Layout::from_size_align(ALT_STACK_SIZE, 1).unwrap())
-                    as *mut libc::c_void;
-            alt_stack.ss_size = ALT_STACK_SIZE;
+            alt_stack.ss_sp = alloc(Layout::from_size_align(alt_stack_size, 1).unwrap()).cast();
+            alt_stack.ss_size = alt_stack_size;
             libc::sigaltstack(&alt_stack, std::ptr::null_mut());
 
             let mut sa: libc::sigaction = std::mem::zeroed();
@@ -1469,6 +1469,23 @@ mod signal_handler {
             libc::sigaction(libc::SIGSEGV, &sa, std::ptr::null_mut());
         }
     }
+
+    /// Modern kernels on modern hardware can have dynamic signal stack sizes.
+    #[cfg(any(target_os = "linux", target_os = "android"))]
+    fn min_sigstack_size() -> usize {
+        const AT_MINSIGSTKSZ: core::ffi::c_ulong = 51;
+        let dynamic_sigstksz = unsafe { libc::getauxval(AT_MINSIGSTKSZ) };
+        // If getauxval couldn't find the entry, it returns 0,
+        // so take the higher of the "constant" and auxval.
+        // This transparently supports older kernels which don't provide AT_MINSIGSTKSZ
+        libc::MINSIGSTKSZ.max(dynamic_sigstksz as _)
+    }
+
+    /// Not all OS support hardware where this is needed.
+    #[cfg(not(any(target_os = "linux", target_os = "android")))]
+    fn min_sigstack_size() -> usize {
+        libc::MINSIGSTKSZ
+    }
 }
 
 #[cfg(not(all(unix, any(target_env = "gnu", target_os = "macos"))))]
diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs
index 30bf8c2ad10..3a4eb90f7f9 100644
--- a/compiler/rustc_hir/src/def.rs
+++ b/compiler/rustc_hir/src/def.rs
@@ -109,8 +109,6 @@ pub enum DefKind {
     InlineConst,
     /// Opaque type, aka `impl Trait`.
     OpaqueTy,
-    /// A return-position `impl Trait` in a trait definition
-    ImplTraitPlaceholder,
     Field,
     /// Lifetime parameter: the `'a` in `struct Foo<'a> { ... }`
     LifetimeParam,
@@ -143,7 +141,6 @@ impl DefKind {
             DefKind::Ctor(CtorOf::Struct, CtorKind::Fn) => "tuple struct",
             DefKind::Ctor(CtorOf::Struct, CtorKind::Const) => "unit struct",
             DefKind::OpaqueTy => "opaque type",
-            DefKind::ImplTraitPlaceholder => "opaque type in trait",
             DefKind::TyAlias => "type alias",
             DefKind::TraitAlias => "trait alias",
             DefKind::AssocTy => "associated type",
@@ -227,8 +224,7 @@ impl DefKind {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::GlobalAsm
-            | DefKind::Impl { .. }
-            | DefKind::ImplTraitPlaceholder => None,
+            | DefKind::Impl { .. } => None,
         }
     }
 
@@ -262,7 +258,6 @@ impl DefKind {
             | DefKind::Use
             | DefKind::ForeignMod
             | DefKind::OpaqueTy
-            | DefKind::ImplTraitPlaceholder
             | DefKind::Impl { .. }
             | DefKind::Field
             | DefKind::TyParam
diff --git a/compiler/rustc_hir/src/target.rs b/compiler/rustc_hir/src/target.rs
index 961deac544a..0d65ddb5642 100644
--- a/compiler/rustc_hir/src/target.rs
+++ b/compiler/rustc_hir/src/target.rs
@@ -36,7 +36,6 @@ pub enum Target {
     GlobalAsm,
     TyAlias,
     OpaqueTy,
-    ImplTraitPlaceholder,
     Enum,
     Variant,
     Struct,
@@ -80,13 +79,7 @@ impl Target {
             ItemKind::ForeignMod { .. } => Target::ForeignMod,
             ItemKind::GlobalAsm(..) => Target::GlobalAsm,
             ItemKind::TyAlias(..) => Target::TyAlias,
-            ItemKind::OpaqueTy(ref opaque) => {
-                if opaque.in_trait {
-                    Target::ImplTraitPlaceholder
-                } else {
-                    Target::OpaqueTy
-                }
-            }
+            ItemKind::OpaqueTy(..) => Target::OpaqueTy,
             ItemKind::Enum(..) => Target::Enum,
             ItemKind::Struct(..) => Target::Struct,
             ItemKind::Union(..) => Target::Union,
@@ -110,7 +103,6 @@ impl Target {
             DefKind::GlobalAsm => Target::GlobalAsm,
             DefKind::TyAlias => Target::TyAlias,
             DefKind::OpaqueTy => Target::OpaqueTy,
-            DefKind::ImplTraitPlaceholder => Target::ImplTraitPlaceholder,
             DefKind::Enum => Target::Enum,
             DefKind::Struct => Target::Struct,
             DefKind::Union => Target::Union,
@@ -165,7 +157,6 @@ impl Target {
             Target::GlobalAsm => "global asm",
             Target::TyAlias => "type alias",
             Target::OpaqueTy => "opaque type",
-            Target::ImplTraitPlaceholder => "opaque type in trait",
             Target::Enum => "enum",
             Target::Variant => "enum variant",
             Target::Struct => "struct",
diff --git a/compiler/rustc_hir_analysis/src/astconv/mod.rs b/compiler/rustc_hir_analysis/src/astconv/mod.rs
index 3d698462840..db3d41ed247 100644
--- a/compiler/rustc_hir_analysis/src/astconv/mod.rs
+++ b/compiler/rustc_hir_analysis/src/astconv/mod.rs
@@ -2128,7 +2128,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
 
         let span = path.span;
         match path.res {
-            Res::Def(DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder, did) => {
+            Res::Def(DefKind::OpaqueTy, did) => {
                 // Check for desugared `impl Trait`.
                 assert!(tcx.is_type_alias_impl_trait(did));
                 let item_segment = path.segments.split_last().unwrap();
@@ -2439,7 +2439,7 @@ impl<'o, 'tcx> dyn AstConv<'tcx> + 'o {
                         // If this is an RPITIT and we are using the new RPITIT lowering scheme, we
                         // generate the def_id of an associated type for the trait and return as
                         // type a projection.
-                        let def_id = if in_trait && tcx.lower_impl_trait_in_trait_to_assoc_ty() {
+                        let def_id = if in_trait {
                             tcx.associated_type_for_impl_trait_in_trait(local_def_id).to_def_id()
                         } else {
                             local_def_id.to_def_id()
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 120545c8e5d..91c33b09082 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -302,16 +302,11 @@ pub(super) fn check_opaque_for_inheriting_lifetimes(
 
     if let ItemKind::OpaqueTy(&hir::OpaqueTy {
         origin: hir::OpaqueTyOrigin::AsyncFn(..) | hir::OpaqueTyOrigin::FnReturn(..),
-        in_trait,
         ..
     }) = item.kind
     {
         let substs = InternalSubsts::identity_for_item(tcx, def_id);
-        let opaque_identity_ty = if in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-            Ty::new_projection(tcx, def_id.to_def_id(), substs)
-        } else {
-            Ty::new_opaque(tcx, def_id.to_def_id(), substs)
-        };
+        let opaque_identity_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
         let mut visitor = ProhibitOpaqueVisitor {
             opaque_identity_ty,
             parent_count: tcx.generics_of(def_id).parent_count as u32,
@@ -576,17 +571,6 @@ fn check_item_type(tcx: TyCtxt<'_>, id: hir::ItemId) {
                 check_opaque(tcx, id);
             }
         }
-        DefKind::ImplTraitPlaceholder => {
-            let parent = tcx.impl_trait_in_trait_parent_fn(id.owner_id.to_def_id());
-            // Only check the validity of this opaque type if the function has a default body
-            if let hir::Node::TraitItem(hir::TraitItem {
-                kind: hir::TraitItemKind::Fn(_, hir::TraitFn::Provided(_)),
-                ..
-            }) = tcx.hir().get_by_def_id(parent.expect_local())
-            {
-                check_opaque(tcx, id);
-            }
-        }
         DefKind::TyAlias => {
             let pty_ty = tcx.type_of(id.owner_id).subst_identity();
             let generics = tcx.generics_of(id.owner_id);
diff --git a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
index 57f74172ed0..d6f33869a03 100644
--- a/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
+++ b/compiler/rustc_hir_analysis/src/collect/item_bounds.rs
@@ -113,16 +113,12 @@ pub(super) fn explicit_item_bounds(
             ..
         }) => associated_type_bounds(tcx, def_id, bounds, *span),
         hir::Node::Item(hir::Item {
-            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, in_trait, .. }),
+            kind: hir::ItemKind::OpaqueTy(hir::OpaqueTy { bounds, .. }),
             span,
             ..
         }) => {
             let substs = InternalSubsts::identity_for_item(tcx, def_id);
-            let item_ty = if *in_trait && !tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-                Ty::new_projection(tcx, def_id.to_def_id(), substs)
-            } else {
-                Ty::new_opaque(tcx, def_id.to_def_id(), substs)
-            };
+            let item_ty = Ty::new_opaque(tcx, def_id.to_def_id(), substs);
             opaque_type_bounds(tcx, def_id, bounds, item_ty, *span)
         }
         hir::Node::Item(hir::Item { kind: hir::ItemKind::TyAlias(..), .. }) => &[],
diff --git a/compiler/rustc_hir_analysis/src/impl_wf_check.rs b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
index 5526dd4b007..d654b0be620 100644
--- a/compiler/rustc_hir_analysis/src/impl_wf_check.rs
+++ b/compiler/rustc_hir_analysis/src/impl_wf_check.rs
@@ -109,20 +109,7 @@ fn enforce_impl_params_are_constrained(tcx: TyCtxt<'_>, impl_def_id: LocalDefId)
                         vec![]
                     }
                 }
-                ty::AssocKind::Fn => {
-                    if !tcx.lower_impl_trait_in_trait_to_assoc_ty()
-                        && item.defaultness(tcx).has_value()
-                        && tcx.impl_method_has_trait_impl_trait_tys(item.def_id)
-                        && let Ok(table) = tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
-                    {
-                        table.values().copied().flat_map(|ty| {
-                            cgp::parameters_for(&ty.subst_identity(), true)
-                        }).collect()
-                    } else {
-                        vec![]
-                    }
-                }
-                ty::AssocKind::Const => vec![],
+                ty::AssocKind::Fn | ty::AssocKind::Const => vec![],
             }
         })
         .collect();
diff --git a/compiler/rustc_hir_analysis/src/variance/mod.rs b/compiler/rustc_hir_analysis/src/variance/mod.rs
index 066e7449189..c703cb03515 100644
--- a/compiler/rustc_hir_analysis/src/variance/mod.rs
+++ b/compiler/rustc_hir_analysis/src/variance/mod.rs
@@ -56,7 +56,7 @@ fn variances_of(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Variance] {
             let crate_map = tcx.crate_variances(());
             return crate_map.variances.get(&item_def_id.to_def_id()).copied().unwrap_or(&[]);
         }
-        DefKind::OpaqueTy | DefKind::ImplTraitPlaceholder => {
+        DefKind::OpaqueTy => {
             return variance_of_opaque(tcx, item_def_id);
         }
         _ => {}
@@ -115,14 +115,6 @@ fn variance_of_opaque(tcx: TyCtxt<'_>, item_def_id: LocalDefId) -> &[ty::Varianc
                 {
                     self.visit_opaque(*def_id, substs)
                 }
-                // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty) check whether this is necessary
-                // at all for RPITITs.
-                ty::Alias(_, ty::AliasTy { def_id, substs, .. })
-                    if self.tcx.is_impl_trait_in_trait(*def_id)
-                        && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() =>
-                {
-                    self.visit_opaque(*def_id, substs)
-                }
                 _ => t.super_visit_with(self),
             }
         }
diff --git a/compiler/rustc_hir_typeck/src/lib.rs b/compiler/rustc_hir_typeck/src/lib.rs
index 6f82ffcfe4a..862430f5eb1 100644
--- a/compiler/rustc_hir_typeck/src/lib.rs
+++ b/compiler/rustc_hir_typeck/src/lib.rs
@@ -141,7 +141,7 @@ fn has_typeck_results(tcx: TyCtxt<'_>, def_id: DefId) -> bool {
 }
 
 fn used_trait_imports(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &UnordSet<LocalDefId> {
-    &*tcx.typeck(def_id).used_trait_imports
+    &tcx.typeck(def_id).used_trait_imports
 }
 
 fn typeck<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &ty::TypeckResults<'tcx> {
diff --git a/compiler/rustc_hir_typeck/src/method/mod.rs b/compiler/rustc_hir_typeck/src/method/mod.rs
index e52cea1889f..c59e9e315b1 100644
--- a/compiler/rustc_hir_typeck/src/method/mod.rs
+++ b/compiler/rustc_hir_typeck/src/method/mod.rs
@@ -12,7 +12,6 @@ pub use self::MethodError::*;
 
 use crate::errors::OpMethodGenericParams;
 use crate::FnCtxt;
-use rustc_data_structures::sync::Lrc;
 use rustc_errors::{Applicability, Diagnostic, SubdiagnosticMessage};
 use rustc_hir as hir;
 use rustc_hir::def::{CtorOf, DefKind, Namespace};
@@ -190,11 +189,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         self.lint_dot_call_from_2018(self_ty, segment, span, call_expr, self_expr, &pick, args);
 
-        for import_id in &pick.import_ids {
+        for &import_id in &pick.import_ids {
             debug!("used_trait_import: {:?}", import_id);
-            Lrc::get_mut(&mut self.typeck_results.borrow_mut().used_trait_imports)
-                .unwrap()
-                .insert(*import_id);
+            self.typeck_results.borrow_mut().used_trait_imports.insert(import_id);
         }
 
         self.tcx.check_stability(pick.item.def_id, Some(call_expr.hir_id), span, None);
@@ -567,10 +564,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         debug!(?pick);
         {
             let mut typeck_results = self.typeck_results.borrow_mut();
-            let used_trait_imports = Lrc::get_mut(&mut typeck_results.used_trait_imports).unwrap();
             for import_id in pick.import_ids {
                 debug!(used_trait_import=?import_id);
-                used_trait_imports.insert(import_id);
+                typeck_results.used_trait_imports.insert(import_id);
             }
         }
 
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 42f4531c0ef..69c8cc8c590 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -335,8 +335,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         expected: Ty<'tcx>,
         mut def_bm: BindingMode,
     ) -> (Ty<'tcx>, BindingMode) {
-        let mut expected = self.resolve_vars_with_obligations(expected);
-
+        let mut expected = self.try_structurally_resolve_type(pat.span, expected);
         // Peel off as many `&` or `&mut` from the scrutinee type as possible. For example,
         // for `match &&&mut Some(5)` the loop runs three times, aborting when it reaches
         // the `Some(5)` which is not of type Ref.
@@ -353,7 +352,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             // Preserve the reference type. We'll need it later during THIR lowering.
             pat_adjustments.push(expected);
 
-            expected = inner_ty;
+            expected = self.try_structurally_resolve_type(pat.span, inner_ty);
             def_bm = ty::BindByReference(match def_bm {
                 // If default binding mode is by value, make it `ref` or `ref mut`
                 // (depending on whether we observe `&` or `&mut`).
@@ -627,6 +626,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         local_ty
     }
 
+    /// When a variable is bound several times in a `PatKind::Or`, it'll resolve all of the
+    /// subsequent bindings of the same name to the first usage. Verify that all of these
+    /// bindings have the same type by comparing them all against the type of that first pat.
     fn check_binding_alt_eq_ty(
         &self,
         ba: hir::BindingAnnotation,
@@ -638,7 +640,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let var_ty = self.local_ty(span, var_id);
         if let Some(mut err) = self.demand_eqtype_pat_diag(span, var_ty, ty, ti) {
             let hir = self.tcx.hir();
-            let var_ty = self.resolve_vars_with_obligations(var_ty);
+            let var_ty = self.resolve_vars_if_possible(var_ty);
             let msg = format!("first introduced with type `{var_ty}` here");
             err.span_label(hir.span(var_id), msg);
             let in_match = hir.parent_iter(var_id).any(|(_, n)| {
@@ -656,7 +658,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 &mut err,
                 span,
                 var_ty,
-                self.resolve_vars_with_obligations(ty),
+                self.resolve_vars_if_possible(ty),
                 ba,
             );
             err.emit();
diff --git a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
index bb75ecc6adb..a90a41f5d70 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/need_type_info.rs
@@ -162,10 +162,18 @@ fn fmt_printer<'a, 'tcx>(infcx: &'a InferCtxt<'tcx>, ns: Namespace) -> FmtPrinte
         let mut infcx_inner = infcx.inner.borrow_mut();
         let ty_vars = infcx_inner.type_variables();
         let var_origin = ty_vars.var_origin(ty_vid);
-        if let TypeVariableOriginKind::TypeParameterDefinition(name, _) = var_origin.kind
+        if let TypeVariableOriginKind::TypeParameterDefinition(name, def_id) = var_origin.kind
             && !var_origin.span.from_expansion()
         {
-            Some(name)
+            let generics = infcx.tcx.generics_of(infcx.tcx.parent(def_id));
+            let idx = generics.param_def_id_to_index(infcx.tcx, def_id).unwrap();
+            let generic_param_def = generics.param_at(idx as usize, infcx.tcx);
+            if let ty::GenericParamDefKind::Type { synthetic: true, .. } = generic_param_def.kind
+            {
+                None
+            } else {
+                Some(name)
+            }
         } else {
             None
         }
diff --git a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
index 1422bdc9ea2..b0e7cf23cae 100644
--- a/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
+++ b/compiler/rustc_infer/src/infer/error_reporting/suggest.rs
@@ -464,52 +464,53 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         span: Span,
     ) -> Option<TypeErrorAdditionalDiags> {
         let hir = self.tcx.hir();
-        if let Some(node) = self.tcx.hir().find_by_def_id(cause.body_id) &&
-            let hir::Node::Item(hir::Item {
-                    kind: hir::ItemKind::Fn(_sig, _, body_id), ..
-                }) = node {
-        let body = hir.body(*body_id);
-
-        /// Find the if expression with given span
-        struct IfVisitor {
-            pub result: bool,
-            pub found_if: bool,
-            pub err_span: Span,
-        }
+        if let Some(body_id) = self.tcx.hir().maybe_body_owned_by(cause.body_id) {
+            let body = hir.body(body_id);
+
+            /// Find the if expression with given span
+            struct IfVisitor {
+                pub result: bool,
+                pub found_if: bool,
+                pub err_span: Span,
+            }
 
-        impl<'v> Visitor<'v> for IfVisitor {
-            fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
-                if self.result { return; }
-                match ex.kind {
-                    hir::ExprKind::If(cond, _, _) => {
-                        self.found_if = true;
-                        walk_expr(self, cond);
-                        self.found_if = false;
+            impl<'v> Visitor<'v> for IfVisitor {
+                fn visit_expr(&mut self, ex: &'v hir::Expr<'v>) {
+                    if self.result {
+                        return;
+                    }
+                    match ex.kind {
+                        hir::ExprKind::If(cond, _, _) => {
+                            self.found_if = true;
+                            walk_expr(self, cond);
+                            self.found_if = false;
+                        }
+                        _ => walk_expr(self, ex),
                     }
-                    _ => walk_expr(self, ex),
                 }
-            }
 
-            fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
-                if let hir::StmtKind::Local(hir::Local {
-                        span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
-                    }) = &ex.kind
-                    && self.found_if
-                    && span.eq(&self.err_span) {
-                        self.result = true;
+                fn visit_stmt(&mut self, ex: &'v hir::Stmt<'v>) {
+                    if let hir::StmtKind::Local(hir::Local {
+                                    span, pat: hir::Pat{..}, ty: None, init: Some(_), ..
+                                }) = &ex.kind
+                                && self.found_if
+                                && span.eq(&self.err_span) {
+                                self.result = true;
+                            }
+                    walk_stmt(self, ex);
                 }
-                walk_stmt(self, ex);
-            }
 
-            fn visit_body(&mut self, body: &'v hir::Body<'v>) {
-                hir::intravisit::walk_body(self, body);
+                fn visit_body(&mut self, body: &'v hir::Body<'v>) {
+                    hir::intravisit::walk_body(self, body);
+                }
             }
-        }
 
-        let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
-        visitor.visit_body(&body);
-        if visitor.result {
-                return Some(TypeErrorAdditionalDiags::AddLetForLetChains{span: span.shrink_to_lo()});
+            let mut visitor = IfVisitor { err_span: span, found_if: false, result: false };
+            visitor.visit_body(&body);
+            if visitor.result {
+                return Some(TypeErrorAdditionalDiags::AddLetForLetChains {
+                    span: span.shrink_to_lo(),
+                });
             }
         }
         None
diff --git a/compiler/rustc_infer/src/infer/mod.rs b/compiler/rustc_infer/src/infer/mod.rs
index fca32b73d1d..a123effd0f0 100644
--- a/compiler/rustc_infer/src/infer/mod.rs
+++ b/compiler/rustc_infer/src/infer/mod.rs
@@ -332,6 +332,39 @@ pub struct InferCtxt<'tcx> {
     next_trait_solver: bool,
 }
 
+impl<'tcx> ty::InferCtxtLike<TyCtxt<'tcx>> for InferCtxt<'tcx> {
+    fn universe_of_ty(&self, ty: ty::InferTy) -> Option<ty::UniverseIndex> {
+        use InferTy::*;
+        match ty {
+            // FIXME(BoxyUwU): this is kind of jank and means that printing unresolved
+            // ty infers will give you the universe of the var it resolved to not the universe
+            // it actually had. It also means that if you have a `?0.1` and infer it to `u8` then
+            // try to print out `?0.1` it will just print `?0`.
+            TyVar(ty_vid) => match self.probe_ty_var(ty_vid) {
+                Err(universe) => Some(universe),
+                Ok(_) => None,
+            },
+            IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => None,
+        }
+    }
+
+    fn universe_of_ct(&self, ct: ty::InferConst<'tcx>) -> Option<ty::UniverseIndex> {
+        use ty::InferConst::*;
+        match ct {
+            // Same issue as with `universe_of_ty`
+            Var(ct_vid) => match self.probe_const_var(ct_vid) {
+                Err(universe) => Some(universe),
+                Ok(_) => None,
+            },
+            Fresh(_) => None,
+        }
+    }
+
+    fn universe_of_lt(&self, lt: ty::RegionVid) -> Option<ty::UniverseIndex> {
+        Some(self.universe_of_region_vid(lt))
+    }
+}
+
 /// See the `error_reporting` module for more details.
 #[derive(Clone, Copy, Debug, PartialEq, Eq, TypeFoldable, TypeVisitable)]
 pub enum ValuePairs<'tcx> {
@@ -1068,6 +1101,11 @@ impl<'tcx> InferCtxt<'tcx> {
         self.inner.borrow_mut().unwrap_region_constraints().universe(r)
     }
 
+    /// Return the universe that the region variable `r` was created in.
+    pub fn universe_of_region_vid(&self, vid: ty::RegionVid) -> ty::UniverseIndex {
+        self.inner.borrow_mut().unwrap_region_constraints().var_universe(vid)
+    }
+
     /// Number of region variables created so far.
     pub fn num_region_vars(&self) -> usize {
         self.inner.borrow_mut().unwrap_region_constraints().num_region_vars()
diff --git a/compiler/rustc_lint/messages.ftl b/compiler/rustc_lint/messages.ftl
index 34b7e09576a..2c92277b50d 100644
--- a/compiler/rustc_lint/messages.ftl
+++ b/compiler/rustc_lint/messages.ftl
@@ -215,6 +215,9 @@ lint_expectation = this lint expectation is unfulfilled
     .note = the `unfulfilled_lint_expectations` lint can't be expected and will always produce this message
     .rationale = {$rationale}
 
+lint_fn_null_check = function pointers are not nullable, so checking them for null will always return false
+    .help = wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
 lint_for_loops_over_fallibles =
     for loop over {$article} `{$ty}`. This is more readably written as an `if let` statement
     .suggestion = consider using `if let` to clear intent
diff --git a/compiler/rustc_lint/src/fn_null_check.rs b/compiler/rustc_lint/src/fn_null_check.rs
new file mode 100644
index 00000000000..e3b33463ccf
--- /dev/null
+++ b/compiler/rustc_lint/src/fn_null_check.rs
@@ -0,0 +1,112 @@
+use crate::{lints::FnNullCheckDiag, LateContext, LateLintPass, LintContext};
+use rustc_ast::LitKind;
+use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
+use rustc_session::{declare_lint, declare_lint_pass};
+use rustc_span::sym;
+
+declare_lint! {
+    /// The `incorrect_fn_null_checks` lint checks for expression that checks if a
+    /// function pointer is null.
+    ///
+    /// ### Example
+    ///
+    /// ```rust
+    /// # fn test() {}
+    /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
+    /// #   test;
+    ///
+    /// if (fn_ptr as *const ()).is_null() { /* ... */ }
+    /// ```
+    ///
+    /// {{produces}}
+    ///
+    /// ### Explanation
+    ///
+    /// Function pointers are assumed to be non-null, checking them for null will always
+    /// return false.
+    INCORRECT_FN_NULL_CHECKS,
+    Warn,
+    "incorrect checking of null function pointer"
+}
+
+declare_lint_pass!(IncorrectFnNullChecks => [INCORRECT_FN_NULL_CHECKS]);
+
+fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
+    let mut expr = expr.peel_blocks();
+    let mut had_at_least_one_cast = false;
+    while let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
+            && let TyKind::Ptr(_) = cast_ty.kind {
+        expr = cast_expr.peel_blocks();
+        had_at_least_one_cast = true;
+    }
+    had_at_least_one_cast && cx.typeck_results().expr_ty_adjusted(expr).is_fn()
+}
+
+impl<'tcx> LateLintPass<'tcx> for IncorrectFnNullChecks {
+    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
+        match expr.kind {
+            // Catching:
+            // <*<const/mut> <ty>>::is_null(fn_ptr as *<const/mut> <ty>)
+            ExprKind::Call(path, [arg])
+                if let ExprKind::Path(ref qpath) = path.kind
+                    && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                    && matches!(
+                        cx.tcx.get_diagnostic_name(def_id),
+                        Some(sym::ptr_const_is_null | sym::ptr_is_null)
+                    )
+                    && is_fn_ptr_cast(cx, arg) =>
+            {
+                cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
+            }
+
+            // Catching:
+            // (fn_ptr as *<const/mut> <ty>).is_null()
+            ExprKind::MethodCall(_, receiver, _, _)
+                if let Some(def_id) = cx.typeck_results().type_dependent_def_id(expr.hir_id)
+                    && matches!(
+                        cx.tcx.get_diagnostic_name(def_id),
+                        Some(sym::ptr_const_is_null | sym::ptr_is_null)
+                    )
+                    && is_fn_ptr_cast(cx, receiver) =>
+            {
+                cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
+            }
+
+            ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
+                let to_check: &Expr<'_>;
+                if is_fn_ptr_cast(cx, left) {
+                    to_check = right;
+                } else if is_fn_ptr_cast(cx, right) {
+                    to_check = left;
+                } else {
+                    return;
+                }
+
+                match to_check.kind {
+                    // Catching:
+                    // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
+                    ExprKind::Cast(cast_expr, _)
+                        if let ExprKind::Lit(spanned) = cast_expr.kind
+                            && let LitKind::Int(v, _) = spanned.node && v == 0 =>
+                    {
+                        cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
+                    },
+
+                    // Catching:
+                    // (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
+                    ExprKind::Call(path, [])
+                        if let ExprKind::Path(ref qpath) = path.kind
+                            && let Some(def_id) = cx.qpath_res(qpath, path.hir_id).opt_def_id()
+                            && let Some(diag_item) = cx.tcx.get_diagnostic_name(def_id)
+                            && (diag_item == sym::ptr_null || diag_item == sym::ptr_null_mut) =>
+                    {
+                        cx.emit_spanned_lint(INCORRECT_FN_NULL_CHECKS, expr.span, FnNullCheckDiag)
+                    },
+
+                    _ => {},
+                }
+            }
+            _ => {}
+        }
+    }
+}
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 5e3f057d428..beb38dbb94c 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -58,6 +58,7 @@ mod early;
 mod enum_intrinsics_non_enums;
 mod errors;
 mod expect;
+mod fn_null_check;
 mod for_loops_over_fallibles;
 pub mod hidden_unicode_codepoints;
 mod internal;
@@ -102,6 +103,7 @@ use cast_ref_to_mut::*;
 use deref_into_dyn_supertrait::*;
 use drop_forget_useless::*;
 use enum_intrinsics_non_enums::EnumIntrinsicsNonEnums;
+use fn_null_check::*;
 use for_loops_over_fallibles::*;
 use hidden_unicode_codepoints::*;
 use internal::*;
@@ -225,6 +227,7 @@ late_lint_methods!(
             // Depends on types used in type definitions
             MissingCopyImplementations: MissingCopyImplementations,
             // Depends on referenced function signatures in expressions
+            IncorrectFnNullChecks: IncorrectFnNullChecks,
             MutableTransmutes: MutableTransmutes,
             TypeAliasBounds: TypeAliasBounds,
             TrivialConstraints: TrivialConstraints,
diff --git a/compiler/rustc_lint/src/lints.rs b/compiler/rustc_lint/src/lints.rs
index 0613ef2c5e9..1dea758bb29 100644
--- a/compiler/rustc_lint/src/lints.rs
+++ b/compiler/rustc_lint/src/lints.rs
@@ -613,6 +613,12 @@ pub struct ExpectationNote {
     pub rationale: Symbol,
 }
 
+// fn_null_check.rs
+#[derive(LintDiagnostic)]
+#[diag(lint_fn_null_check)]
+#[help]
+pub struct FnNullCheckDiag;
+
 // for_loops_over_fallibles.rs
 #[derive(LintDiagnostic)]
 #[diag(lint_for_loops_over_fallibles)]
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index 87c542dc2e2..a0f2e9aed81 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -4084,7 +4084,7 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// The preferred location for where clauses on associated types in impls
+    /// The preferred location for where clauses on associated types
     /// is after the type. However, for most of generic associated types development,
     /// it was only accepted before the equals. To provide a transition period and
     /// further evaluate this change, both are currently accepted. At some point in
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index bb7510b3a53..ab5fa961b95 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -1616,17 +1616,6 @@ extern "C" void LLVMRustSetLinkage(LLVMValueRef V,
   LLVMSetLinkage(V, fromRust(RustLinkage));
 }
 
-// FIXME: replace with LLVMConstInBoundsGEP2 when bumped minimal version to llvm-14
-extern "C" LLVMValueRef LLVMRustConstInBoundsGEP2(LLVMTypeRef Ty,
-                                                  LLVMValueRef ConstantVal,
-                                                  LLVMValueRef *ConstantIndices,
-                                                  unsigned NumIndices) {
-  ArrayRef<Constant *> IdxList(unwrap<Constant>(ConstantIndices, NumIndices),
-                               NumIndices);
-  Constant *Val = unwrap<Constant>(ConstantVal);
-  return wrap(ConstantExpr::getInBoundsGetElementPtr(unwrap(Ty), Val, IdxList));
-}
-
 extern "C" bool LLVMRustConstIntGetZExtValue(LLVMValueRef CV, uint64_t *value) {
     auto C = unwrap<llvm::ConstantInt>(CV);
     if (C->getBitWidth() > 64)
diff --git a/compiler/rustc_metadata/src/rmeta/encoder.rs b/compiler/rustc_metadata/src/rmeta/encoder.rs
index 541c19c3561..01dd35b0e5b 100644
--- a/compiler/rustc_metadata/src/rmeta/encoder.rs
+++ b/compiler/rustc_metadata/src/rmeta/encoder.rs
@@ -824,7 +824,6 @@ fn should_encode_span(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::Impl { .. }
         | DefKind::Closure
@@ -867,7 +866,6 @@ fn should_encode_attrs(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
         | DefKind::Generator => false,
@@ -902,7 +900,6 @@ fn should_encode_expn_that_defined(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
@@ -939,7 +936,6 @@ fn should_encode_visibility(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::GlobalAsm
         | DefKind::Impl { .. }
         | DefKind::Closure
@@ -966,7 +962,6 @@ fn should_encode_stability(def_kind: DefKind) -> bool {
         | DefKind::ForeignMod
         | DefKind::TyAlias
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Enum
         | DefKind::Union
         | DefKind::Impl { .. }
@@ -1033,7 +1028,6 @@ fn should_encode_variances(def_kind: DefKind) -> bool {
         | DefKind::Enum
         | DefKind::Variant
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Fn
         | DefKind::Ctor(..)
         | DefKind::AssocFn => true,
@@ -1083,7 +1077,6 @@ fn should_encode_generics(def_kind: DefKind) -> bool {
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Impl { .. }
         | DefKind::Field
         | DefKind::TyParam
@@ -1134,19 +1127,6 @@ fn should_encode_type(tcx: TyCtxt<'_>, def_id: LocalDefId, def_kind: DefKind) ->
             }
         }
 
-        DefKind::ImplTraitPlaceholder => {
-            let parent_def_id = tcx.impl_trait_in_trait_parent_fn(def_id.to_def_id());
-            let assoc_item = tcx.associated_item(parent_def_id);
-            match assoc_item.container {
-                // Always encode an RPIT in an impl fn, since it always has a body
-                ty::AssocItemContainer::ImplContainer => true,
-                ty::AssocItemContainer::TraitContainer => {
-                    // Encode an RPIT for a trait only if the trait has a default body
-                    assoc_item.defaultness(tcx).has_value()
-                }
-            }
-        }
-
         DefKind::AssocTy => {
             let assoc_item = tcx.associated_item(def_id);
             match assoc_item.container {
@@ -1192,7 +1172,6 @@ fn should_encode_fn_sig(def_kind: DefKind) -> bool {
         | DefKind::Ctor(..)
         | DefKind::TyAlias
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
         | DefKind::Impl { .. }
         | DefKind::AssocConst
@@ -1235,7 +1214,6 @@ fn should_encode_constness(def_kind: DefKind) -> bool {
         | DefKind::TyAlias
         | DefKind::OpaqueTy
         | DefKind::Impl { of_trait: false }
-        | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
         | DefKind::Generator
         | DefKind::ConstParam
@@ -1268,7 +1246,6 @@ fn should_encode_const(def_kind: DefKind) -> bool {
         | DefKind::Static(..)
         | DefKind::TyAlias
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::ForeignTy
         | DefKind::Impl { .. }
         | DefKind::AssocFn
@@ -1289,11 +1266,8 @@ fn should_encode_const(def_kind: DefKind) -> bool {
     }
 }
 
-// We only encode impl trait in trait when using `lower-impl-trait-in-trait-to-assoc-ty` unstable
-// option.
 fn should_encode_fn_impl_trait_in_trait<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> bool {
-    if tcx.lower_impl_trait_in_trait_to_assoc_ty()
-        && let Some(assoc_item) = tcx.opt_associated_item(def_id)
+    if let Some(assoc_item) = tcx.opt_associated_item(def_id)
         && assoc_item.container == ty::AssocItemContainer::TraitContainer
         && assoc_item.kind == ty::AssocKind::Fn
     {
@@ -1447,9 +1421,6 @@ impl<'a, 'tcx> EncodeContext<'a, 'tcx> {
                     .is_type_alias_impl_trait
                     .set(def_id.index, self.tcx.is_type_alias_impl_trait(def_id));
             }
-            if let DefKind::ImplTraitPlaceholder = def_kind {
-                self.encode_explicit_item_bounds(def_id);
-            }
             if tcx.impl_method_has_trait_impl_trait_tys(def_id)
                 && let Ok(table) = self.tcx.collect_return_position_impl_trait_in_trait_tys(def_id)
             {
diff --git a/compiler/rustc_metadata/src/rmeta/table.rs b/compiler/rustc_metadata/src/rmeta/table.rs
index f002d7f97b9..a4313d79ab1 100644
--- a/compiler/rustc_metadata/src/rmeta/table.rs
+++ b/compiler/rustc_metadata/src/rmeta/table.rs
@@ -142,7 +142,6 @@ fixed_size_enum! {
         ( AnonConst                                )
         ( InlineConst                              )
         ( OpaqueTy                                 )
-        ( ImplTraitPlaceholder                     )
         ( Field                                    )
         ( LifetimeParam                            )
         ( GlobalAsm                                )
diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs
index 5f2eb890c4e..6bb8e632dbe 100644
--- a/compiler/rustc_middle/src/hir/map/mod.rs
+++ b/compiler/rustc_middle/src/hir/map/mod.rs
@@ -195,13 +195,7 @@ impl<'hir> Map<'hir> {
                 ItemKind::Fn(..) => DefKind::Fn,
                 ItemKind::Macro(_, macro_kind) => DefKind::Macro(macro_kind),
                 ItemKind::Mod(..) => DefKind::Mod,
-                ItemKind::OpaqueTy(ref opaque) => {
-                    if opaque.in_trait && !self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-                        DefKind::ImplTraitPlaceholder
-                    } else {
-                        DefKind::OpaqueTy
-                    }
-                }
+                ItemKind::OpaqueTy(..) => DefKind::OpaqueTy,
                 ItemKind::TyAlias(..) => DefKind::TyAlias,
                 ItemKind::Enum(..) => DefKind::Enum,
                 ItemKind::Struct(..) => DefKind::Struct,
diff --git a/compiler/rustc_middle/src/mir/syntax.rs b/compiler/rustc_middle/src/mir/syntax.rs
index 7f1d3820341..8c8efc36a2f 100644
--- a/compiler/rustc_middle/src/mir/syntax.rs
+++ b/compiler/rustc_middle/src/mir/syntax.rs
@@ -1050,10 +1050,6 @@ pub type PlaceElem<'tcx> = ProjectionElem<Local, Ty<'tcx>>;
 /// there may be other effects: if the type has a validity constraint loading the place might be UB
 /// if the validity constraint is not met.
 ///
-/// **Needs clarification:** Ralf proposes that loading a place not have side-effects.
-/// This is what is implemented in miri today. Are these the semantics we want for MIR? Is this
-/// something we can even decide without knowing more about Rust's memory model?
-///
 /// **Needs clarification:** Is loading a place that has its variant index set well-formed? Miri
 /// currently implements it, but it seems like this may be something to check against in the
 /// validator.
@@ -1071,6 +1067,16 @@ pub enum Operand<'tcx> {
     /// in [UCG#188]. You should not emit MIR that may attempt a subsequent second load of this
     /// place without first re-initializing it.
     ///
+    /// **Needs clarification:** The operational impact of `Move` is unclear. Currently (both in
+    /// Miri and codegen) it has no effect at all unless it appears in an argument to `Call`; for
+    /// `Call` it allows the argument to be passed to the callee "in-place", i.e. the callee might
+    /// just get a reference to this place instead of a full copy. Miri implements this with a
+    /// combination of aliasing model "protectors" and putting `uninit` into the place. Ralf
+    /// proposes that we don't want these semantics for `Move` in regular assignments, because
+    /// loading a place should not have side-effects, and the aliasing model "protectors" are
+    /// inherently tied to a function call. Are these the semantics we want for MIR? Is this
+    /// something we can even decide without knowing more about Rust's memory model?
+    ///
     /// [UCG#188]: https://github.com/rust-lang/unsafe-code-guidelines/issues/188
     Move(Place<'tcx>),
 
diff --git a/compiler/rustc_middle/src/ty/consts/kind.rs b/compiler/rustc_middle/src/ty/consts/kind.rs
index a6bf7491118..5f2b6d42bf8 100644
--- a/compiler/rustc_middle/src/ty/consts/kind.rs
+++ b/compiler/rustc_middle/src/ty/consts/kind.rs
@@ -8,7 +8,7 @@ use rustc_hir::def_id::DefId;
 use rustc_macros::HashStable;
 
 /// An unevaluated (potentially generic) constant used in the type-system.
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, TyEncodable, TyDecodable, Lift)]
 #[derive(Hash, HashStable, TypeFoldable, TypeVisitable)]
 pub struct UnevaluatedConst<'tcx> {
     pub def: DefId,
@@ -35,7 +35,7 @@ impl<'tcx> UnevaluatedConst<'tcx> {
     }
 }
 
-#[derive(Copy, Clone, Debug, Eq, PartialEq, PartialOrd, Ord, Hash)]
+#[derive(Copy, Clone, Eq, PartialEq, PartialOrd, Ord, Hash)]
 #[derive(HashStable, TyEncodable, TyDecodable, TypeVisitable, TypeFoldable)]
 pub enum Expr<'tcx> {
     Binop(mir::BinOp, Const<'tcx>, Const<'tcx>),
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index 035e978f64c..6990fbbb634 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -1036,7 +1036,9 @@ impl<'tcx> TyCtxt<'tcx> {
         scope_def_id: LocalDefId,
     ) -> Vec<&'tcx hir::Ty<'tcx>> {
         let hir_id = self.hir().local_def_id_to_hir_id(scope_def_id);
-        let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) = self.hir().fn_decl_by_hir_id(hir_id) else {
+        let Some(hir::FnDecl { output: hir::FnRetTy::Return(hir_output), .. }) =
+            self.hir().fn_decl_by_hir_id(hir_id)
+        else {
             return vec![];
         };
 
@@ -2002,16 +2004,8 @@ impl<'tcx> TyCtxt<'tcx> {
         )
     }
 
-    pub fn lower_impl_trait_in_trait_to_assoc_ty(self) -> bool {
-        self.sess.opts.unstable_opts.lower_impl_trait_in_trait_to_assoc_ty
-    }
-
     pub fn is_impl_trait_in_trait(self, def_id: DefId) -> bool {
-        if self.lower_impl_trait_in_trait_to_assoc_ty() {
-            self.opt_rpitit_info(def_id).is_some()
-        } else {
-            self.def_kind(def_id) == DefKind::ImplTraitPlaceholder
-        }
+        self.opt_rpitit_info(def_id).is_some()
     }
 
     /// Named module children from all kinds of items, including imports.
diff --git a/compiler/rustc_middle/src/ty/list.rs b/compiler/rustc_middle/src/ty/list.rs
index 71911a5a618..7a32cfb1085 100644
--- a/compiler/rustc_middle/src/ty/list.rs
+++ b/compiler/rustc_middle/src/ty/list.rs
@@ -1,6 +1,7 @@
 use crate::arena::Arena;
 use rustc_data_structures::aligned::{align_of, Aligned};
 use rustc_serialize::{Encodable, Encoder};
+use rustc_type_ir::{InferCtxtLike, OptWithInfcx};
 use std::alloc::Layout;
 use std::cmp::Ordering;
 use std::fmt;
@@ -119,6 +120,14 @@ impl<T: fmt::Debug> fmt::Debug for List<T> {
         (**self).fmt(f)
     }
 }
+impl<'tcx, T: super::DebugWithInfcx<TyCtxt<'tcx>>> super::DebugWithInfcx<TyCtxt<'tcx>> for List<T> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        fmt::Debug::fmt(&this.map(|this| this.as_slice()), f)
+    }
+}
 
 impl<S: Encoder, T: Encodable<S>> Encodable<S> for List<T> {
     #[inline]
@@ -202,6 +211,8 @@ unsafe impl<T: Sync> Sync for List<T> {}
 // We need this since `List` uses extern type `OpaqueListContents`.
 #[cfg(parallel_compiler)]
 use rustc_data_structures::sync::DynSync;
+
+use super::TyCtxt;
 #[cfg(parallel_compiler)]
 unsafe impl<T: DynSync> DynSync for List<T> {}
 
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index aa8bfd3178c..519bdb01623 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -53,6 +53,7 @@ use rustc_span::symbol::{kw, sym, Ident, Symbol};
 use rustc_span::{ExpnId, ExpnKind, Span};
 use rustc_target::abi::{Align, FieldIdx, Integer, IntegerType, VariantIdx};
 pub use rustc_target::abi::{ReprFlags, ReprOptions};
+pub use rustc_type_ir::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
 pub use subst::*;
 pub use vtable::*;
 
@@ -2688,7 +2689,6 @@ impl<'tcx> TyCtxt<'tcx> {
             | Some(ImplTraitInTraitData::Impl { fn_def_id, .. }) => fn_def_id,
             None => {
                 while let def_kind = self.def_kind(def_id) && def_kind != DefKind::AssocFn {
-                    debug_assert_eq!(def_kind, DefKind::ImplTraitPlaceholder);
                     def_id = self.parent(def_id);
                 }
                 def_id
@@ -2720,26 +2720,9 @@ impl<'tcx> TyCtxt<'tcx> {
 
         let Some(trait_item_def_id) = item.trait_item_def_id else { return false; };
 
-        if self.lower_impl_trait_in_trait_to_assoc_ty() {
-            return !self
-                .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
-                .is_empty();
-        }
-
-        // FIXME(RPITIT): This does a somewhat manual walk through the signature
-        // of the trait fn to look for any RPITITs, but that's kinda doing a lot
-        // of work. We can probably remove this when we refactor RPITITs to be
-        // associated types.
-        self.fn_sig(trait_item_def_id).subst_identity().skip_binder().output().walk().any(|arg| {
-            if let ty::GenericArgKind::Type(ty) = arg.unpack()
-                && let ty::Alias(ty::Projection, data) = ty.kind()
-                && self.def_kind(data.def_id) == DefKind::ImplTraitPlaceholder
-            {
-                true
-            } else {
-                false
-            }
-        })
+        return !self
+            .associated_types_for_impl_traits_in_associated_fn(trait_item_def_id)
+            .is_empty();
     }
 }
 
diff --git a/compiler/rustc_middle/src/ty/relate.rs b/compiler/rustc_middle/src/ty/relate.rs
index 5741832c980..54dedf31d9f 100644
--- a/compiler/rustc_middle/src/ty/relate.rs
+++ b/compiler/rustc_middle/src/ty/relate.rs
@@ -567,15 +567,9 @@ pub fn structurally_relate_tys<'tcx, R: TypeRelation<'tcx>>(
 
         // Alias tend to mostly already be handled downstream due to normalization.
         (&ty::Alias(a_kind, a_data), &ty::Alias(b_kind, b_data)) => {
-            // FIXME(-Zlower-impl-trait-in-trait-to-assoc-ty): This if can be removed
-            // and the assert uncommented once the new desugaring is stable.
-            if a_kind == b_kind {
-                let alias_ty = relation.relate(a_data, b_data)?;
-                // assert_eq!(a_kind, b_kind);
-                Ok(Ty::new_alias(tcx, a_kind, alias_ty))
-            } else {
-                Err(TypeError::Sorts(expected_found(relation, a, b)))
-            }
+            let alias_ty = relation.relate(a_data, b_data)?;
+            assert_eq!(a_kind, b_kind);
+            Ok(Ty::new_alias(tcx, a_kind, alias_ty))
         }
 
         _ => Err(TypeError::Sorts(expected_found(relation, a, b))),
diff --git a/compiler/rustc_middle/src/ty/structural_impls.rs b/compiler/rustc_middle/src/ty/structural_impls.rs
index 7220d133f68..c82ce9112fc 100644
--- a/compiler/rustc_middle/src/ty/structural_impls.rs
+++ b/compiler/rustc_middle/src/ty/structural_impls.rs
@@ -11,13 +11,15 @@ use crate::ty::{self, AliasTy, InferConst, Lift, Term, TermKind, Ty, TyCtxt};
 use rustc_hir::def::Namespace;
 use rustc_index::{Idx, IndexVec};
 use rustc_target::abi::TyAndLayout;
-use rustc_type_ir::ConstKind;
+use rustc_type_ir::{ConstKind, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
 
-use std::fmt;
+use std::fmt::{self, Debug};
 use std::ops::ControlFlow;
 use std::rc::Rc;
 use std::sync::Arc;
 
+use super::{GenericArg, GenericArgKind, Region};
+
 impl fmt::Debug for ty::TraitDef {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         ty::tls::with(|tcx| {
@@ -89,7 +91,16 @@ impl fmt::Debug for ty::FreeRegion {
 
 impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = self;
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::FnSig<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        let sig = this.data;
+        let ty::FnSig { inputs_and_output: _, c_variadic, unsafety, abi } = sig;
 
         write!(f, "{}", unsafety.prefix_str())?;
         match abi {
@@ -98,15 +109,15 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
         };
 
         write!(f, "fn(")?;
-        let inputs = self.inputs();
+        let inputs = sig.inputs();
         match inputs.len() {
             0 if *c_variadic => write!(f, "...)")?,
             0 => write!(f, ")")?,
             _ => {
-                for ty in &self.inputs()[0..(self.inputs().len() - 1)] {
-                    write!(f, "{ty:?}, ")?;
+                for ty in &sig.inputs()[0..(sig.inputs().len() - 1)] {
+                    write!(f, "{:?}, ", &this.wrap(ty))?;
                 }
-                write!(f, "{:?}", self.inputs().last().unwrap())?;
+                write!(f, "{:?}", &this.wrap(sig.inputs().last().unwrap()))?;
                 if *c_variadic {
                     write!(f, "...")?;
                 }
@@ -114,9 +125,9 @@ impl<'tcx> fmt::Debug for ty::FnSig<'tcx> {
             }
         }
 
-        match self.output().kind() {
+        match sig.output().kind() {
             ty::Tuple(list) if list.is_empty() => Ok(()),
-            _ => write!(f, " -> {:?}", self.output()),
+            _ => write!(f, " -> {:?}", &this.wrap(sig.output())),
         }
     }
 }
@@ -133,6 +144,14 @@ impl<'tcx> fmt::Debug for ty::TraitRef<'tcx> {
     }
 }
 
+impl<'tcx> ty::DebugWithInfcx<TyCtxt<'tcx>> for Ty<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        this.data.fmt(f)
+    }
+}
 impl<'tcx> fmt::Debug for Ty<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         with_no_trimmed_paths!(fmt::Display::fmt(self, f))
@@ -217,9 +236,17 @@ impl<'tcx> fmt::Debug for ty::PredicateKind<'tcx> {
 
 impl<'tcx> fmt::Debug for AliasTy<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for AliasTy<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
         f.debug_struct("AliasTy")
-            .field("substs", &self.substs)
-            .field("def_id", &self.def_id)
+            .field("substs", &this.map(|data| data.substs))
+            .field("def_id", &this.data.def_id)
             .finish()
     }
 }
@@ -232,13 +259,93 @@ impl<'tcx> fmt::Debug for ty::InferConst<'tcx> {
         }
     }
 }
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::InferConst<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        use ty::InferConst::*;
+        match this.infcx.and_then(|infcx| infcx.universe_of_ct(*this.data)) {
+            None => write!(f, "{:?}", this.data),
+            Some(universe) => match *this.data {
+                Var(vid) => write!(f, "?{}_{}c", vid.index, universe.index()),
+                Fresh(_) => {
+                    unreachable!()
+                }
+            },
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::consts::Expr<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::consts::Expr<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.data {
+            ty::Expr::Binop(op, lhs, rhs) => {
+                write!(f, "({op:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
+            }
+            ty::Expr::UnOp(op, rhs) => write!(f, "({op:?}: {:?})", &this.wrap(rhs)),
+            ty::Expr::FunctionCall(func, args) => {
+                write!(f, "{:?}(", &this.wrap(func))?;
+                for arg in args.as_slice().iter().rev().skip(1).rev() {
+                    write!(f, "{:?}, ", &this.wrap(arg))?;
+                }
+                if let Some(arg) = args.last() {
+                    write!(f, "{:?}", &this.wrap(arg))?;
+                }
+
+                write!(f, ")")
+            }
+            ty::Expr::Cast(cast_kind, lhs, rhs) => {
+                write!(f, "({cast_kind:?}: {:?}, {:?})", &this.wrap(lhs), &this.wrap(rhs))
+            }
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for ty::UnevaluatedConst<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::UnevaluatedConst<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        f.debug_struct("UnevaluatedConst")
+            .field("def", &this.data.def)
+            .field("substs", &this.wrap(this.data.substs))
+            .finish()
+    }
+}
 
 impl<'tcx> fmt::Debug for ty::Const<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::Const<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
         // This reflects what `Const` looked liked before `Interned` was
         // introduced. We print it like this to avoid having to update expected
         // output in a lot of tests.
-        write!(f, "Const {{ ty: {:?}, kind: {:?} }}", self.ty(), self.kind())
+        write!(
+            f,
+            "Const {{ ty: {:?}, kind: {:?} }}",
+            &this.map(|data| data.ty()),
+            &this.map(|data| data.kind())
+        )
     }
 }
 
@@ -261,6 +368,66 @@ impl<T: fmt::Debug> fmt::Debug for ty::Placeholder<T> {
     }
 }
 
+impl<'tcx> fmt::Debug for GenericArg<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        match self.unpack() {
+            GenericArgKind::Lifetime(lt) => lt.fmt(f),
+            GenericArgKind::Type(ty) => ty.fmt(f),
+            GenericArgKind::Const(ct) => ct.fmt(f),
+        }
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for GenericArg<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.data.unpack() {
+            GenericArgKind::Lifetime(lt) => write!(f, "{:?}", &this.wrap(lt)),
+            GenericArgKind::Const(ct) => write!(f, "{:?}", &this.wrap(ct)),
+            GenericArgKind::Type(ty) => write!(f, "{:?}", &this.wrap(ty)),
+        }
+    }
+}
+
+impl<'tcx> fmt::Debug for Region<'tcx> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        write!(f, "{:?}", self.kind())
+    }
+}
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for Region<'tcx> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        write!(f, "{:?}", &this.map(|data| data.kind()))
+    }
+}
+
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ty::RegionVid {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.infcx.and_then(|infcx| infcx.universe_of_lt(*this.data)) {
+            Some(universe) => write!(f, "'?{}_{}", this.data.index(), universe.index()),
+            None => write!(f, "{:?}", this.data),
+        }
+    }
+}
+
+impl<'tcx, T: DebugWithInfcx<TyCtxt<'tcx>>> DebugWithInfcx<TyCtxt<'tcx>> for ty::Binder<'tcx, T> {
+    fn fmt<InfCtx: InferCtxtLike<TyCtxt<'tcx>>>(
+        this: OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        f.debug_tuple("Binder")
+            .field(&this.map(|data| data.as_ref().skip_binder()))
+            .field(&this.data.bound_vars())
+            .finish()
+    }
+}
+
 ///////////////////////////////////////////////////////////////////////////
 // Atomic structs
 //
diff --git a/compiler/rustc_middle/src/ty/sty.rs b/compiler/rustc_middle/src/ty/sty.rs
index 94746fbdc19..9f4515b95e7 100644
--- a/compiler/rustc_middle/src/ty/sty.rs
+++ b/compiler/rustc_middle/src/ty/sty.rs
@@ -35,9 +35,12 @@ use std::ops::{ControlFlow, Deref, Range};
 use ty::util::IntTypeExt;
 
 use rustc_type_ir::sty::TyKind::*;
+use rustc_type_ir::CollectAndApply;
+use rustc_type_ir::ConstKind as IrConstKind;
+use rustc_type_ir::DebugWithInfcx;
+use rustc_type_ir::DynKind;
+use rustc_type_ir::RegionKind as IrRegionKind;
 use rustc_type_ir::TyKind as IrTyKind;
-use rustc_type_ir::{CollectAndApply, ConstKind as IrConstKind};
-use rustc_type_ir::{DynKind, RegionKind as IrRegionKind};
 
 use super::GenericParamDefKind;
 
@@ -694,6 +697,15 @@ pub enum ExistentialPredicate<'tcx> {
     AutoTrait(DefId),
 }
 
+impl<'tcx> DebugWithInfcx<TyCtxt<'tcx>> for ExistentialPredicate<'tcx> {
+    fn fmt<InfCtx: rustc_type_ir::InferCtxtLike<TyCtxt<'tcx>>>(
+        this: rustc_type_ir::OptWithInfcx<'_, TyCtxt<'tcx>, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        fmt::Debug::fmt(&this.data, f)
+    }
+}
+
 impl<'tcx> ExistentialPredicate<'tcx> {
     /// Compares via an ordering that will not change if modules are reordered or other changes are
     /// made to the tree. In particular, this ordering is preserved across incremental compilations.
@@ -1237,7 +1249,7 @@ impl<'tcx> AliasTy<'tcx> {
     pub fn kind(self, tcx: TyCtxt<'tcx>) -> ty::AliasKind {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy if let DefKind::Impl { of_trait: false } = tcx.def_kind(tcx.parent(self.def_id)) => ty::Inherent,
-            DefKind::AssocTy | DefKind::ImplTraitPlaceholder => ty::Projection,
+            DefKind::AssocTy => ty::Projection,
             DefKind::OpaqueTy => ty::Opaque,
             DefKind::TyAlias => ty::Weak,
             kind => bug!("unexpected DefKind in AliasTy: {kind:?}"),
@@ -1265,9 +1277,6 @@ impl<'tcx> AliasTy<'tcx> {
     pub fn trait_def_id(self, tcx: TyCtxt<'tcx>) -> DefId {
         match tcx.def_kind(self.def_id) {
             DefKind::AssocTy | DefKind::AssocConst => tcx.parent(self.def_id),
-            DefKind::ImplTraitPlaceholder => {
-                tcx.parent(tcx.impl_trait_in_trait_parent_fn(self.def_id))
-            }
             kind => bug!("expected a projection AliasTy; found {kind:?}"),
         }
     }
@@ -1574,12 +1583,6 @@ impl<'tcx> Deref for Region<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for Region<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        write!(f, "{:?}", self.kind())
-    }
-}
-
 #[derive(Copy, Clone, PartialEq, Eq, Hash, TyEncodable, TyDecodable, PartialOrd, Ord)]
 #[derive(HashStable)]
 pub struct EarlyBoundRegion {
@@ -1970,7 +1973,6 @@ impl<'tcx> Ty<'tcx> {
             (kind, tcx.def_kind(alias_ty.def_id)),
             (ty::Opaque, DefKind::OpaqueTy)
                 | (ty::Projection | ty::Inherent, DefKind::AssocTy)
-                | (ty::Opaque | ty::Projection, DefKind::ImplTraitPlaceholder)
                 | (ty::Weak, DefKind::TyAlias)
         );
         Ty::new(tcx, Alias(kind, alias_ty))
diff --git a/compiler/rustc_middle/src/ty/subst.rs b/compiler/rustc_middle/src/ty/subst.rs
index 4d5f5b8658c..e1a58b97557 100644
--- a/compiler/rustc_middle/src/ty/subst.rs
+++ b/compiler/rustc_middle/src/ty/subst.rs
@@ -17,7 +17,6 @@ use smallvec::SmallVec;
 
 use core::intrinsics;
 use std::cmp::Ordering;
-use std::fmt;
 use std::marker::PhantomData;
 use std::mem;
 use std::num::NonZeroUsize;
@@ -80,16 +79,6 @@ impl<'tcx> GenericArgKind<'tcx> {
     }
 }
 
-impl<'tcx> fmt::Debug for GenericArg<'tcx> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self.unpack() {
-            GenericArgKind::Lifetime(lt) => lt.fmt(f),
-            GenericArgKind::Type(ty) => ty.fmt(f),
-            GenericArgKind::Const(ct) => ct.fmt(f),
-        }
-    }
-}
-
 impl<'tcx> Ord for GenericArg<'tcx> {
     fn cmp(&self, other: &GenericArg<'tcx>) -> Ordering {
         self.unpack().cmp(&other.unpack())
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 8cbffa14850..e85afeb4b6e 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -7,11 +7,8 @@ use crate::{
         GenericArgKind, InternalSubsts, SubstsRef, Ty, UserSubsts,
     },
 };
-use rustc_data_structures::{
-    fx::{FxHashMap, FxIndexMap},
-    sync::Lrc,
-    unord::{UnordItems, UnordSet},
-};
+use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use rustc_data_structures::unord::{UnordItems, UnordSet};
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir as hir;
 use rustc_hir::{
@@ -145,7 +142,7 @@ pub struct TypeckResults<'tcx> {
     /// This is used for warning unused imports. During type
     /// checking, this `Lrc` should not be cloned: it must have a ref-count
     /// of 1 so that we can insert things into the set mutably.
-    pub used_trait_imports: Lrc<UnordSet<LocalDefId>>,
+    pub used_trait_imports: UnordSet<LocalDefId>,
 
     /// If any errors occurred while type-checking this body,
     /// this field will be set to `Some(ErrorGuaranteed)`.
@@ -273,7 +270,7 @@ impl<'tcx> TypeckResults<'tcx> {
             liberated_fn_sigs: Default::default(),
             fru_field_types: Default::default(),
             coercion_casts: Default::default(),
-            used_trait_imports: Lrc::new(Default::default()),
+            used_trait_imports: Default::default(),
             tainted_by_errors: None,
             concrete_opaque_types: Default::default(),
             closure_min_captures: Default::default(),
diff --git a/compiler/rustc_mir_dataflow/src/impls/mod.rs b/compiler/rustc_mir_dataflow/src/impls/mod.rs
index 98cec1c6760..cb74bea724a 100644
--- a/compiler/rustc_mir_dataflow/src/impls/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/impls/mod.rs
@@ -731,11 +731,11 @@ fn switch_on_enum_discriminant<'mir, 'tcx>(
 
 struct OnMutBorrow<F>(F);
 
-impl<F> Visitor<'_> for OnMutBorrow<F>
+impl<'tcx, F> Visitor<'tcx> for OnMutBorrow<F>
 where
-    F: FnMut(&mir::Place<'_>),
+    F: FnMut(&mir::Place<'tcx>),
 {
-    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'_>, location: Location) {
+    fn visit_rvalue(&mut self, rvalue: &mir::Rvalue<'tcx>, location: Location) {
         // FIXME: Does `&raw const foo` allow mutation? See #90413.
         match rvalue {
             mir::Rvalue::Ref(_, mir::BorrowKind::Mut { .. }, place)
@@ -756,7 +756,7 @@ where
 fn for_each_mut_borrow<'tcx>(
     mir: &impl MirVisitable<'tcx>,
     location: Location,
-    f: impl FnMut(&mir::Place<'_>),
+    f: impl FnMut(&mir::Place<'tcx>),
 ) {
     let mut vis = OnMutBorrow(f);
 
diff --git a/compiler/rustc_mir_dataflow/src/lib.rs b/compiler/rustc_mir_dataflow/src/lib.rs
index d43446bc5b2..900d438f8d5 100644
--- a/compiler/rustc_mir_dataflow/src/lib.rs
+++ b/compiler/rustc_mir_dataflow/src/lib.rs
@@ -43,6 +43,7 @@ pub mod impls;
 pub mod move_paths;
 pub mod rustc_peek;
 pub mod storage;
+pub mod un_derefer;
 pub mod value_analysis;
 
 fluent_messages! { "../messages.ftl" }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
index dc7e9ab3ce6..5052de99184 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/builder.rs
@@ -4,7 +4,6 @@ use rustc_middle::mir::*;
 use rustc_middle::ty::{self, TyCtxt};
 use smallvec::{smallvec, SmallVec};
 
-use std::iter;
 use std::mem;
 
 use super::abs_domain::Lift;
@@ -40,22 +39,22 @@ impl<'a, 'tcx> MoveDataBuilder<'a, 'tcx> {
                     locals: body
                         .local_decls
                         .iter_enumerated()
-                        .filter(|(_, l)| !l.is_deref_temp())
-                        .map(|(i, _)| {
-                            (
-                                i,
+                        .map(|(i, l)| {
+                            if l.is_deref_temp() {
+                                MovePathIndex::MAX
+                            } else {
                                 Self::new_move_path(
                                     &mut move_paths,
                                     &mut path_map,
                                     &mut init_path_map,
                                     None,
                                     Place::from(i),
-                                ),
-                            )
+                                )
+                            }
                         })
                         .collect(),
                     projections: Default::default(),
-                    derefer_sidetable: Default::default(),
+                    un_derefer: Default::default(),
                 },
                 move_paths,
                 path_map,
@@ -100,11 +99,10 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     ///
     /// Maybe we should have separate "borrowck" and "moveck" modes.
     fn move_path_for(&mut self, place: Place<'tcx>) -> Result<MovePathIndex, MoveError<'tcx>> {
-        let deref_chain = self.builder.data.rev_lookup.deref_chain(place.as_ref());
+        let data = &mut self.builder.data;
 
         debug!("lookup({:?})", place);
-        let mut base =
-            self.builder.data.rev_lookup.find_local(deref_chain.first().unwrap_or(&place).local);
+        let mut base = data.rev_lookup.find_local(place.local);
 
         // The move path index of the first union that we find. Once this is
         // some we stop creating child move paths, since moves from unions
@@ -113,55 +111,60 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
         // from `*(u.f: &_)` isn't allowed.
         let mut union_path = None;
 
-        for place in deref_chain.into_iter().chain(iter::once(place)) {
-            for (place_ref, elem) in place.as_ref().iter_projections() {
-                let body = self.builder.body;
-                let tcx = self.builder.tcx;
-                let place_ty = place_ref.ty(body, tcx).ty;
-                match place_ty.kind() {
-                    ty::Ref(..) | ty::RawPtr(..) => {
-                        return Err(MoveError::cannot_move_out_of(
-                            self.loc,
-                            BorrowedContent {
-                                target_place: place_ref.project_deeper(&[elem], tcx),
-                            },
-                        ));
-                    }
-                    ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
-                        return Err(MoveError::cannot_move_out_of(
-                            self.loc,
-                            InteriorOfTypeWithDestructor { container_ty: place_ty },
-                        ));
-                    }
-                    ty::Adt(adt, _) if adt.is_union() => {
-                        union_path.get_or_insert(base);
-                    }
-                    ty::Slice(_) => {
+        for (place_ref, elem) in data.rev_lookup.un_derefer.iter_projections(place.as_ref()) {
+            let body = self.builder.body;
+            let tcx = self.builder.tcx;
+            let place_ty = place_ref.ty(body, tcx).ty;
+            match place_ty.kind() {
+                ty::Ref(..) | ty::RawPtr(..) => {
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        BorrowedContent { target_place: place_ref.project_deeper(&[elem], tcx) },
+                    ));
+                }
+                ty::Adt(adt, _) if adt.has_dtor(tcx) && !adt.is_box() => {
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        InteriorOfTypeWithDestructor { container_ty: place_ty },
+                    ));
+                }
+                ty::Adt(adt, _) if adt.is_union() => {
+                    union_path.get_or_insert(base);
+                }
+                ty::Slice(_) => {
+                    return Err(MoveError::cannot_move_out_of(
+                        self.loc,
+                        InteriorOfSliceOrArray {
+                            ty: place_ty,
+                            is_index: matches!(elem, ProjectionElem::Index(..)),
+                        },
+                    ));
+                }
+
+                ty::Array(..) => {
+                    if let ProjectionElem::Index(..) = elem {
                         return Err(MoveError::cannot_move_out_of(
                             self.loc,
-                            InteriorOfSliceOrArray {
-                                ty: place_ty,
-                                is_index: matches!(elem, ProjectionElem::Index(..)),
-                            },
+                            InteriorOfSliceOrArray { ty: place_ty, is_index: true },
                         ));
                     }
+                }
 
-                    ty::Array(..) => {
-                        if let ProjectionElem::Index(..) = elem {
-                            return Err(MoveError::cannot_move_out_of(
-                                self.loc,
-                                InteriorOfSliceOrArray { ty: place_ty, is_index: true },
-                            ));
-                        }
-                    }
-
-                    _ => {}
-                };
+                _ => {}
+            };
 
-                if union_path.is_none() {
-                    base = self
-                        .add_move_path(base, elem, |tcx| place_ref.project_deeper(&[elem], tcx));
-                }
+            if union_path.is_none() {
+                // inlined from add_move_path because of a borrowck conflict with the iterator
+                base =
+                    *data.rev_lookup.projections.entry((base, elem.lift())).or_insert_with(|| {
+                        MoveDataBuilder::new_move_path(
+                            &mut data.move_paths,
+                            &mut data.path_map,
+                            &mut data.init_path_map,
+                            Some(base),
+                            place_ref.project_deeper(&[elem], tcx),
+                        )
+                    })
             }
         }
 
@@ -282,10 +285,14 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
     fn gather_statement(&mut self, stmt: &Statement<'tcx>) {
         match &stmt.kind {
             StatementKind::Assign(box (place, Rvalue::CopyForDeref(reffed))) => {
-                assert!(place.projection.is_empty());
-                if self.builder.body.local_decls[place.local].is_deref_temp() {
-                    self.builder.data.rev_lookup.derefer_sidetable.insert(place.local, *reffed);
-                }
+                let local = place.as_local().unwrap();
+                assert!(self.builder.body.local_decls[local].is_deref_temp());
+
+                let rev_lookup = &mut self.builder.data.rev_lookup;
+
+                rev_lookup.un_derefer.insert(local, reffed.as_ref());
+                let base_local = rev_lookup.un_derefer.deref_chain(local).first().unwrap().local;
+                rev_lookup.locals[local] = rev_lookup.locals[base_local];
             }
             StatementKind::Assign(box (place, rval)) => {
                 self.create_move_path(*place);
@@ -306,7 +313,7 @@ impl<'b, 'a, 'tcx> Gatherer<'b, 'a, 'tcx> {
             StatementKind::StorageLive(_) => {}
             StatementKind::StorageDead(local) => {
                 // DerefTemp locals (results of CopyForDeref) don't actually move anything.
-                if !self.builder.data.rev_lookup.derefer_sidetable.contains_key(&local) {
+                if !self.builder.body.local_decls[*local].is_deref_temp() {
                     self.gather_move(Place::from(*local));
                 }
             }
diff --git a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
index aa901f66d3f..0c7aa6676ec 100644
--- a/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
+++ b/compiler/rustc_mir_dataflow/src/move_paths/mod.rs
@@ -1,5 +1,6 @@
 use crate::move_paths::builder::MoveDat;
-use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
+use crate::un_derefer::UnDerefer;
+use rustc_data_structures::fx::FxHashMap;
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::mir::*;
 use rustc_middle::ty::{ParamEnv, Ty, TyCtxt};
@@ -290,7 +291,7 @@ impl Init {
 /// Tables mapping from a place to its MovePathIndex.
 #[derive(Debug)]
 pub struct MovePathLookup<'tcx> {
-    locals: FxIndexMap<Local, MovePathIndex>,
+    locals: IndexVec<Local, MovePathIndex>,
 
     /// projections are made from a base-place and a projection
     /// elem. The base-place will have a unique MovePathIndex; we use
@@ -300,8 +301,7 @@ pub struct MovePathLookup<'tcx> {
     /// elem to the associated MovePathIndex.
     projections: FxHashMap<(MovePathIndex, AbstractElem), MovePathIndex>,
 
-    /// Maps `DerefTemp` locals to the `Place`s assigned to them.
-    derefer_sidetable: FxHashMap<Local, Place<'tcx>>,
+    un_derefer: UnDerefer<'tcx>,
 }
 
 mod builder;
@@ -317,54 +317,23 @@ impl<'tcx> MovePathLookup<'tcx> {
     // alternative will *not* create a MovePath on the fly for an
     // unknown place, but will rather return the nearest available
     // parent.
-    pub fn find(&self, place: PlaceRef<'_>) -> LookupResult {
-        let deref_chain = self.deref_chain(place);
+    pub fn find(&self, place: PlaceRef<'tcx>) -> LookupResult {
+        let mut result = self.find_local(place.local);
 
-        let local = match deref_chain.first() {
-            Some(place) => place.local,
-            None => place.local,
-        };
-
-        let mut result = *self.locals.get(&local).unwrap_or_else(|| {
-            bug!("base local ({local:?}) of deref_chain should not be a deref temp")
-        });
-
-        // this needs to be a closure because `place` has a different lifetime than `prefix`'s places
-        let mut subpaths_for_place = |place: PlaceRef<'_>| {
-            for elem in place.projection.iter() {
-                if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
-                    result = subpath;
-                } else {
-                    return Some(result);
-                }
-            }
-            None
-        };
-
-        for place in deref_chain {
-            if let Some(result) = subpaths_for_place(place.as_ref()) {
+        for (_, elem) in self.un_derefer.iter_projections(place) {
+            if let Some(&subpath) = self.projections.get(&(result, elem.lift())) {
+                result = subpath;
+            } else {
                 return LookupResult::Parent(Some(result));
             }
         }
 
-        if let Some(result) = subpaths_for_place(place) {
-            return LookupResult::Parent(Some(result));
-        }
-
         LookupResult::Exact(result)
     }
 
+    #[inline]
     pub fn find_local(&self, local: Local) -> MovePathIndex {
-        let deref_chain = self.deref_chain(Place::from(local).as_ref());
-
-        let local = match deref_chain.last() {
-            Some(place) => place.local,
-            None => local,
-        };
-
-        *self.locals.get(&local).unwrap_or_else(|| {
-            bug!("base local ({local:?}) of deref_chain should not be a deref temp")
-        })
+        self.locals[local]
     }
 
     /// An enumerated iterator of `local`s and their associated
@@ -372,22 +341,7 @@ impl<'tcx> MovePathLookup<'tcx> {
     pub fn iter_locals_enumerated(
         &self,
     ) -> impl DoubleEndedIterator<Item = (Local, MovePathIndex)> + ExactSizeIterator + '_ {
-        self.locals.iter().map(|(&l, &idx)| (l, idx))
-    }
-
-    /// Returns the chain of places behind `DerefTemp` locals in `place`
-    pub fn deref_chain(&self, place: PlaceRef<'_>) -> Vec<Place<'tcx>> {
-        let mut prefix = Vec::new();
-        let mut local = place.local;
-
-        while let Some(&reffed) = self.derefer_sidetable.get(&local) {
-            prefix.insert(0, reffed);
-            local = reffed.local;
-        }
-
-        debug!("deref_chain({place:?}) = {prefix:?}");
-
-        prefix
+        self.locals.iter_enumerated().map(|(l, &idx)| (l, idx))
     }
 }
 
diff --git a/compiler/rustc_mir_dataflow/src/un_derefer.rs b/compiler/rustc_mir_dataflow/src/un_derefer.rs
new file mode 100644
index 00000000000..874d50ffd0e
--- /dev/null
+++ b/compiler/rustc_mir_dataflow/src/un_derefer.rs
@@ -0,0 +1,100 @@
+use rustc_data_structures::fx::FxHashMap;
+use rustc_middle::mir::*;
+
+/// Used for reverting changes made by `DerefSeparator`
+#[derive(Default, Debug)]
+pub struct UnDerefer<'tcx> {
+    deref_chains: FxHashMap<Local, Vec<PlaceRef<'tcx>>>,
+}
+
+impl<'tcx> UnDerefer<'tcx> {
+    #[inline]
+    pub fn insert(&mut self, local: Local, reffed: PlaceRef<'tcx>) {
+        let mut chain = self.deref_chains.remove(&reffed.local).unwrap_or_default();
+        chain.push(reffed);
+        self.deref_chains.insert(local, chain);
+    }
+
+    /// Returns the chain of places behind `DerefTemp` locals
+    #[inline]
+    pub fn deref_chain(&self, local: Local) -> &[PlaceRef<'tcx>] {
+        self.deref_chains.get(&local).map(Vec::as_slice).unwrap_or_default()
+    }
+
+    /// Iterates over the projections of a place and its deref chain.
+    ///
+    /// See [`PlaceRef::iter_projections`]
+    #[inline]
+    pub fn iter_projections(
+        &self,
+        place: PlaceRef<'tcx>,
+    ) -> impl Iterator<Item = (PlaceRef<'tcx>, PlaceElem<'tcx>)> + '_ {
+        ProjectionIter::new(self.deref_chain(place.local), place)
+    }
+}
+
+/// The iterator returned by [`UnDerefer::iter_projections`].
+struct ProjectionIter<'a, 'tcx> {
+    places: SlicePlusOne<'a, PlaceRef<'tcx>>,
+    proj_idx: usize,
+}
+
+impl<'a, 'tcx> ProjectionIter<'a, 'tcx> {
+    #[inline]
+    fn new(deref_chain: &'a [PlaceRef<'tcx>], place: PlaceRef<'tcx>) -> Self {
+        // just return an empty iterator for a bare local
+        let last = if place.as_local().is_none() {
+            Some(place)
+        } else {
+            debug_assert!(deref_chain.is_empty());
+            None
+        };
+
+        ProjectionIter { places: SlicePlusOne { slice: deref_chain, last }, proj_idx: 0 }
+    }
+}
+
+impl<'tcx> Iterator for ProjectionIter<'_, 'tcx> {
+    type Item = (PlaceRef<'tcx>, PlaceElem<'tcx>);
+
+    #[inline]
+    fn next(&mut self) -> Option<(PlaceRef<'tcx>, PlaceElem<'tcx>)> {
+        let place = self.places.read()?;
+
+        // the projection should never be empty except for a bare local which is handled in new
+        let partial_place =
+            PlaceRef { local: place.local, projection: &place.projection[..self.proj_idx] };
+        let elem = place.projection[self.proj_idx];
+
+        if self.proj_idx == place.projection.len() - 1 {
+            self.proj_idx = 0;
+            self.places.advance();
+        } else {
+            self.proj_idx += 1;
+        }
+
+        Some((partial_place, elem))
+    }
+}
+
+struct SlicePlusOne<'a, T> {
+    slice: &'a [T],
+    last: Option<T>,
+}
+
+impl<T: Copy> SlicePlusOne<'_, T> {
+    #[inline]
+    fn read(&self) -> Option<T> {
+        self.slice.first().copied().or(self.last)
+    }
+
+    #[inline]
+    fn advance(&mut self) {
+        match self.slice {
+            [_, ref remainder @ ..] => {
+                self.slice = remainder;
+            }
+            [] => self.last = None,
+        }
+    }
+}
diff --git a/compiler/rustc_mir_transform/src/const_prop.rs b/compiler/rustc_mir_transform/src/const_prop.rs
index 2f2c7357b00..f3ac679f97b 100644
--- a/compiler/rustc_mir_transform/src/const_prop.rs
+++ b/compiler/rustc_mir_transform/src/const_prop.rs
@@ -22,8 +22,8 @@ use rustc_target::spec::abi::Abi as CallAbi;
 
 use crate::MirPass;
 use rustc_const_eval::interpret::{
-    self, compile_time_machine, AllocId, ConstAllocation, ConstValue, Frame, ImmTy, Immediate,
-    InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
+    self, compile_time_machine, AllocId, ConstAllocation, ConstValue, FnArg, Frame, ImmTy,
+    Immediate, InterpCx, InterpResult, LocalValue, MemoryKind, OpTy, PlaceTy, Pointer, Scalar,
     StackPopCleanup,
 };
 
@@ -185,7 +185,7 @@ impl<'mir, 'tcx> interpret::Machine<'mir, 'tcx> for ConstPropMachine<'mir, 'tcx>
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _abi: CallAbi,
-        _args: &[OpTy<'tcx>],
+        _args: &[FnArg<'tcx>],
         _destination: &PlaceTy<'tcx>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
diff --git a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
index 78fb196358f..5b6cbb5577c 100644
--- a/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
+++ b/compiler/rustc_mir_transform/src/dataflow_const_prop.rs
@@ -532,7 +532,7 @@ impl<'tcx, 'map, 'a> Visitor<'tcx> for OperandCollector<'tcx, 'map, 'a> {
 
 struct DummyMachine;
 
-impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine {
+impl<'mir, 'tcx: 'mir> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachine {
     rustc_const_eval::interpret::compile_time_machine!(<'mir, 'tcx>);
     type MemoryKind = !;
     const PANIC_ON_ALLOC_FAIL: bool = true;
@@ -557,7 +557,7 @@ impl<'mir, 'tcx> rustc_const_eval::interpret::Machine<'mir, 'tcx> for DummyMachi
         _ecx: &mut InterpCx<'mir, 'tcx, Self>,
         _instance: ty::Instance<'tcx>,
         _abi: rustc_target::spec::abi::Abi,
-        _args: &[rustc_const_eval::interpret::OpTy<'tcx, Self::Provenance>],
+        _args: &[rustc_const_eval::interpret::FnArg<'tcx, Self::Provenance>],
         _destination: &rustc_const_eval::interpret::PlaceTy<'tcx, Self::Provenance>,
         _target: Option<BasicBlock>,
         _unwind: UnwindAction,
diff --git a/compiler/rustc_monomorphize/src/polymorphize.rs b/compiler/rustc_monomorphize/src/polymorphize.rs
index 88a3e028527..aa2ce65e4cc 100644
--- a/compiler/rustc_monomorphize/src/polymorphize.rs
+++ b/compiler/rustc_monomorphize/src/polymorphize.rs
@@ -163,7 +163,6 @@ fn mark_used_by_default_parameters<'tcx>(
         | DefKind::AnonConst
         | DefKind::InlineConst
         | DefKind::OpaqueTy
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 073760f394e..f48900c3c52 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -694,7 +694,6 @@ impl CheckAttrVisitor<'_> {
             | Target::GlobalAsm
             | Target::TyAlias
             | Target::OpaqueTy
-            | Target::ImplTraitPlaceholder
             | Target::Enum
             | Target::Variant
             | Target::Struct
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 4fcee9396ed..fe23506b878 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -136,19 +136,7 @@ where
 
     fn visit_projection_ty(&mut self, projection: ty::AliasTy<'tcx>) -> ControlFlow<V::BreakTy> {
         let tcx = self.def_id_visitor.tcx();
-        let (trait_ref, assoc_substs) = if tcx.def_kind(projection.def_id)
-            != DefKind::ImplTraitPlaceholder
-        {
-            projection.trait_ref_and_own_substs(tcx)
-        } else {
-            // HACK(RPITIT): Remove this when RPITITs are lowered to regular assoc tys
-            let def_id = tcx.impl_trait_in_trait_parent_fn(projection.def_id);
-            let trait_generics = tcx.generics_of(def_id);
-            (
-                ty::TraitRef::new(tcx, def_id, projection.substs.truncate_to(tcx, trait_generics)),
-                &projection.substs[trait_generics.count()..],
-            )
-        };
+        let (trait_ref, assoc_substs) = projection.trait_ref_and_own_substs(tcx);
         self.visit_trait(trait_ref)?;
         if V::SHALLOW {
             ControlFlow::Continue(())
@@ -651,7 +639,6 @@ impl<'tcx> EmbargoVisitor<'tcx> {
             | DefKind::ForeignTy
             | DefKind::Fn
             | DefKind::OpaqueTy
-            | DefKind::ImplTraitPlaceholder
             | DefKind::AssocFn
             | DefKind::Trait
             | DefKind::TyParam
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index e6ceedddfa1..ff63e4e33cb 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -949,7 +949,6 @@ impl<'a, 'b, 'tcx> BuildReducedGraphVisitor<'a, 'b, 'tcx> {
                 | DefKind::TyAlias
                 | DefKind::ForeignTy
                 | DefKind::OpaqueTy
-                | DefKind::ImplTraitPlaceholder
                 | DefKind::TraitAlias
                 | DefKind::AssocTy,
                 _,
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 90cb312edd2..f6c7aecf8b0 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -3503,7 +3503,7 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
         let report_errors = |this: &mut Self, res: Option<Res>| {
             if this.should_report_errs() {
                 let (err, candidates) =
-                    this.smart_resolve_report_errors(path, path, path_span, source, res);
+                    this.smart_resolve_report_errors(path, None, path_span, source, res);
 
                 let def_id = this.parent_scope.module.nearest_parent_mod();
                 let instead = res.is_some();
@@ -3555,14 +3555,14 @@ impl<'a: 'ast, 'b, 'ast, 'tcx> LateResolutionVisitor<'a, 'b, 'ast, 'tcx> {
             // Before we start looking for candidates, we have to get our hands
             // on the type user is trying to perform invocation on; basically:
             // we're transforming `HashMap::new` into just `HashMap`.
-            let prefix_path = match path.split_last() {
-                Some((_, path)) if !path.is_empty() => path,
+            let (following_seg, prefix_path) = match path.split_last() {
+                Some((last, path)) if !path.is_empty() => (Some(last), path),
                 _ => return Some(parent_err),
             };
 
             let (mut err, candidates) = this.smart_resolve_report_errors(
                 prefix_path,
-                path,
+                following_seg,
                 path_span,
                 PathSource::Type,
                 None,
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index c0e3f1aaf01..78ef72a7e34 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -332,15 +332,11 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     pub(crate) fn smart_resolve_partial_mod_path_errors(
         &mut self,
         prefix_path: &[Segment],
-        path: &[Segment],
+        following_seg: Option<&Segment>,
     ) -> Vec<ImportSuggestion> {
-        let next_seg = if path.len() >= prefix_path.len() + 1 && prefix_path.len() == 1 {
-            path.get(prefix_path.len())
-        } else {
-            None
-        };
         if let Some(segment) = prefix_path.last() &&
-            let Some(next_seg) = next_seg {
+            let Some(following_seg) = following_seg
+        {
             let candidates = self.r.lookup_import_candidates(
                 segment.ident,
                 Namespace::TypeNS,
@@ -353,9 +349,10 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
                 .filter(|candidate| {
                     if let Some(def_id) = candidate.did &&
                         let Some(module) = self.r.get_module(def_id) {
-                            self.r.resolutions(module).borrow().iter().any(|(key, _r)| {
-                                key.ident.name == next_seg.ident.name
-                            })
+                                Some(def_id) != self.parent_scope.module.opt_def_id() &&
+                                self.r.resolutions(module).borrow().iter().any(|(key, _r)| {
+                                    key.ident.name == following_seg.ident.name
+                                })
                     } else {
                         false
                     }
@@ -371,7 +368,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     pub(crate) fn smart_resolve_report_errors(
         &mut self,
         path: &[Segment],
-        full_path: &[Segment],
+        following_seg: Option<&Segment>,
         span: Span,
         source: PathSource<'_>,
         res: Option<Res>,
@@ -412,8 +409,15 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             return (err, Vec::new());
         }
 
-        let (found, candidates) =
-            self.try_lookup_name_relaxed(&mut err, source, path, full_path, span, res, &base_error);
+        let (found, candidates) = self.try_lookup_name_relaxed(
+            &mut err,
+            source,
+            path,
+            following_seg,
+            span,
+            res,
+            &base_error,
+        );
         if found {
             return (err, candidates);
         }
@@ -422,7 +426,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
 
         // if we have suggested using pattern matching, then don't add needless suggestions
         // for typos.
-        fallback |= self.suggest_typo(&mut err, source, path, span, &base_error);
+        fallback |= self.suggest_typo(&mut err, source, path, following_seg, span, &base_error);
 
         if fallback {
             // Fallback label.
@@ -519,7 +523,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diagnostic,
         source: PathSource<'_>,
         path: &[Segment],
-        full_path: &[Segment],
+        following_seg: Option<&Segment>,
         span: Span,
         res: Option<Res>,
         base_error: &BaseError,
@@ -590,8 +594,9 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         // Try finding a suitable replacement.
-        let typo_sugg =
-            self.lookup_typo_candidate(path, source.namespace(), is_expected).to_opt_suggestion();
+        let typo_sugg = self
+            .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
+            .to_opt_suggestion();
         if path.len() == 1 && self.self_type_is_available() {
             if let Some(candidate) =
                 self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
@@ -690,7 +695,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         }
 
         if candidates.is_empty() {
-            candidates = self.smart_resolve_partial_mod_path_errors(path, full_path);
+            candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg);
         }
 
         return (false, candidates);
@@ -776,12 +781,14 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
         err: &mut Diagnostic,
         source: PathSource<'_>,
         path: &[Segment],
+        following_seg: Option<&Segment>,
         span: Span,
         base_error: &BaseError,
     ) -> bool {
         let is_expected = &|res| source.is_expected(res);
         let ident_span = path.last().map_or(span, |ident| ident.ident.span);
-        let typo_sugg = self.lookup_typo_candidate(path, source.namespace(), is_expected);
+        let typo_sugg =
+            self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
         let is_in_same_file = &|sp1, sp2| {
             let source_map = self.r.tcx.sess.source_map();
             let file1 = source_map.span_to_filename(sp1);
@@ -1715,6 +1722,7 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
     fn lookup_typo_candidate(
         &mut self,
         path: &[Segment],
+        following_seg: Option<&Segment>,
         ns: Namespace,
         filter_fn: &impl Fn(Res) -> bool,
     ) -> TypoCandidate {
@@ -1793,6 +1801,26 @@ impl<'a: 'ast, 'ast, 'tcx> LateResolutionVisitor<'a, '_, 'ast, 'tcx> {
             }
         }
 
+        // if next_seg is present, let's filter everything that does not continue the path
+        if let Some(following_seg) = following_seg {
+            names.retain(|suggestion| match suggestion.res {
+                Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => {
+                    // FIXME: this is not totally accurate, but mostly works
+                    suggestion.candidate != following_seg.ident.name
+                }
+                Res::Def(DefKind::Mod, def_id) => self.r.get_module(def_id).map_or_else(
+                    || false,
+                    |module| {
+                        self.r
+                            .resolutions(module)
+                            .borrow()
+                            .iter()
+                            .any(|(key, _)| key.ident.name == following_seg.ident.name)
+                    },
+                ),
+                _ => true,
+            });
+        }
         let name = path[path.len() - 1].ident.name;
         // Make sure error reporting is deterministic.
         names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));
diff --git a/compiler/rustc_session/src/options.rs b/compiler/rustc_session/src/options.rs
index 7840a0ecf0b..87d67c099ce 100644
--- a/compiler/rustc_session/src/options.rs
+++ b/compiler/rustc_session/src/options.rs
@@ -1583,9 +1583,6 @@ options! {
         "what location details should be tracked when using caller_location, either \
         `none`, or a comma separated list of location details, for which \
         valid options are `file`, `line`, and `column` (default: `file,line,column`)"),
-    lower_impl_trait_in_trait_to_assoc_ty: bool = (false, parse_bool, [TRACKED],
-        "modify the lowering strategy for `impl Trait` in traits so that they are lowered to \
-        generic associated types"),
     ls: bool = (false, parse_bool, [UNTRACKED],
         "list the symbols defined by a library crate (default: no)"),
     macro_backtrace: bool = (false, parse_bool, [UNTRACKED],
diff --git a/compiler/rustc_smir/Cargo.toml b/compiler/rustc_smir/Cargo.toml
index a6e6de5f785..80d4e7ed02f 100644
--- a/compiler/rustc_smir/Cargo.toml
+++ b/compiler/rustc_smir/Cargo.toml
@@ -4,14 +4,18 @@ version = "0.0.0"
 edition = "2021"
 
 [dependencies]
-rustc_hir = { path = "../rustc_hir" }
+# Use optional dependencies for rustc_* in order to support building this crate separately.
+rustc_hir = { path = "../rustc_hir", optional = true }
 rustc_middle = { path = "../rustc_middle", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
+rustc_target = { path = "../rustc_target", optional = true }
 tracing = "0.1"
 scoped-tls = "1.0"
 
 [features]
 default = [
+    "rustc_hir",
     "rustc_middle",
     "rustc_span",
+    "rustc_target",
 ]
diff --git a/compiler/rustc_smir/rust-toolchain.toml b/compiler/rustc_smir/rust-toolchain.toml
index 157dfd620ee..d75e8e33b1c 100644
--- a/compiler/rustc_smir/rust-toolchain.toml
+++ b/compiler/rustc_smir/rust-toolchain.toml
@@ -1,3 +1,3 @@
 [toolchain]
-channel = "nightly-2023-02-28"
+channel = "nightly-2023-06-14"
 components = [ "rustfmt", "rustc-dev" ]
diff --git a/compiler/rustc_smir/src/lib.rs b/compiler/rustc_smir/src/lib.rs
index fb03633b99b..8450bb73119 100644
--- a/compiler/rustc_smir/src/lib.rs
+++ b/compiler/rustc_smir/src/lib.rs
@@ -13,6 +13,17 @@
 #![cfg_attr(not(feature = "default"), feature(rustc_private))]
 #![feature(local_key_cell_methods)]
 #![feature(ptr_metadata)]
+#![feature(type_alias_impl_trait)] // Used to define opaque types.
+
+// Declare extern rustc_* crates to enable building this crate separately from the compiler.
+#[cfg(not(feature = "default"))]
+extern crate rustc_hir;
+#[cfg(not(feature = "default"))]
+extern crate rustc_middle;
+#[cfg(not(feature = "default"))]
+extern crate rustc_span;
+#[cfg(not(feature = "default"))]
+extern crate rustc_target;
 
 pub mod rustc_internal;
 pub mod stable_mir;
diff --git a/compiler/rustc_smir/src/rustc_internal/mod.rs b/compiler/rustc_smir/src/rustc_internal/mod.rs
index 609a04d263c..87e0b211556 100644
--- a/compiler/rustc_smir/src/rustc_internal/mod.rs
+++ b/compiler/rustc_smir/src/rustc_internal/mod.rs
@@ -3,6 +3,9 @@
 //! For that, we define APIs that will temporarily be public to 3P that exposes rustc internal APIs
 //! until stable MIR is complete.
 
+use std::fmt::Debug;
+use std::string::ToString;
+
 use crate::{
     rustc_smir::Tables,
     stable_mir::{self, with},
@@ -49,3 +52,10 @@ pub fn crate_num(item: &stable_mir::Crate) -> CrateNum {
 pub fn run(tcx: TyCtxt<'_>, f: impl FnOnce()) {
     crate::stable_mir::run(Tables { tcx, def_ids: vec![], types: vec![] }, f);
 }
+
+/// A type that provides internal information but that can still be used for debug purpose.
+pub type Opaque = impl Debug + ToString + Clone;
+
+pub(crate) fn opaque<T: Debug>(value: &T) -> Opaque {
+    format!("{value:?}")
+}
diff --git a/compiler/rustc_smir/src/rustc_smir/mod.rs b/compiler/rustc_smir/src/rustc_smir/mod.rs
index 85d5bb00c4e..f22c620021e 100644
--- a/compiler/rustc_smir/src/rustc_smir/mod.rs
+++ b/compiler/rustc_smir/src/rustc_smir/mod.rs
@@ -7,11 +7,13 @@
 //!
 //! For now, we are developing everything inside `rustc`, thus, we keep this module private.
 
+use crate::rustc_internal::{self, opaque};
 use crate::stable_mir::ty::{FloatTy, IntTy, RigidTy, TyKind, UintTy};
 use crate::stable_mir::{self, Context};
 use rustc_middle::mir;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_span::def_id::{CrateNum, DefId, LOCAL_CRATE};
+use rustc_target::abi::FieldIdx;
 use tracing::debug;
 
 impl<'tcx> Context for Tables<'tcx> {
@@ -137,11 +139,21 @@ fn smir_crate(tcx: TyCtxt<'_>, crate_num: CrateNum) -> stable_mir::Crate {
     stable_mir::Crate { id: crate_num.into(), name: crate_name, is_local }
 }
 
-pub trait Stable {
+/// Trait used to convert between an internal MIR type to a Stable MIR type.
+pub(crate) trait Stable {
+    /// The stable representation of the type implementing Stable.
     type T;
+    /// Converts an object to the equivalent Stable MIR representation.
     fn stable(&self) -> Self::T;
 }
 
+impl Stable for DefId {
+    type T = stable_mir::CrateItem;
+    fn stable(&self) -> Self::T {
+        rustc_internal::crate_item(*self)
+    }
+}
+
 impl<'tcx> Stable for mir::Statement<'tcx> {
     type T = stable_mir::mir::Statement;
     fn stable(&self) -> Self::T {
@@ -173,12 +185,18 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> {
         match self {
             Use(op) => stable_mir::mir::Rvalue::Use(op.stable()),
             Repeat(_, _) => todo!(),
-            Ref(_, _, _) => todo!(),
-            ThreadLocalRef(_) => todo!(),
-            AddressOf(_, _) => todo!(),
-            Len(_) => todo!(),
+            Ref(region, kind, place) => {
+                stable_mir::mir::Rvalue::Ref(opaque(region), kind.stable(), place.stable())
+            }
+            ThreadLocalRef(def_id) => stable_mir::mir::Rvalue::ThreadLocalRef(def_id.stable()),
+            AddressOf(mutability, place) => {
+                stable_mir::mir::Rvalue::AddressOf(mutability.stable(), place.stable())
+            }
+            Len(place) => stable_mir::mir::Rvalue::Len(place.stable()),
             Cast(_, _, _) => todo!(),
-            BinaryOp(_, _) => todo!(),
+            BinaryOp(bin_op, ops) => {
+                stable_mir::mir::Rvalue::BinaryOp(bin_op.stable(), ops.0.stable(), ops.1.stable())
+            }
             CheckedBinaryOp(bin_op, ops) => stable_mir::mir::Rvalue::CheckedBinaryOp(
                 bin_op.stable(),
                 ops.0.stable(),
@@ -186,14 +204,119 @@ impl<'tcx> Stable for mir::Rvalue<'tcx> {
             ),
             NullaryOp(_, _) => todo!(),
             UnaryOp(un_op, op) => stable_mir::mir::Rvalue::UnaryOp(un_op.stable(), op.stable()),
-            Discriminant(_) => todo!(),
+            Discriminant(place) => stable_mir::mir::Rvalue::Discriminant(place.stable()),
             Aggregate(_, _) => todo!(),
             ShallowInitBox(_, _) => todo!(),
-            CopyForDeref(_) => todo!(),
+            CopyForDeref(place) => stable_mir::mir::Rvalue::CopyForDeref(place.stable()),
+        }
+    }
+}
+
+impl Stable for mir::Mutability {
+    type T = stable_mir::mir::Mutability;
+    fn stable(&self) -> Self::T {
+        use mir::Mutability::*;
+        match *self {
+            Not => stable_mir::mir::Mutability::Not,
+            Mut => stable_mir::mir::Mutability::Mut,
+        }
+    }
+}
+
+impl Stable for mir::BorrowKind {
+    type T = stable_mir::mir::BorrowKind;
+    fn stable(&self) -> Self::T {
+        use mir::BorrowKind::*;
+        match *self {
+            Shared => stable_mir::mir::BorrowKind::Shared,
+            Shallow => stable_mir::mir::BorrowKind::Shallow,
+            Mut { kind } => stable_mir::mir::BorrowKind::Mut { kind: kind.stable() },
+        }
+    }
+}
+
+impl Stable for mir::MutBorrowKind {
+    type T = stable_mir::mir::MutBorrowKind;
+    fn stable(&self) -> Self::T {
+        use mir::MutBorrowKind::*;
+        match *self {
+            Default => stable_mir::mir::MutBorrowKind::Default,
+            TwoPhaseBorrow => stable_mir::mir::MutBorrowKind::TwoPhaseBorrow,
+            ClosureCapture => stable_mir::mir::MutBorrowKind::ClosureCapture,
+        }
+    }
+}
+
+impl<'tcx> Stable for mir::NullOp<'tcx> {
+    type T = stable_mir::mir::NullOp;
+    fn stable(&self) -> Self::T {
+        use mir::NullOp::*;
+        match self {
+            SizeOf => stable_mir::mir::NullOp::SizeOf,
+            AlignOf => stable_mir::mir::NullOp::AlignOf,
+            OffsetOf(indices) => {
+                stable_mir::mir::NullOp::OffsetOf(indices.iter().map(|idx| idx.stable()).collect())
+            }
+        }
+    }
+}
+
+impl Stable for mir::CastKind {
+    type T = stable_mir::mir::CastKind;
+    fn stable(&self) -> Self::T {
+        use mir::CastKind::*;
+        match self {
+            PointerExposeAddress => stable_mir::mir::CastKind::PointerExposeAddress,
+            PointerFromExposedAddress => stable_mir::mir::CastKind::PointerFromExposedAddress,
+            PointerCoercion(c) => stable_mir::mir::CastKind::PointerCoercion(c.stable()),
+            DynStar => stable_mir::mir::CastKind::DynStar,
+            IntToInt => stable_mir::mir::CastKind::IntToInt,
+            FloatToInt => stable_mir::mir::CastKind::FloatToInt,
+            FloatToFloat => stable_mir::mir::CastKind::FloatToFloat,
+            IntToFloat => stable_mir::mir::CastKind::IntToFloat,
+            PtrToPtr => stable_mir::mir::CastKind::PtrToPtr,
+            FnPtrToPtr => stable_mir::mir::CastKind::FnPtrToPtr,
+            Transmute => stable_mir::mir::CastKind::Transmute,
         }
     }
 }
 
+impl Stable for ty::adjustment::PointerCoercion {
+    type T = stable_mir::mir::PointerCoercion;
+    fn stable(&self) -> Self::T {
+        use ty::adjustment::PointerCoercion;
+        match self {
+            PointerCoercion::ReifyFnPointer => stable_mir::mir::PointerCoercion::ReifyFnPointer,
+            PointerCoercion::UnsafeFnPointer => stable_mir::mir::PointerCoercion::UnsafeFnPointer,
+            PointerCoercion::ClosureFnPointer(unsafety) => {
+                stable_mir::mir::PointerCoercion::ClosureFnPointer(unsafety.stable())
+            }
+            PointerCoercion::MutToConstPointer => {
+                stable_mir::mir::PointerCoercion::MutToConstPointer
+            }
+            PointerCoercion::ArrayToPointer => stable_mir::mir::PointerCoercion::ArrayToPointer,
+            PointerCoercion::Unsize => stable_mir::mir::PointerCoercion::Unsize,
+        }
+    }
+}
+
+impl Stable for rustc_hir::Unsafety {
+    type T = stable_mir::mir::Safety;
+    fn stable(&self) -> Self::T {
+        match self {
+            rustc_hir::Unsafety::Unsafe => stable_mir::mir::Safety::Unsafe,
+            rustc_hir::Unsafety::Normal => stable_mir::mir::Safety::Normal,
+        }
+    }
+}
+
+impl Stable for FieldIdx {
+    type T = usize;
+    fn stable(&self) -> Self::T {
+        self.as_usize()
+    }
+}
+
 impl<'tcx> Stable for mir::Operand<'tcx> {
     type T = stable_mir::mir::Operand;
     fn stable(&self) -> Self::T {
@@ -229,34 +352,38 @@ impl Stable for mir::UnwindAction {
     }
 }
 
-fn rustc_assert_msg_to_msg<'tcx>(
-    assert_message: &rustc_middle::mir::AssertMessage<'tcx>,
-) -> stable_mir::mir::AssertMessage {
-    use rustc_middle::mir::AssertKind;
-    match assert_message {
-        AssertKind::BoundsCheck { len, index } => {
-            stable_mir::mir::AssertMessage::BoundsCheck { len: len.stable(), index: index.stable() }
-        }
-        AssertKind::Overflow(bin_op, op1, op2) => {
-            stable_mir::mir::AssertMessage::Overflow(bin_op.stable(), op1.stable(), op2.stable())
-        }
-        AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()),
-        AssertKind::DivisionByZero(op) => {
-            stable_mir::mir::AssertMessage::DivisionByZero(op.stable())
-        }
-        AssertKind::RemainderByZero(op) => {
-            stable_mir::mir::AssertMessage::RemainderByZero(op.stable())
-        }
-        AssertKind::ResumedAfterReturn(generator) => {
-            stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable())
-        }
-        AssertKind::ResumedAfterPanic(generator) => {
-            stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable())
-        }
-        AssertKind::MisalignedPointerDereference { required, found } => {
-            stable_mir::mir::AssertMessage::MisalignedPointerDereference {
-                required: required.stable(),
-                found: found.stable(),
+impl<'tcx> Stable for mir::AssertMessage<'tcx> {
+    type T = stable_mir::mir::AssertMessage;
+    fn stable(&self) -> Self::T {
+        use rustc_middle::mir::AssertKind;
+        match self {
+            AssertKind::BoundsCheck { len, index } => stable_mir::mir::AssertMessage::BoundsCheck {
+                len: len.stable(),
+                index: index.stable(),
+            },
+            AssertKind::Overflow(bin_op, op1, op2) => stable_mir::mir::AssertMessage::Overflow(
+                bin_op.stable(),
+                op1.stable(),
+                op2.stable(),
+            ),
+            AssertKind::OverflowNeg(op) => stable_mir::mir::AssertMessage::OverflowNeg(op.stable()),
+            AssertKind::DivisionByZero(op) => {
+                stable_mir::mir::AssertMessage::DivisionByZero(op.stable())
+            }
+            AssertKind::RemainderByZero(op) => {
+                stable_mir::mir::AssertMessage::RemainderByZero(op.stable())
+            }
+            AssertKind::ResumedAfterReturn(generator) => {
+                stable_mir::mir::AssertMessage::ResumedAfterReturn(generator.stable())
+            }
+            AssertKind::ResumedAfterPanic(generator) => {
+                stable_mir::mir::AssertMessage::ResumedAfterPanic(generator.stable())
+            }
+            AssertKind::MisalignedPointerDereference { required, found } => {
+                stable_mir::mir::AssertMessage::MisalignedPointerDereference {
+                    required: required.stable(),
+                    found: found.stable(),
+                }
             }
         }
     }
@@ -381,7 +508,7 @@ impl<'tcx> Stable for mir::Terminator<'tcx> {
             Assert { cond, expected, msg, target, unwind } => Terminator::Assert {
                 cond: cond.stable(),
                 expected: *expected,
-                msg: rustc_assert_msg_to_msg(msg),
+                msg: msg.stable(),
                 target: target.as_usize(),
                 unwind: unwind.stable(),
             },
diff --git a/compiler/rustc_smir/src/stable_mir/mir/body.rs b/compiler/rustc_smir/src/stable_mir/mir/body.rs
index 468e915d1a0..fa3b0d6c559 100644
--- a/compiler/rustc_smir/src/stable_mir/mir/body.rs
+++ b/compiler/rustc_smir/src/stable_mir/mir/body.rs
@@ -1,4 +1,5 @@
-use crate::stable_mir::ty::Ty;
+use crate::rustc_internal::Opaque;
+use crate::stable_mir::{self, ty::Ty};
 
 #[derive(Clone, Debug)]
 pub struct Body {
@@ -136,12 +137,98 @@ pub enum Statement {
     Nop,
 }
 
+type Region = Opaque;
+
 // FIXME this is incomplete
 #[derive(Clone, Debug)]
 pub enum Rvalue {
-    Use(Operand),
+    /// Creates a pointer with the indicated mutability to the place.
+    ///
+    /// This is generated by pointer casts like `&v as *const _` or raw address of expressions like
+    /// `&raw v` or `addr_of!(v)`.
+    AddressOf(Mutability, Place),
+
+    /// * `Offset` has the same semantics as [`offset`](pointer::offset), except that the second
+    ///   parameter may be a `usize` as well.
+    /// * The comparison operations accept `bool`s, `char`s, signed or unsigned integers, floats,
+    ///   raw pointers, or function pointers and return a `bool`. The types of the operands must be
+    ///   matching, up to the usual caveat of the lifetimes in function pointers.
+    /// * Left and right shift operations accept signed or unsigned integers not necessarily of the
+    ///   same type and return a value of the same type as their LHS. Like in Rust, the RHS is
+    ///   truncated as needed.
+    /// * The `Bit*` operations accept signed integers, unsigned integers, or bools with matching
+    ///   types and return a value of that type.
+    /// * The remaining operations accept signed integers, unsigned integers, or floats with
+    ///   matching types and return a value of that type.
+    BinaryOp(BinOp, Operand, Operand),
+
+    /// Performs essentially all of the casts that can be performed via `as`.
+    ///
+    /// This allows for casts from/to a variety of types.
+    Cast(CastKind, Operand, Ty),
+
+    /// Same as `BinaryOp`, but yields `(T, bool)` with a `bool` indicating an error condition.
+    ///
+    /// For addition, subtraction, and multiplication on integers the error condition is set when
+    /// the infinite precision result would not be equal to the actual result.
     CheckedBinaryOp(BinOp, Operand, Operand),
+
+    /// A CopyForDeref is equivalent to a read from a place.
+    /// When such a read happens, it is guaranteed that the only use of the returned value is a
+    /// deref operation, immediately followed by one or more projections.
+    CopyForDeref(Place),
+
+    /// Computes the discriminant of the place, returning it as an integer of type
+    /// [`discriminant_ty`]. Returns zero for types without discriminant.
+    ///
+    /// The validity requirements for the underlying value are undecided for this rvalue, see
+    /// [#91095]. Note too that the value of the discriminant is not the same thing as the
+    /// variant index; use [`discriminant_for_variant`] to convert.
+    ///
+    /// [`discriminant_ty`]: crate::ty::Ty::discriminant_ty
+    /// [#91095]: https://github.com/rust-lang/rust/issues/91095
+    /// [`discriminant_for_variant`]: crate::ty::Ty::discriminant_for_variant
+    Discriminant(Place),
+
+    /// Yields the length of the place, as a `usize`.
+    ///
+    /// If the type of the place is an array, this is the array length. For slices (`[T]`, not
+    /// `&[T]`) this accesses the place's metadata to determine the length. This rvalue is
+    /// ill-formed for places of other types.
+    Len(Place),
+
+    /// Creates a reference to the place.
+    Ref(Region, BorrowKind, Place),
+
+    /// Transmutes a `*mut u8` into shallow-initialized `Box<T>`.
+    ///
+    /// This is different from a normal transmute because dataflow analysis will treat the box as
+    /// initialized but its content as uninitialized. Like other pointer casts, this in general
+    /// affects alias analysis.
+    ShallowInitBox(Operand, Ty),
+
+    /// Creates a pointer/reference to the given thread local.
+    ///
+    /// The yielded type is a `*mut T` if the static is mutable, otherwise if the static is extern a
+    /// `*const T`, and if neither of those apply a `&T`.
+    ///
+    /// **Note:** This is a runtime operation that actually executes code and is in this sense more
+    /// like a function call. Also, eliminating dead stores of this rvalue causes `fn main() {}` to
+    /// SIGILL for some reason that I (JakobDegen) never got a chance to look into.
+    ///
+    /// **Needs clarification**: Are there weird additional semantics here related to the runtime
+    /// nature of this operation?
+    ThreadLocalRef(stable_mir::CrateItem),
+
+    /// Exactly like `BinaryOp`, but less operands.
+    ///
+    /// Also does two's-complement arithmetic. Negation requires a signed integer or a float;
+    /// bitwise not requires a signed integer, unsigned integer, or bool. Both operation kinds
+    /// return a value with the same type as their operand.
     UnaryOp(UnOp, Operand),
+
+    /// Yields the operand unchanged
+    Use(Operand),
 }
 
 #[derive(Clone, Debug)]
@@ -157,8 +244,98 @@ pub struct Place {
     pub projection: String,
 }
 
+type FieldIdx = usize;
+
 #[derive(Clone, Debug)]
 pub struct SwitchTarget {
     pub value: u128,
     pub target: usize,
 }
+
+#[derive(Clone, Debug)]
+pub enum BorrowKind {
+    /// Data must be immutable and is aliasable.
+    Shared,
+
+    /// The immediately borrowed place must be immutable, but projections from
+    /// it don't need to be. For example, a shallow borrow of `a.b` doesn't
+    /// conflict with a mutable borrow of `a.b.c`.
+    Shallow,
+
+    /// Data is mutable and not aliasable.
+    Mut {
+        /// `true` if this borrow arose from method-call auto-ref
+        kind: MutBorrowKind,
+    },
+}
+
+#[derive(Clone, Debug)]
+pub enum MutBorrowKind {
+    Default,
+    TwoPhaseBorrow,
+    ClosureCapture,
+}
+
+#[derive(Clone, Debug)]
+pub enum Mutability {
+    Not,
+    Mut,
+}
+
+#[derive(Clone, Debug)]
+pub enum Safety {
+    Unsafe,
+    Normal,
+}
+
+#[derive(Clone, Debug)]
+pub enum PointerCoercion {
+    /// Go from a fn-item type to a fn-pointer type.
+    ReifyFnPointer,
+
+    /// Go from a safe fn pointer to an unsafe fn pointer.
+    UnsafeFnPointer,
+
+    /// Go from a non-capturing closure to an fn pointer or an unsafe fn pointer.
+    /// It cannot convert a closure that requires unsafe.
+    ClosureFnPointer(Safety),
+
+    /// Go from a mut raw pointer to a const raw pointer.
+    MutToConstPointer,
+
+    /// Go from `*const [T; N]` to `*const T`
+    ArrayToPointer,
+
+    /// Unsize a pointer/reference value, e.g., `&[T; n]` to
+    /// `&[T]`. Note that the source could be a thin or fat pointer.
+    /// This will do things like convert thin pointers to fat
+    /// pointers, or convert structs containing thin pointers to
+    /// structs containing fat pointers, or convert between fat
+    /// pointers.
+    Unsize,
+}
+
+#[derive(Clone, Debug)]
+pub enum CastKind {
+    PointerExposeAddress,
+    PointerFromExposedAddress,
+    PointerCoercion(PointerCoercion),
+    DynStar,
+    IntToInt,
+    FloatToInt,
+    FloatToFloat,
+    IntToFloat,
+    PtrToPtr,
+    FnPtrToPtr,
+    Transmute,
+}
+
+#[derive(Clone, Debug)]
+pub enum NullOp {
+    /// Returns the size of a value of that type.
+    SizeOf,
+    /// Returns the minimum alignment of a type.
+    AlignOf,
+    /// Returns the offset of a field.
+    OffsetOf(Vec<FieldIdx>),
+}
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 5c6d43e50ea..d655276a991 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1152,8 +1152,10 @@ symbols! {
         profiler_runtime,
         ptr,
         ptr_cast_mut,
+        ptr_const_is_null,
         ptr_from_ref,
         ptr_guaranteed_cmp,
+        ptr_is_null,
         ptr_mask,
         ptr_null,
         ptr_null_mut,
diff --git a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
index f342180590f..4dc06d2bfac 100644
--- a/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/error_reporting/mod.rs
@@ -1640,6 +1640,8 @@ impl<'tcx> InferCtxtPrivExt<'tcx> for TypeErrCtxt<'_, 'tcx> {
                     )
                     .into(),
                 };
+                // FIXME(-Ztrait-solver=next): For diagnostic purposes, it would be nice
+                // to deeply normalize this type.
                 let normalized_term =
                     ocx.normalize(&obligation.cause, obligation.param_env, unnormalized_term);
 
diff --git a/compiler/rustc_trait_selection/src/traits/project.rs b/compiler/rustc_trait_selection/src/traits/project.rs
index a10bca31ff1..4ccfb54ff7c 100644
--- a/compiler/rustc_trait_selection/src/traits/project.rs
+++ b/compiler/rustc_trait_selection/src/traits/project.rs
@@ -131,8 +131,6 @@ enum ProjectionCandidate<'tcx> {
 
     /// From an "impl" (or a "pseudo-impl" returned by select)
     Select(Selection<'tcx>),
-
-    ImplTraitInTrait(ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>),
 }
 
 enum ProjectionCandidateSet<'tcx> {
@@ -1472,8 +1470,6 @@ fn project<'cx, 'tcx>(
 
     let mut candidates = ProjectionCandidateSet::None;
 
-    assemble_candidate_for_impl_trait_in_trait(selcx, obligation, &mut candidates);
-
     // Make sure that the following procedures are kept in order. ParamEnv
     // needs to be first because it has highest priority, and Select checks
     // the return value of push_candidate which assumes it's ran at last.
@@ -1499,7 +1495,7 @@ fn project<'cx, 'tcx>(
         ProjectionCandidateSet::None => {
             let tcx = selcx.tcx();
             let term = match tcx.def_kind(obligation.predicate.def_id) {
-                DefKind::AssocTy | DefKind::ImplTraitPlaceholder => Ty::new_projection(
+                DefKind::AssocTy => Ty::new_projection(
                     tcx,
                     obligation.predicate.def_id,
                     obligation.predicate.substs,
@@ -1530,47 +1526,6 @@ fn project<'cx, 'tcx>(
     }
 }
 
-/// If the predicate's item is an `ImplTraitPlaceholder`, we do a select on the
-/// corresponding trait ref. If this yields an `impl`, then we're able to project
-/// to a concrete type, since we have an `impl`'s method  to provide the RPITIT.
-fn assemble_candidate_for_impl_trait_in_trait<'cx, 'tcx>(
-    selcx: &mut SelectionContext<'cx, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    candidate_set: &mut ProjectionCandidateSet<'tcx>,
-) {
-    let tcx = selcx.tcx();
-    if tcx.def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
-        let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
-
-        let trait_def_id = tcx.parent(trait_fn_def_id);
-        let trait_substs =
-            obligation.predicate.substs.truncate_to(tcx, tcx.generics_of(trait_def_id));
-        let trait_predicate = ty::TraitRef::new(tcx, trait_def_id, trait_substs);
-
-        let _ = selcx.infcx.commit_if_ok(|_| {
-            match selcx.select(&obligation.with(tcx, trait_predicate)) {
-                Ok(Some(super::ImplSource::UserDefined(data))) => {
-                    candidate_set.push_candidate(ProjectionCandidate::ImplTraitInTrait(data));
-                    Ok(())
-                }
-                Ok(None) => {
-                    candidate_set.mark_ambiguous();
-                    Err(())
-                }
-                Ok(Some(_)) => {
-                    // Don't know enough about the impl to provide a useful signature
-                    Err(())
-                }
-                Err(e) => {
-                    debug!(error = ?e, "selection error");
-                    candidate_set.mark_error(e);
-                    Err(())
-                }
-            }
-        });
-    }
-}
-
 /// The first thing we have to do is scan through the parameter
 /// environment to see whether there are any projection predicates
 /// there that can answer this question.
@@ -1739,11 +1694,6 @@ fn assemble_candidates_from_impls<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     candidate_set: &mut ProjectionCandidateSet<'tcx>,
 ) {
-    // Can't assemble candidate from impl for RPITIT
-    if selcx.tcx().def_kind(obligation.predicate.def_id) == DefKind::ImplTraitPlaceholder {
-        return;
-    }
-
     // If we are resolving `<T as TraitRef<...>>::Item == Type`,
     // start out by selecting the predicate `T as TraitRef<...>`:
     let trait_ref = obligation.predicate.trait_ref(selcx.tcx());
@@ -2012,9 +1962,6 @@ fn confirm_candidate<'cx, 'tcx>(
         ProjectionCandidate::Select(impl_source) => {
             confirm_select_candidate(selcx, obligation, impl_source)
         }
-        ProjectionCandidate::ImplTraitInTrait(data) => {
-            confirm_impl_trait_in_trait_candidate(selcx, obligation, data)
-        }
     };
 
     // When checking for cycle during evaluation, we compare predicates with
@@ -2240,8 +2187,7 @@ fn confirm_closure_candidate<'cx, 'tcx>(
     obligation: &ProjectionTyObligation<'tcx>,
     nested: Vec<PredicateObligation<'tcx>>,
 ) -> Progress<'tcx> {
-    let ty::Closure(_, substs) =
-        selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
+    let ty::Closure(_, substs) = selcx.infcx.shallow_resolve(obligation.predicate.self_ty()).kind()
     else {
         unreachable!()
     };
@@ -2419,103 +2365,6 @@ fn confirm_impl_candidate<'cx, 'tcx>(
     }
 }
 
-fn confirm_impl_trait_in_trait_candidate<'tcx>(
-    selcx: &mut SelectionContext<'_, 'tcx>,
-    obligation: &ProjectionTyObligation<'tcx>,
-    data: ImplSourceUserDefinedData<'tcx, PredicateObligation<'tcx>>,
-) -> Progress<'tcx> {
-    let tcx = selcx.tcx();
-    let mut obligations = data.nested;
-
-    let trait_fn_def_id = tcx.impl_trait_in_trait_parent_fn(obligation.predicate.def_id);
-    let leaf_def = match specialization_graph::assoc_def(tcx, data.impl_def_id, trait_fn_def_id) {
-        Ok(assoc_ty) => assoc_ty,
-        Err(guar) => return Progress::error(tcx, guar),
-    };
-    // We don't support specialization for RPITITs anyways... yet.
-    // Also don't try to project to an RPITIT that has no value
-    if !leaf_def.is_final() || !leaf_def.item.defaultness(tcx).has_value() {
-        return Progress { term: Ty::new_misc_error(tcx).into(), obligations };
-    }
-
-    // Use the default `impl Trait` for the trait, e.g., for a default trait body
-    if leaf_def.item.container == ty::AssocItemContainer::TraitContainer {
-        return Progress {
-            term: Ty::new_opaque(tcx, obligation.predicate.def_id, obligation.predicate.substs)
-                .into(),
-            obligations,
-        };
-    }
-
-    // Rebase from {trait}::{fn}::{opaque} to {impl}::{fn}::{opaque},
-    // since `data.substs` are the impl substs.
-    let impl_fn_substs =
-        obligation.predicate.substs.rebase_onto(tcx, tcx.parent(trait_fn_def_id), data.substs);
-    let impl_fn_substs = translate_substs(
-        selcx.infcx,
-        obligation.param_env,
-        data.impl_def_id,
-        impl_fn_substs,
-        leaf_def.defining_node,
-    );
-
-    if !check_substs_compatible(tcx, leaf_def.item, impl_fn_substs) {
-        let err = Ty::new_error_with_message(
-            tcx,
-            obligation.cause.span,
-            "impl method and trait method have different parameters",
-        );
-        return Progress { term: err.into(), obligations };
-    }
-
-    let impl_fn_def_id = leaf_def.item.def_id;
-
-    let cause = ObligationCause::new(
-        obligation.cause.span,
-        obligation.cause.body_id,
-        super::ItemObligation(impl_fn_def_id),
-    );
-    let predicates = normalize_with_depth_to(
-        selcx,
-        obligation.param_env,
-        cause.clone(),
-        obligation.recursion_depth + 1,
-        tcx.predicates_of(impl_fn_def_id).instantiate(tcx, impl_fn_substs),
-        &mut obligations,
-    );
-    obligations.extend(predicates.into_iter().map(|(pred, span)| {
-        Obligation::with_depth(
-            tcx,
-            ObligationCause::new(
-                obligation.cause.span,
-                obligation.cause.body_id,
-                if span.is_dummy() {
-                    super::ItemObligation(impl_fn_def_id)
-                } else {
-                    super::BindingObligation(impl_fn_def_id, span)
-                },
-            ),
-            obligation.recursion_depth + 1,
-            obligation.param_env,
-            pred,
-        )
-    }));
-
-    let ty = normalize_with_depth_to(
-        selcx,
-        obligation.param_env,
-        cause.clone(),
-        obligation.recursion_depth + 1,
-        tcx.collect_return_position_impl_trait_in_trait_tys(impl_fn_def_id).map_or_else(
-            |guar| Ty::new_error(tcx, guar),
-            |tys| tys[&obligation.predicate.def_id].subst(tcx, impl_fn_substs),
-        ),
-        &mut obligations,
-    );
-
-    Progress { term: ty.into(), obligations }
-}
-
 // Get obligations corresponding to the predicates from the where-clause of the
 // associated type itself.
 fn assoc_ty_own_obligations<'cx, 'tcx>(
diff --git a/compiler/rustc_ty_utils/src/assoc.rs b/compiler/rustc_ty_utils/src/assoc.rs
index 897e7aad48b..7e22ef89ed3 100644
--- a/compiler/rustc_ty_utils/src/assoc.rs
+++ b/compiler/rustc_ty_utils/src/assoc.rs
@@ -24,70 +24,54 @@ fn associated_item_def_ids(tcx: TyCtxt<'_>, def_id: LocalDefId) -> &[DefId] {
     let item = tcx.hir().expect_item(def_id);
     match item.kind {
         hir::ItemKind::Trait(.., ref trait_item_refs) => {
-            if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-                // We collect RPITITs for each trait method's return type and create a
-                // corresponding associated item using associated_types_for_impl_traits_in_associated_fn
-                // query.
-                tcx.arena.alloc_from_iter(
-                    trait_item_refs
-                        .iter()
-                        .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
-                        .chain(
-                            trait_item_refs
-                                .iter()
-                                .filter(|trait_item_ref| {
-                                    matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
-                                })
-                                .flat_map(|trait_item_ref| {
-                                    let trait_fn_def_id =
-                                        trait_item_ref.id.owner_id.def_id.to_def_id();
-                                    tcx.associated_types_for_impl_traits_in_associated_fn(
-                                        trait_fn_def_id,
-                                    )
-                                })
-                                .map(|def_id| *def_id),
-                        ),
-                )
-            } else {
-                tcx.arena.alloc_from_iter(
-                    trait_item_refs
-                        .iter()
-                        .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id()),
-                )
-            }
+            // We collect RPITITs for each trait method's return type and create a
+            // corresponding associated item using associated_types_for_impl_traits_in_associated_fn
+            // query.
+            tcx.arena.alloc_from_iter(
+                trait_item_refs
+                    .iter()
+                    .map(|trait_item_ref| trait_item_ref.id.owner_id.to_def_id())
+                    .chain(
+                        trait_item_refs
+                            .iter()
+                            .filter(|trait_item_ref| {
+                                matches!(trait_item_ref.kind, hir::AssocItemKind::Fn { .. })
+                            })
+                            .flat_map(|trait_item_ref| {
+                                let trait_fn_def_id = trait_item_ref.id.owner_id.def_id.to_def_id();
+                                tcx.associated_types_for_impl_traits_in_associated_fn(
+                                    trait_fn_def_id,
+                                )
+                            })
+                            .map(|def_id| *def_id),
+                    ),
+            )
         }
         hir::ItemKind::Impl(ref impl_) => {
-            if tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-                // We collect RPITITs for each trait method's return type, on the impl side too and
-                // create a corresponding associated item using
-                // associated_types_for_impl_traits_in_associated_fn query.
-                tcx.arena.alloc_from_iter(
-                    impl_
-                        .items
-                        .iter()
-                        .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
-                        .chain(impl_.of_trait.iter().flat_map(|_| {
-                            impl_
-                                .items
-                                .iter()
-                                .filter(|impl_item_ref| {
-                                    matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
-                                })
-                                .flat_map(|impl_item_ref| {
-                                    let impl_fn_def_id =
-                                        impl_item_ref.id.owner_id.def_id.to_def_id();
-                                    tcx.associated_types_for_impl_traits_in_associated_fn(
-                                        impl_fn_def_id,
-                                    )
-                                })
-                                .map(|def_id| *def_id)
-                        })),
-                )
-            } else {
-                tcx.arena.alloc_from_iter(
-                    impl_.items.iter().map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id()),
-                )
-            }
+            // We collect RPITITs for each trait method's return type, on the impl side too and
+            // create a corresponding associated item using
+            // associated_types_for_impl_traits_in_associated_fn query.
+            tcx.arena.alloc_from_iter(
+                impl_
+                    .items
+                    .iter()
+                    .map(|impl_item_ref| impl_item_ref.id.owner_id.to_def_id())
+                    .chain(impl_.of_trait.iter().flat_map(|_| {
+                        impl_
+                            .items
+                            .iter()
+                            .filter(|impl_item_ref| {
+                                matches!(impl_item_ref.kind, hir::AssocItemKind::Fn { .. })
+                            })
+                            .flat_map(|impl_item_ref| {
+                                let impl_fn_def_id = impl_item_ref.id.owner_id.def_id.to_def_id();
+                                tcx.associated_types_for_impl_traits_in_associated_fn(
+                                    impl_fn_def_id,
+                                )
+                            })
+                            .map(|def_id| *def_id)
+                    })),
+            )
         }
         _ => span_bug!(item.span, "associated_item_def_ids: not impl or trait"),
     }
diff --git a/compiler/rustc_ty_utils/src/implied_bounds.rs b/compiler/rustc_ty_utils/src/implied_bounds.rs
index 10dec9a7a32..2822595a8a7 100644
--- a/compiler/rustc_ty_utils/src/implied_bounds.rs
+++ b/compiler/rustc_ty_utils/src/implied_bounds.rs
@@ -75,7 +75,6 @@ fn assumed_wf_types<'tcx>(tcx: TyCtxt<'tcx>, def_id: LocalDefId) -> &'tcx [(Ty<'
         | DefKind::ForeignMod
         | DefKind::AnonConst
         | DefKind::InlineConst
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 570c3b245cd..87dfacc4c2d 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -318,7 +318,6 @@ fn opaque_types_defined_by<'tcx>(tcx: TyCtxt<'tcx>, item: LocalDefId) -> &'tcx [
         | DefKind::ExternCrate
         | DefKind::Use
         | DefKind::ForeignMod
-        | DefKind::ImplTraitPlaceholder
         | DefKind::Field
         | DefKind::LifetimeParam
         | DefKind::GlobalAsm
diff --git a/compiler/rustc_ty_utils/src/ty.rs b/compiler/rustc_ty_utils/src/ty.rs
index 6e5c50492c6..43e3c99fb57 100644
--- a/compiler/rustc_ty_utils/src/ty.rs
+++ b/compiler/rustc_ty_utils/src/ty.rs
@@ -282,11 +282,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for ImplTraitInTraitFinder<'_, 'tcx> {
             // If we're lowering to associated item, install the opaque type which is just
             // the `type_of` of the trait's associated item. If we're using the old lowering
             // strategy, then just reinterpret the associated type like an opaque :^)
-            let default_ty = if self.tcx.lower_impl_trait_in_trait_to_assoc_ty() {
-                self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs)
-            } else {
-                Ty::new_alias(self.tcx,ty::Opaque, shifted_alias_ty)
-            };
+            let default_ty = self.tcx.type_of(shifted_alias_ty.def_id).subst(self.tcx, shifted_alias_ty.substs);
 
             self.predicates.push(
                 ty::Binder::bind_with_vars(
@@ -408,9 +404,7 @@ fn unsizing_params_for_adt<'tcx>(tcx: TyCtxt<'tcx>, def_id: DefId) -> BitSet<u32
     };
 
     // The last field of the structure has to exist and contain type/const parameters.
-    let Some((tail_field, prefix_fields)) =
-        def.non_enum_variant().fields.raw.split_last() else
-    {
+    let Some((tail_field, prefix_fields)) = def.non_enum_variant().fields.raw.split_last() else {
         return BitSet::new_empty(num_params);
     };
 
diff --git a/compiler/rustc_type_ir/src/lib.rs b/compiler/rustc_type_ir/src/lib.rs
index 878a6b784ed..9ca26d18ae1 100644
--- a/compiler/rustc_type_ir/src/lib.rs
+++ b/compiler/rustc_type_ir/src/lib.rs
@@ -31,6 +31,7 @@ mod macros;
 mod structural_impls;
 
 pub use codec::*;
+pub use structural_impls::{DebugWithInfcx, InferCtxtLike, OptWithInfcx};
 pub use sty::*;
 pub use ty_info::*;
 
@@ -39,41 +40,41 @@ pub trait HashStableContext {}
 
 pub trait Interner: Sized {
     type AdtDef: Clone + Debug + Hash + Ord;
-    type SubstsRef: Clone + Debug + Hash + Ord;
+    type SubstsRef: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type DefId: Clone + Debug + Hash + Ord;
     type Binder<T>;
-    type Ty: Clone + Debug + Hash + Ord;
-    type Const: Clone + Debug + Hash + Ord;
-    type Region: Clone + Debug + Hash + Ord;
+    type Ty: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type Const: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type Region: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type Predicate;
     type TypeAndMut: Clone + Debug + Hash + Ord;
     type Mutability: Clone + Debug + Hash + Ord;
     type Movability: Clone + Debug + Hash + Ord;
-    type PolyFnSig: Clone + Debug + Hash + Ord;
-    type ListBinderExistentialPredicate: Clone + Debug + Hash + Ord;
-    type BinderListTy: Clone + Debug + Hash + Ord;
+    type PolyFnSig: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type ListBinderExistentialPredicate: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type BinderListTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type ListTy: Clone + Debug + Hash + Ord + IntoIterator<Item = Self::Ty>;
-    type AliasTy: Clone + Debug + Hash + Ord;
+    type AliasTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type ParamTy: Clone + Debug + Hash + Ord;
     type BoundTy: Clone + Debug + Hash + Ord;
     type PlaceholderType: Clone + Debug + Hash + Ord;
+    type InferTy: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type ErrorGuaranteed: Clone + Debug + Hash + Ord;
     type PredicateKind: Clone + Debug + Hash + PartialEq + Eq;
     type AllocId: Clone + Debug + Hash + Ord;
 
-    type InferConst: Clone + Debug + Hash + Ord;
-    type AliasConst: Clone + Debug + Hash + Ord;
+    type InferConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
+    type AliasConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type PlaceholderConst: Clone + Debug + Hash + Ord;
     type ParamConst: Clone + Debug + Hash + Ord;
     type BoundConst: Clone + Debug + Hash + Ord;
-    type InferTy: Clone + Debug + Hash + Ord;
     type ValueConst: Clone + Debug + Hash + Ord;
-    type ExprConst: Clone + Debug + Hash + Ord;
+    type ExprConst: Clone + DebugWithInfcx<Self> + Hash + Ord;
 
     type EarlyBoundRegion: Clone + Debug + Hash + Ord;
     type BoundRegion: Clone + Debug + Hash + Ord;
     type FreeRegion: Clone + Debug + Hash + Ord;
-    type RegionVid: Clone + Debug + Hash + Ord;
+    type RegionVid: Clone + DebugWithInfcx<Self> + Hash + Ord;
     type PlaceholderRegion: Clone + Debug + Hash + Ord;
 
     fn ty_and_mut_to_parts(ty_and_mut: Self::TypeAndMut) -> (Self::Ty, Self::Mutability);
@@ -775,20 +776,6 @@ impl fmt::Debug for FloatVid {
     }
 }
 
-impl fmt::Debug for InferTy {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        use InferTy::*;
-        match *self {
-            TyVar(ref v) => v.fmt(f),
-            IntVar(ref v) => v.fmt(f),
-            FloatVar(ref v) => v.fmt(f),
-            FreshTy(v) => write!(f, "FreshTy({v:?})"),
-            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
-            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
-        }
-    }
-}
-
 impl fmt::Debug for Variance {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         f.write_str(match *self {
diff --git a/compiler/rustc_type_ir/src/structural_impls.rs b/compiler/rustc_type_ir/src/structural_impls.rs
index 1e42175f6e3..1a2d6d64eb0 100644
--- a/compiler/rustc_type_ir/src/structural_impls.rs
+++ b/compiler/rustc_type_ir/src/structural_impls.rs
@@ -4,12 +4,13 @@
 
 use crate::fold::{FallibleTypeFolder, TypeFoldable};
 use crate::visit::{TypeVisitable, TypeVisitor};
-use crate::{ConstKind, FloatTy, IntTy, Interner, UintTy};
+use crate::{ConstKind, FloatTy, InferTy, IntTy, Interner, UintTy, UniverseIndex};
 use rustc_data_structures::functor::IdFunctor;
 use rustc_data_structures::sync::Lrc;
 use rustc_index::{Idx, IndexVec};
 
 use core::fmt;
+use std::marker::PhantomData;
 use std::ops::ControlFlow;
 
 ///////////////////////////////////////////////////////////////////////////
@@ -165,6 +166,116 @@ impl<I: Interner, T: TypeVisitable<I>, Ix: Idx> TypeVisitable<I> for IndexVec<Ix
     }
 }
 
+///////////////////////////////////////////////////
+//  Debug impls
+
+pub trait InferCtxtLike<I: Interner> {
+    fn universe_of_ty(&self, ty: I::InferTy) -> Option<UniverseIndex>;
+    fn universe_of_lt(&self, lt: I::RegionVid) -> Option<UniverseIndex>;
+    fn universe_of_ct(&self, ct: I::InferConst) -> Option<UniverseIndex>;
+}
+
+impl<I: Interner> InferCtxtLike<I> for core::convert::Infallible {
+    fn universe_of_ty(&self, _ty: <I as Interner>::InferTy) -> Option<UniverseIndex> {
+        match *self {}
+    }
+    fn universe_of_ct(&self, _ct: <I as Interner>::InferConst) -> Option<UniverseIndex> {
+        match *self {}
+    }
+    fn universe_of_lt(&self, _lt: <I as Interner>::RegionVid) -> Option<UniverseIndex> {
+        match *self {}
+    }
+}
+
+pub trait DebugWithInfcx<I: Interner>: fmt::Debug {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result;
+}
+
+impl<I: Interner, T: DebugWithInfcx<I> + ?Sized> DebugWithInfcx<I> for &'_ T {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        <T as DebugWithInfcx<I>>::fmt(this.map(|&data| data), f)
+    }
+}
+impl<I: Interner, T: DebugWithInfcx<I>> DebugWithInfcx<I> for [T] {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        match f.alternate() {
+            true => {
+                write!(f, "[\n")?;
+                for element in this.data.iter() {
+                    write!(f, "{:?},\n", &this.wrap(element))?;
+                }
+                write!(f, "]")
+            }
+            false => {
+                write!(f, "[")?;
+                if this.data.len() > 0 {
+                    for element in &this.data[..(this.data.len() - 1)] {
+                        write!(f, "{:?}, ", &this.wrap(element))?;
+                    }
+                    if let Some(element) = this.data.last() {
+                        write!(f, "{:?}", &this.wrap(element))?;
+                    }
+                }
+                write!(f, "]")
+            }
+        }
+    }
+}
+
+pub struct OptWithInfcx<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> {
+    pub data: T,
+    pub infcx: Option<&'a InfCtx>,
+    _interner: PhantomData<I>,
+}
+
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Copy> Copy for OptWithInfcx<'_, I, InfCtx, T> {}
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: Clone> Clone for OptWithInfcx<'_, I, InfCtx, T> {
+    fn clone(&self) -> Self {
+        Self { data: self.data.clone(), infcx: self.infcx, _interner: self._interner }
+    }
+}
+
+impl<'a, I: Interner, T> OptWithInfcx<'a, I, core::convert::Infallible, T> {
+    pub fn new_no_ctx(data: T) -> Self {
+        Self { data, infcx: None, _interner: PhantomData }
+    }
+}
+
+impl<'a, I: Interner, InfCtx: InferCtxtLike<I>, T> OptWithInfcx<'a, I, InfCtx, T> {
+    pub fn new(data: T, infcx: &'a InfCtx) -> Self {
+        Self { data, infcx: Some(infcx), _interner: PhantomData }
+    }
+
+    pub fn wrap<U>(self, u: U) -> OptWithInfcx<'a, I, InfCtx, U> {
+        OptWithInfcx { data: u, infcx: self.infcx, _interner: PhantomData }
+    }
+
+    pub fn map<U>(self, f: impl FnOnce(T) -> U) -> OptWithInfcx<'a, I, InfCtx, U> {
+        OptWithInfcx { data: f(self.data), infcx: self.infcx, _interner: PhantomData }
+    }
+
+    pub fn as_ref(&self) -> OptWithInfcx<'a, I, InfCtx, &T> {
+        OptWithInfcx { data: &self.data, infcx: self.infcx, _interner: PhantomData }
+    }
+}
+
+impl<I: Interner, InfCtx: InferCtxtLike<I>, T: DebugWithInfcx<I>> fmt::Debug
+    for OptWithInfcx<'_, I, InfCtx, T>
+{
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        DebugWithInfcx::fmt(self.as_ref(), f)
+    }
+}
+
 impl fmt::Debug for IntTy {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         write!(f, "{}", self.name_str())
@@ -183,20 +294,60 @@ impl fmt::Debug for FloatTy {
     }
 }
 
+impl fmt::Debug for InferTy {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        use InferTy::*;
+        match *self {
+            TyVar(ref v) => v.fmt(f),
+            IntVar(ref v) => v.fmt(f),
+            FloatVar(ref v) => v.fmt(f),
+            FreshTy(v) => write!(f, "FreshTy({v:?})"),
+            FreshIntTy(v) => write!(f, "FreshIntTy({v:?})"),
+            FreshFloatTy(v) => write!(f, "FreshFloatTy({v:?})"),
+        }
+    }
+}
+impl<I: Interner<InferTy = InferTy>> DebugWithInfcx<I> for InferTy {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        use InferTy::*;
+        match this.infcx.and_then(|infcx| infcx.universe_of_ty(*this.data)) {
+            None => write!(f, "{:?}", this.data),
+            Some(universe) => match *this.data {
+                TyVar(ty_vid) => write!(f, "?{}_{}t", ty_vid.index(), universe.index()),
+                IntVar(_) | FloatVar(_) | FreshTy(_) | FreshIntTy(_) | FreshFloatTy(_) => {
+                    unreachable!()
+                }
+            },
+        }
+    }
+}
+
 impl<I: Interner> fmt::Debug for ConstKind<I> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
+impl<I: Interner> DebugWithInfcx<I> for ConstKind<I> {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
         use ConstKind::*;
-        match self {
+
+        match this.data {
             Param(param) => write!(f, "{param:?}"),
-            Infer(var) => write!(f, "{var:?}"),
+            Infer(var) => write!(f, "{:?}", &this.wrap(var)),
             Bound(debruijn, var) => crate::debug_bound_var(f, *debruijn, var.clone()),
             Placeholder(placeholder) => write!(f, "{placeholder:?}"),
             Unevaluated(uv) => {
-                write!(f, "{uv:?}")
+                write!(f, "{:?}", &this.wrap(uv))
             }
             Value(valtree) => write!(f, "{valtree:?}"),
             Error(_) => write!(f, "{{const error}}"),
-            Expr(expr) => write!(f, "{expr:?}"),
+            Expr(expr) => write!(f, "{:?}", &this.wrap(expr)),
         }
     }
 }
diff --git a/compiler/rustc_type_ir/src/sty.rs b/compiler/rustc_type_ir/src/sty.rs
index b696f9b9b59..416e8a3d2d2 100644
--- a/compiler/rustc_type_ir/src/sty.rs
+++ b/compiler/rustc_type_ir/src/sty.rs
@@ -3,7 +3,6 @@
 use std::cmp::Ordering;
 use std::{fmt, hash};
 
-use crate::DebruijnIndex;
 use crate::FloatTy;
 use crate::HashStableContext;
 use crate::IntTy;
@@ -11,6 +10,7 @@ use crate::Interner;
 use crate::TyDecoder;
 use crate::TyEncoder;
 use crate::UintTy;
+use crate::{DebruijnIndex, DebugWithInfcx, InferCtxtLike, OptWithInfcx};
 
 use self::RegionKind::*;
 use self::TyKind::*;
@@ -503,42 +503,48 @@ impl<I: Interner> hash::Hash for TyKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Debug`
-impl<I: Interner> fmt::Debug for TyKind<I> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
+impl<I: Interner> DebugWithInfcx<I> for TyKind<I> {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> fmt::Result {
+        match this.data {
             Bool => write!(f, "bool"),
             Char => write!(f, "char"),
             Int(i) => write!(f, "{i:?}"),
             Uint(u) => write!(f, "{u:?}"),
             Float(float) => write!(f, "{float:?}"),
-            Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, s),
+            Adt(d, s) => f.debug_tuple_field2_finish("Adt", d, &this.wrap(s)),
             Foreign(d) => f.debug_tuple_field1_finish("Foreign", d),
             Str => write!(f, "str"),
-            Array(t, c) => write!(f, "[{t:?}; {c:?}]"),
-            Slice(t) => write!(f, "[{t:?}]"),
+            Array(t, c) => write!(f, "[{:?}; {:?}]", &this.wrap(t), &this.wrap(c)),
+            Slice(t) => write!(f, "[{:?}]", &this.wrap(t)),
             RawPtr(p) => {
                 let (ty, mutbl) = I::ty_and_mut_to_parts(p.clone());
                 match I::mutability_is_mut(mutbl) {
                     true => write!(f, "*mut "),
                     false => write!(f, "*const "),
                 }?;
-                write!(f, "{ty:?}")
+                write!(f, "{:?}", &this.wrap(ty))
             }
             Ref(r, t, m) => match I::mutability_is_mut(m.clone()) {
-                true => write!(f, "&{r:?} mut {t:?}"),
-                false => write!(f, "&{r:?} {t:?}"),
+                true => write!(f, "&{:?} mut {:?}", &this.wrap(r), &this.wrap(t)),
+                false => write!(f, "&{:?} {:?}", &this.wrap(r), &this.wrap(t)),
             },
-            FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, s),
-            FnPtr(s) => write!(f, "{s:?}"),
+            FnDef(d, s) => f.debug_tuple_field2_finish("FnDef", d, &this.wrap(s)),
+            FnPtr(s) => write!(f, "{:?}", &this.wrap(s)),
             Dynamic(p, r, repr) => match repr {
-                DynKind::Dyn => write!(f, "dyn {p:?} + {r:?}"),
-                DynKind::DynStar => write!(f, "dyn* {p:?} + {r:?}"),
+                DynKind::Dyn => write!(f, "dyn {:?} + {:?}", &this.wrap(p), &this.wrap(r)),
+                DynKind::DynStar => {
+                    write!(f, "dyn* {:?} + {:?}", &this.wrap(p), &this.wrap(r))
+                }
             },
-            Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, s),
-            Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, s, m),
-            GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", g),
-            GeneratorWitnessMIR(d, s) => f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, s),
+            Closure(d, s) => f.debug_tuple_field2_finish("Closure", d, &this.wrap(s)),
+            Generator(d, s, m) => f.debug_tuple_field3_finish("Generator", d, &this.wrap(s), m),
+            GeneratorWitness(g) => f.debug_tuple_field1_finish("GeneratorWitness", &this.wrap(g)),
+            GeneratorWitnessMIR(d, s) => {
+                f.debug_tuple_field2_finish("GeneratorWitnessMIR", d, &this.wrap(s))
+            }
             Never => write!(f, "!"),
             Tuple(t) => {
                 let mut iter = t.clone().into_iter();
@@ -547,28 +553,34 @@ impl<I: Interner> fmt::Debug for TyKind<I> {
 
                 match iter.next() {
                     None => return write!(f, ")"),
-                    Some(ty) => write!(f, "{ty:?}")?,
+                    Some(ty) => write!(f, "{:?}", &this.wrap(ty))?,
                 };
 
                 match iter.next() {
                     None => return write!(f, ",)"),
-                    Some(ty) => write!(f, "{ty:?})")?,
+                    Some(ty) => write!(f, "{:?})", &this.wrap(ty))?,
                 }
 
                 for ty in iter {
-                    write!(f, ", {ty:?}")?;
+                    write!(f, ", {:?}", &this.wrap(ty))?;
                 }
                 write!(f, ")")
             }
-            Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, a),
+            Alias(i, a) => f.debug_tuple_field2_finish("Alias", i, &this.wrap(a)),
             Param(p) => write!(f, "{p:?}"),
             Bound(d, b) => crate::debug_bound_var(f, *d, b),
             Placeholder(p) => write!(f, "{p:?}"),
-            Infer(t) => write!(f, "{t:?}"),
+            Infer(t) => write!(f, "{:?}", this.wrap(t)),
             TyKind::Error(_) => write!(f, "{{type error}}"),
         }
     }
 }
+// This is manually implemented because a derive would require `I: Debug`
+impl<I: Interner> fmt::Debug for TyKind<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
 
 // This is manually implemented because a derive would require `I: Encodable`
 impl<I: Interner, E: TyEncoder> Encodable<E> for TyKind<I>
@@ -1356,21 +1368,23 @@ impl<I: Interner> hash::Hash for RegionKind<I> {
     }
 }
 
-// This is manually implemented because a derive would require `I: Debug`
-impl<I: Interner> fmt::Debug for RegionKind<I> {
-    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        match self {
+impl<I: Interner> DebugWithInfcx<I> for RegionKind<I> {
+    fn fmt<InfCtx: InferCtxtLike<I>>(
+        this: OptWithInfcx<'_, I, InfCtx, &Self>,
+        f: &mut core::fmt::Formatter<'_>,
+    ) -> core::fmt::Result {
+        match this.data {
             ReEarlyBound(data) => write!(f, "ReEarlyBound({data:?})"),
 
             ReLateBound(binder_id, bound_region) => {
                 write!(f, "ReLateBound({binder_id:?}, {bound_region:?})")
             }
 
-            ReFree(fr) => fr.fmt(f),
+            ReFree(fr) => write!(f, "{fr:?}"),
 
             ReStatic => f.write_str("ReStatic"),
 
-            ReVar(vid) => vid.fmt(f),
+            ReVar(vid) => write!(f, "{:?}", &this.wrap(vid)),
 
             RePlaceholder(placeholder) => write!(f, "RePlaceholder({placeholder:?})"),
 
@@ -1380,6 +1394,11 @@ impl<I: Interner> fmt::Debug for RegionKind<I> {
         }
     }
 }
+impl<I: Interner> fmt::Debug for RegionKind<I> {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        OptWithInfcx::new_no_ctx(self).fmt(f)
+    }
+}
 
 // This is manually implemented because a derive would require `I: Encodable`
 impl<I: Interner, E: TyEncoder> Encodable<E> for RegionKind<I>
diff --git a/library/core/src/mem/transmutability.rs b/library/core/src/mem/transmutability.rs
index 3805d149b70..aed23119fd2 100644
--- a/library/core/src/mem/transmutability.rs
+++ b/library/core/src/mem/transmutability.rs
@@ -9,6 +9,7 @@ use crate::marker::ConstParamTy;
 #[lang = "transmute_trait"]
 #[cfg_attr(not(bootstrap), rustc_deny_explicit_impl(implement_via_object = false))]
 #[cfg_attr(bootstrap, rustc_deny_explicit_impl)]
+#[rustc_coinductive]
 pub unsafe trait BikeshedIntrinsicFrom<Src, Context, const ASSUME: Assume = { Assume::NOTHING }>
 where
     Src: ?Sized,
diff --git a/library/core/src/ptr/const_ptr.rs b/library/core/src/ptr/const_ptr.rs
index 926189a17b2..74046a9c7c3 100644
--- a/library/core/src/ptr/const_ptr.rs
+++ b/library/core/src/ptr/const_ptr.rs
@@ -30,6 +30,7 @@ impl<T: ?Sized> *const T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
+    #[rustc_diagnostic_item = "ptr_const_is_null"]
     #[inline]
     pub const fn is_null(self) -> bool {
         #[inline]
diff --git a/library/core/src/ptr/mut_ptr.rs b/library/core/src/ptr/mut_ptr.rs
index c6f43857887..e7f27439540 100644
--- a/library/core/src/ptr/mut_ptr.rs
+++ b/library/core/src/ptr/mut_ptr.rs
@@ -29,6 +29,7 @@ impl<T: ?Sized> *mut T {
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
     #[rustc_const_unstable(feature = "const_ptr_is_null", issue = "74939")]
+    #[rustc_diagnostic_item = "ptr_is_null"]
     #[inline]
     pub const fn is_null(self) -> bool {
         #[inline]
diff --git a/library/std/src/fs.rs b/library/std/src/fs.rs
index c2d82169dc3..0f79e74f555 100644
--- a/library/std/src/fs.rs
+++ b/library/std/src/fs.rs
@@ -16,6 +16,7 @@ use crate::fmt;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, Read, Seek, SeekFrom, Write};
 use crate::path::{Path, PathBuf};
 use crate::sealed::Sealed;
+use crate::sync::Arc;
 use crate::sys::fs as fs_imp;
 use crate::sys_common::{AsInner, AsInnerMut, FromInner, IntoInner};
 use crate::time::SystemTime;
@@ -743,7 +744,7 @@ fn buffer_capacity_required(mut file: &File) -> Option<usize> {
 }
 
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Read for File {
+impl Read for &File {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
         self.inner.read(buf)
     }
@@ -776,7 +777,7 @@ impl Read for File {
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Write for File {
+impl Write for &File {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
         self.inner.write(buf)
     }
@@ -795,67 +796,99 @@ impl Write for File {
     }
 }
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Seek for File {
+impl Seek for &File {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
         self.inner.seek(pos)
     }
 }
+
 #[stable(feature = "rust1", since = "1.0.0")]
-impl Read for &File {
+impl Read for File {
     fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
-        self.inner.read(buf)
+        (&*self).read(buf)
+    }
+    fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
+        (&*self).read_vectored(bufs)
     }
-
     fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
-        self.inner.read_buf(cursor)
+        (&*self).read_buf(cursor)
+    }
+    #[inline]
+    fn is_read_vectored(&self) -> bool {
+        (&&*self).is_read_vectored()
+    }
+    fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
+        (&*self).read_to_end(buf)
+    }
+    fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
+        (&*self).read_to_string(buf)
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Write for File {
+    fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
+        (&*self).write(buf)
+    }
+    fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
+        (&*self).write_vectored(bufs)
+    }
+    #[inline]
+    fn is_write_vectored(&self) -> bool {
+        (&&*self).is_write_vectored()
+    }
+    fn flush(&mut self) -> io::Result<()> {
+        (&*self).flush()
+    }
+}
+#[stable(feature = "rust1", since = "1.0.0")]
+impl Seek for File {
+    fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
+        (&*self).seek(pos)
     }
+}
 
+#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")]
+impl Read for Arc<File> {
+    fn read(&mut self, buf: &mut [u8]) -> io::Result<usize> {
+        (&**self).read(buf)
+    }
     fn read_vectored(&mut self, bufs: &mut [IoSliceMut<'_>]) -> io::Result<usize> {
-        self.inner.read_vectored(bufs)
+        (&**self).read_vectored(bufs)
+    }
+    fn read_buf(&mut self, cursor: BorrowedCursor<'_>) -> io::Result<()> {
+        (&**self).read_buf(cursor)
     }
-
     #[inline]
     fn is_read_vectored(&self) -> bool {
-        self.inner.is_read_vectored()
+        (&**self).is_read_vectored()
     }
-
-    // Reserves space in the buffer based on the file size when available.
     fn read_to_end(&mut self, buf: &mut Vec<u8>) -> io::Result<usize> {
-        let size = buffer_capacity_required(self);
-        buf.reserve(size.unwrap_or(0));
-        io::default_read_to_end(self, buf, size)
+        (&**self).read_to_end(buf)
     }
-
-    // Reserves space in the buffer based on the file size when available.
     fn read_to_string(&mut self, buf: &mut String) -> io::Result<usize> {
-        let size = buffer_capacity_required(self);
-        buf.reserve(size.unwrap_or(0));
-        io::default_read_to_string(self, buf, size)
+        (&**self).read_to_string(buf)
     }
 }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Write for &File {
+#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")]
+impl Write for Arc<File> {
     fn write(&mut self, buf: &[u8]) -> io::Result<usize> {
-        self.inner.write(buf)
+        (&**self).write(buf)
     }
-
     fn write_vectored(&mut self, bufs: &[IoSlice<'_>]) -> io::Result<usize> {
-        self.inner.write_vectored(bufs)
+        (&**self).write_vectored(bufs)
     }
-
     #[inline]
     fn is_write_vectored(&self) -> bool {
-        self.inner.is_write_vectored()
+        (&**self).is_write_vectored()
     }
-
     fn flush(&mut self) -> io::Result<()> {
-        self.inner.flush()
+        (&**self).flush()
     }
 }
-#[stable(feature = "rust1", since = "1.0.0")]
-impl Seek for &File {
+#[stable(feature = "io_traits_arc", since = "CURRENT_RUSTC_VERSION")]
+impl Seek for Arc<File> {
     fn seek(&mut self, pos: SeekFrom) -> io::Result<u64> {
-        self.inner.seek(pos)
+        (&**self).seek(pos)
     }
 }
 
diff --git a/library/std/src/io/readbuf.rs b/library/std/src/io/readbuf.rs
index 4800eeda022..1f3f80b9618 100644
--- a/library/std/src/io/readbuf.rs
+++ b/library/std/src/io/readbuf.rs
@@ -99,6 +99,13 @@ impl<'data> BorrowedBuf<'data> {
         unsafe { MaybeUninit::slice_assume_init_ref(&self.buf[0..self.filled]) }
     }
 
+    /// Returns a mutable reference to the filled portion of the buffer.
+    #[inline]
+    pub fn filled_mut(&mut self) -> &mut [u8] {
+        // SAFETY: We only slice the filled part of the buffer, which is always valid
+        unsafe { MaybeUninit::slice_assume_init_mut(&mut self.buf[0..self.filled]) }
+    }
+
     /// Returns a cursor over the unfilled part of the buffer.
     #[inline]
     pub fn unfilled<'this>(&'this mut self) -> BorrowedCursor<'this> {
diff --git a/library/std/src/os/android/raw.rs b/library/std/src/os/android/raw.rs
index a255d032086..daaf3d3eac6 100644
--- a/library/std/src/os/android/raw.rs
+++ b/library/std/src/os/android/raw.rs
@@ -21,26 +21,26 @@ pub use self::arch::{blkcnt_t, blksize_t, dev_t, ino_t, mode_t, nlink_t, off_t,
 
 #[cfg(any(target_arch = "arm", target_arch = "x86"))]
 mod arch {
-    use crate::os::raw::{c_longlong, c_uchar, c_uint, c_ulong, c_ulonglong};
+    use crate::os::raw::{c_long, c_longlong, c_uchar, c_uint, c_ulong, c_ulonglong};
     use crate::os::unix::raw::{gid_t, uid_t};
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type dev_t = u64;
+    pub type dev_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type mode_t = u32;
+    pub type mode_t = c_uint;
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = u64;
+    pub type blkcnt_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blksize_t = u64;
+    pub type blksize_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type ino_t = u64;
+    pub type ino_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type nlink_t = u64;
+    pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = u64;
+    pub type off_t = i32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = i64;
+    pub type time_t = c_long;
 
     #[repr(C)]
     #[derive(Clone)]
@@ -70,18 +70,20 @@ mod arch {
         pub st_blksize: u32,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_blocks: c_ulonglong,
+
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: c_ulong,
+        pub st_atime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: c_ulong,
+        pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: c_ulong,
+        pub st_mtime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: c_ulong,
+        pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: c_ulong,
+        pub st_ctime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: c_ulong,
+        pub st_ctime_nsec: c_long,
+
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_ino: c_ulonglong,
     }
@@ -89,26 +91,26 @@ mod arch {
 
 #[cfg(target_arch = "aarch64")]
 mod arch {
-    use crate::os::raw::{c_uchar, c_ulong};
+    use crate::os::raw::{c_int, c_long, c_uint, c_ulong};
     use crate::os::unix::raw::{gid_t, uid_t};
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type dev_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type mode_t = u32;
+    pub type mode_t = c_uint;
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = u64;
+    pub type blkcnt_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blksize_t = u64;
+    pub type blksize_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type ino_t = u64;
+    pub type ino_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type nlink_t = u64;
+    pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = u64;
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = i64;
+    pub type time_t = c_long;
 
     #[repr(C)]
     #[derive(Clone)]
@@ -117,9 +119,7 @@ mod arch {
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_dev: dev_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __pad0: [c_uchar; 4],
-        #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __st_ino: ino_t,
+        pub st_ino: ino_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_mode: mode_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
@@ -131,27 +131,33 @@ mod arch {
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_rdev: dev_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub __pad3: [c_uchar; 4],
+        pub __pad1: c_ulong,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_size: off_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blksize: blksize_t,
+        pub st_blksize: c_int,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad2: c_int,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_blocks: blkcnt_t,
+        pub st_blocks: c_long,
+
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_atime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: c_ulong,
+        pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_mtime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: c_ulong,
+        pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_ctime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: c_ulong,
+        pub st_ctime_nsec: c_long,
+
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ino: ino_t,
+        pub __unused4: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __unused5: c_uint,
     }
 }
 
@@ -163,20 +169,20 @@ mod arch {
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type dev_t = u64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type mode_t = u32;
+    pub type mode_t = c_uint;
 
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blkcnt_t = u64;
+    pub type blkcnt_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type blksize_t = u64;
+    pub type blksize_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type ino_t = u64;
+    pub type ino_t = c_ulong;
     #[stable(feature = "raw_ext", since = "1.1.0")]
     pub type nlink_t = u32;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type off_t = u64;
+    pub type off_t = i64;
     #[stable(feature = "raw_ext", since = "1.1.0")]
-    pub type time_t = i64;
+    pub type time_t = c_long;
 
     #[repr(C)]
     #[derive(Clone)]
@@ -195,25 +201,30 @@ mod arch {
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_gid: gid_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub __pad0: c_uint,
+        #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_rdev: dev_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_size: i64,
+        pub st_size: off_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_blksize: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
         pub st_blocks: c_long,
+
+        #[stable(feature = "raw_ext", since = "1.1.0")]
+        pub st_atime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime: c_ulong,
+        pub st_atime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_atime_nsec: c_ulong,
+        pub st_mtime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime: c_ulong,
+        pub st_mtime_nsec: c_long,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_mtime_nsec: c_ulong,
+        pub st_ctime: time_t,
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime: c_ulong,
+        pub st_ctime_nsec: c_long,
+
         #[stable(feature = "raw_ext", since = "1.1.0")]
-        pub st_ctime_nsec: c_ulong,
-        __unused: [c_long; 3],
+        pub __pad3: [c_long; 3],
     }
 }
diff --git a/src/bootstrap/builder.rs b/src/bootstrap/builder.rs
index c9bd329d430..c0c749552e6 100644
--- a/src/bootstrap/builder.rs
+++ b/src/bootstrap/builder.rs
@@ -13,7 +13,7 @@ use std::process::Command;
 use std::time::{Duration, Instant};
 
 use crate::cache::{Cache, Interned, INTERNER};
-use crate::config::{SplitDebuginfo, TargetSelection};
+use crate::config::{DryRun, SplitDebuginfo, TargetSelection};
 use crate::doc;
 use crate::flags::{Color, Subcommand};
 use crate::install;
@@ -281,11 +281,15 @@ impl StepDescription {
 
     fn is_excluded(&self, builder: &Builder<'_>, pathset: &PathSet) -> bool {
         if builder.config.exclude.iter().any(|e| pathset.has(&e, builder.kind)) {
-            println!("Skipping {:?} because it is excluded", pathset);
+            if !matches!(builder.config.dry_run, DryRun::SelfCheck) {
+                println!("Skipping {:?} because it is excluded", pathset);
+            }
             return true;
         }
 
-        if !builder.config.exclude.is_empty() {
+        if !builder.config.exclude.is_empty()
+            && !matches!(builder.config.dry_run, DryRun::SelfCheck)
+        {
             builder.verbose(&format!(
                 "{:?} not skipped for {:?} -- not in {:?}",
                 pathset, self.name, builder.config.exclude
diff --git a/src/bootstrap/compile.rs b/src/bootstrap/compile.rs
index efe621bdb7d..caa7417011e 100644
--- a/src/bootstrap/compile.rs
+++ b/src/bootstrap/compile.rs
@@ -688,8 +688,8 @@ fn cp_rustc_component_to_ci_sysroot(
     contents: Vec<String>,
 ) {
     let sysroot = builder.ensure(Sysroot { compiler, force_recompile: false });
+    let ci_rustc_dir = builder.config.ci_rustc_dir();
 
-    let ci_rustc_dir = builder.out.join(&*builder.build.build.triple).join("ci-rustc");
     for file in contents {
         let src = ci_rustc_dir.join(&file);
         let dst = sysroot.join(file);
@@ -1424,7 +1424,7 @@ impl Step for Sysroot {
                 // FIXME: this is wrong when compiler.host != build, but we don't support that today
                 OsStr::new(std::env::consts::DLL_EXTENSION),
             ];
-            let ci_rustc_dir = builder.ci_rustc_dir(builder.config.build);
+            let ci_rustc_dir = builder.config.ci_rustc_dir();
             builder.cp_filtered(&ci_rustc_dir, &sysroot, &|path| {
                 if path.extension().map_or(true, |ext| !filtered_extensions.contains(&ext)) {
                     return true;
diff --git a/src/bootstrap/config.rs b/src/bootstrap/config.rs
index 28ae46efefe..34853743323 100644
--- a/src/bootstrap/config.rs
+++ b/src/bootstrap/config.rs
@@ -1375,6 +1375,25 @@ impl Config {
         let mut omit_git_hash = None;
 
         if let Some(rust) = toml.rust {
+            set(&mut config.channel, rust.channel);
+
+            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
+            // This list is incomplete, please help by expanding it!
+            if config.download_rustc_commit.is_some() {
+                // We need the channel used by the downloaded compiler to match the one we set for rustdoc;
+                // otherwise rustdoc-ui tests break.
+                let ci_channel = t!(fs::read_to_string(config.src.join("src/ci/channel")));
+                let ci_channel = ci_channel.trim_end();
+                if config.channel != ci_channel
+                    && !(config.channel == "dev" && ci_channel == "nightly")
+                {
+                    panic!(
+                        "setting rust.channel={} is incompatible with download-rustc",
+                        config.channel
+                    );
+                }
+            }
+
             debug = rust.debug;
             debug_assertions = rust.debug_assertions;
             debug_assertions_std = rust.debug_assertions_std;
@@ -1386,6 +1405,7 @@ impl Config {
             debuginfo_level_std = rust.debuginfo_level_std;
             debuginfo_level_tools = rust.debuginfo_level_tools;
             debuginfo_level_tests = rust.debuginfo_level_tests;
+
             config.rust_split_debuginfo = rust
                 .split_debuginfo
                 .as_deref()
@@ -1401,7 +1421,6 @@ impl Config {
             set(&mut config.jemalloc, rust.jemalloc);
             set(&mut config.test_compare_mode, rust.test_compare_mode);
             set(&mut config.backtrace, rust.backtrace);
-            set(&mut config.channel, rust.channel);
             config.description = rust.description;
             set(&mut config.rust_dist_src, rust.dist_src);
             set(&mut config.verbose_tests, rust.verbose_tests);
@@ -1442,8 +1461,6 @@ impl Config {
             config.rust_codegen_units_std = rust.codegen_units_std.map(threads_from_config);
             config.rust_profile_use = flags.rust_profile_use.or(rust.profile_use);
             config.rust_profile_generate = flags.rust_profile_generate.or(rust.profile_generate);
-            config.download_rustc_commit = config.download_ci_rustc_commit(rust.download_rustc);
-
             config.rust_lto = rust
                 .lto
                 .as_deref()
@@ -1555,6 +1572,11 @@ impl Config {
                 let mut target = Target::from_triple(&triple);
 
                 if let Some(ref s) = cfg.llvm_config {
+                    if config.download_rustc_commit.is_some() && triple == &*config.build.triple {
+                        panic!(
+                            "setting llvm_config for the host is incompatible with download-rustc"
+                        );
+                    }
                     target.llvm_config = Some(config.src.join(s));
                 }
                 target.llvm_has_rust_patches = cfg.llvm_has_rust_patches;
@@ -1825,6 +1847,12 @@ impl Config {
         self.out.join(&*self.build.triple).join("ci-llvm")
     }
 
+    /// Directory where the extracted `rustc-dev` component is stored.
+    pub(crate) fn ci_rustc_dir(&self) -> PathBuf {
+        assert!(self.download_rustc());
+        self.out.join(self.build.triple).join("ci-rustc")
+    }
+
     /// Determine whether llvm should be linked dynamically.
     ///
     /// If `false`, llvm should be linked statically.
@@ -1860,11 +1888,11 @@ impl Config {
         self.download_rustc_commit().is_some()
     }
 
-    pub(crate) fn download_rustc_commit(&self) -> Option<&'static str> {
+    pub(crate) fn download_rustc_commit(&self) -> Option<&str> {
         static DOWNLOAD_RUSTC: OnceCell<Option<String>> = OnceCell::new();
         if self.dry_run() && DOWNLOAD_RUSTC.get().is_none() {
             // avoid trying to actually download the commit
-            return None;
+            return self.download_rustc_commit.as_deref();
         }
 
         DOWNLOAD_RUSTC
diff --git a/src/bootstrap/dist.rs b/src/bootstrap/dist.rs
index 4522819f996..b34a4b2dc63 100644
--- a/src/bootstrap/dist.rs
+++ b/src/bootstrap/dist.rs
@@ -1074,11 +1074,7 @@ impl Step for Cargo {
 
         tarball.add_file(&cargo, "bin", 0o755);
         tarball.add_file(etc.join("_cargo"), "share/zsh/site-functions", 0o644);
-        tarball.add_renamed_file(
-            etc.join("cargo.bashcomp.sh"),
-            "src/etc/bash_completion.d",
-            "cargo",
-        );
+        tarball.add_renamed_file(etc.join("cargo.bashcomp.sh"), "etc/bash_completion.d", "cargo");
         tarball.add_dir(etc.join("man"), "share/man/man1");
         tarball.add_legal_and_readme_to("share/doc/cargo");
 
diff --git a/src/bootstrap/download.rs b/src/bootstrap/download.rs
index cb40521dda7..a081f6189d7 100644
--- a/src/bootstrap/download.rs
+++ b/src/bootstrap/download.rs
@@ -402,7 +402,11 @@ impl Config {
 
     fn ci_component_contents(&self, stamp_file: &str) -> Vec<String> {
         assert!(self.download_rustc());
-        let ci_rustc_dir = self.out.join(&*self.build.triple).join("ci-rustc");
+        if self.dry_run() {
+            return vec![];
+        }
+
+        let ci_rustc_dir = self.ci_rustc_dir();
         let stamp_file = ci_rustc_dir.join(stamp_file);
         let contents_file = t!(File::open(&stamp_file), stamp_file.display().to_string());
         t!(BufReader::new(contents_file).lines().collect())
@@ -419,7 +423,7 @@ impl Config {
         self.download_toolchain(
             &version,
             "ci-rustc",
-            commit,
+            &format!("{commit}-{}", self.llvm_assertions),
             &extra_components,
             Self::download_ci_component,
         );
@@ -495,8 +499,15 @@ impl Config {
 
     /// Download a single component of a CI-built toolchain (not necessarily a published nightly).
     // NOTE: intentionally takes an owned string to avoid downloading multiple times by accident
-    fn download_ci_component(&self, filename: String, prefix: &str, commit: &str) {
-        Self::download_component(self, DownloadSource::CI, filename, prefix, commit, "ci-rustc")
+    fn download_ci_component(&self, filename: String, prefix: &str, commit_with_assertions: &str) {
+        Self::download_component(
+            self,
+            DownloadSource::CI,
+            filename,
+            prefix,
+            commit_with_assertions,
+            "ci-rustc",
+        )
     }
 
     fn download_component(
@@ -516,11 +527,18 @@ impl Config {
         let bin_root = self.out.join(self.build.triple).join(destination);
         let tarball = cache_dir.join(&filename);
         let (base_url, url, should_verify) = match mode {
-            DownloadSource::CI => (
-                self.stage0_metadata.config.artifacts_server.clone(),
-                format!("{key}/{filename}"),
-                false,
-            ),
+            DownloadSource::CI => {
+                let dist_server = if self.llvm_assertions {
+                    self.stage0_metadata.config.artifacts_with_llvm_assertions_server.clone()
+                } else {
+                    self.stage0_metadata.config.artifacts_server.clone()
+                };
+                let url = format!(
+                    "{}/{filename}",
+                    key.strip_suffix(&format!("-{}", self.llvm_assertions)).unwrap()
+                );
+                (dist_server, url, false)
+            }
             DownloadSource::Dist => {
                 let dist_server = env::var("RUSTUP_DIST_SERVER")
                     .unwrap_or(self.stage0_metadata.config.dist_server.to_string());
diff --git a/src/bootstrap/lib.rs b/src/bootstrap/lib.rs
index 0a7aff62257..0b509132043 100644
--- a/src/bootstrap/lib.rs
+++ b/src/bootstrap/lib.rs
@@ -822,11 +822,6 @@ impl Build {
         self.stage_out(compiler, mode).join(&*target.triple).join(self.cargo_dir())
     }
 
-    /// Directory where the extracted `rustc-dev` component is stored.
-    fn ci_rustc_dir(&self, target: TargetSelection) -> PathBuf {
-        self.out.join(&*target.triple).join("ci-rustc")
-    }
-
     /// Root output directory for LLVM compiled for `target`
     ///
     /// Note that if LLVM is configured externally then the directory returned
diff --git a/src/bootstrap/test.rs b/src/bootstrap/test.rs
index 0907291b54d..a34465ebffb 100644
--- a/src/bootstrap/test.rs
+++ b/src/bootstrap/test.rs
@@ -2348,7 +2348,7 @@ impl Step for Crate {
                 // `std_cargo` actually does the wrong thing: it passes `--sysroot build/host/stage2`,
                 // but we want to use the force-recompile std we just built in `build/host/stage2-test-sysroot`.
                 // Override it.
-                if builder.download_rustc() {
+                if builder.download_rustc() && compiler.stage > 0 {
                     let sysroot = builder
                         .out
                         .join(compiler.host.triple)
diff --git a/src/ci/github-actions/ci.yml b/src/ci/github-actions/ci.yml
index b5b478e60f4..55fd6cca85a 100644
--- a/src/ci/github-actions/ci.yml
+++ b/src/ci/github-actions/ci.yml
@@ -90,7 +90,7 @@ x--expand-yaml-anchors--remove:
     <<: *base-job
 
   - &job-macos-xl
-    os: macos-latest # We use the standard runner for now
+    os: macos-13 # We use the standard runner for now
     <<: *base-job
 
   - &job-windows-8c
diff --git a/src/doc/book b/src/doc/book
-Subproject 21cf840842bdf768a798869f06373c96c1cc512
+Subproject 668c64760b5c7ea654facb4ba5fe9faddfda27c
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject f63e578b92ff43e8cc38fcaa257b660f45c8a8c
+Subproject 2751bdcef125468ea2ee006c11992cd1405aebe
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
-Subproject f2aed2fe8e9f55508c86ba3aa4b6789b18a08a2
+Subproject 1e5556dd1b864109985d5871616ae6b9164bcea
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject c369e4b489332f8721fbae630354fa83385d457
+Subproject 302b995bcb24b70fd883980fd174738c3a10b70
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 5ca365eac678cb0d41a20b3204546d6ed70c717
+Subproject 1ea0178266b3f3f613b0fabdaf16a83961c99cd
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 57636d6926762861f34e030d52ca25a71e95e5b
+Subproject 8a87926a985ce32ca1fad1be4008ee161a0b91e
diff --git a/src/doc/rustc-dev-guide b/src/doc/rustc-dev-guide
-Subproject 17fe3e948498c50e208047a750f17d6a8d89669
+Subproject b5a12d95e32ae53791cc6ab44417774667ed2ac
diff --git a/src/doc/style-guide/src/expressions.md b/src/doc/style-guide/src/expressions.md
index 143161da6cf..41a9eb82cb5 100644
--- a/src/doc/style-guide/src/expressions.md
+++ b/src/doc/style-guide/src/expressions.md
@@ -451,12 +451,11 @@ foo(
 
 #### Multi-line elements
 
-If any element in a chain is formatted across multiple lines, then that element
-and any later elements must be on their own line. Earlier elements may be kept
-on a single line. E.g.,
+If any element in a chain is formatted across multiple lines, put that element
+and any later elements on their own lines.
 
 ```rust
-a.b.c()?.d
+a.b.c()?
     .foo(
         an_expr,
         another_expr,
@@ -803,6 +802,16 @@ foo(|param| {
     action();
     foo(param)
 })
+
+let x = combinable([
+    an_expr,
+    another_expr,
+]);
+
+let arr = [combinable(
+    an_expr,
+    another_expr,
+)];
 ```
 
 Such behaviour should extend recursively, however, tools may choose to limit the
diff --git a/src/librustdoc/formats/item_type.rs b/src/librustdoc/formats/item_type.rs
index 452e14918fa..a3017201cb1 100644
--- a/src/librustdoc/formats/item_type.rs
+++ b/src/librustdoc/formats/item_type.rs
@@ -136,7 +136,6 @@ impl From<DefKind> for ItemType {
             | DefKind::AnonConst
             | DefKind::InlineConst
             | DefKind::OpaqueTy
-            | DefKind::ImplTraitPlaceholder
             | DefKind::Field
             | DefKind::LifetimeParam
             | DefKind::GlobalAsm
diff --git a/src/librustdoc/passes/collect_intra_doc_links.rs b/src/librustdoc/passes/collect_intra_doc_links.rs
index 0dd9e590b9b..ca511d956b9 100644
--- a/src/librustdoc/passes/collect_intra_doc_links.rs
+++ b/src/librustdoc/passes/collect_intra_doc_links.rs
@@ -1860,8 +1860,8 @@ fn resolution_failure(
                                 }
                                 return;
                             }
-                            Trait | TyAlias | ForeignTy | OpaqueTy | ImplTraitPlaceholder
-                            | TraitAlias | TyParam | Static(_) => "associated item",
+                            Trait | TyAlias | ForeignTy | OpaqueTy | TraitAlias | TyParam
+                            | Static(_) => "associated item",
                             Impl { .. } | GlobalAsm => unreachable!("not a path"),
                         }
                     } else {
diff --git a/src/tools/clippy/clippy_lints/src/declared_lints.rs b/src/tools/clippy/clippy_lints/src/declared_lints.rs
index 9d9ee6ba307..b60f0738f64 100644
--- a/src/tools/clippy/clippy_lints/src/declared_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/declared_lints.rs
@@ -171,7 +171,6 @@ pub(crate) static LINTS: &[&crate::LintInfo] = &[
     crate::float_literal::LOSSY_FLOAT_LITERAL_INFO,
     crate::floating_point_arithmetic::IMPRECISE_FLOPS_INFO,
     crate::floating_point_arithmetic::SUBOPTIMAL_FLOPS_INFO,
-    crate::fn_null_check::FN_NULL_CHECK_INFO,
     crate::format::USELESS_FORMAT_INFO,
     crate::format_args::FORMAT_IN_FORMAT_ARGS_INFO,
     crate::format_args::TO_STRING_IN_FORMAT_ARGS_INFO,
diff --git a/src/tools/clippy/clippy_lints/src/fn_null_check.rs b/src/tools/clippy/clippy_lints/src/fn_null_check.rs
deleted file mode 100644
index 521045a9fed..00000000000
--- a/src/tools/clippy/clippy_lints/src/fn_null_check.rs
+++ /dev/null
@@ -1,102 +0,0 @@
-use clippy_utils::consts::{constant, Constant};
-use clippy_utils::diagnostics::span_lint_and_help;
-use clippy_utils::{is_integer_literal, is_path_diagnostic_item};
-use rustc_hir::{BinOpKind, Expr, ExprKind, TyKind};
-use rustc_lint::{LateContext, LateLintPass};
-use rustc_session::{declare_lint_pass, declare_tool_lint};
-use rustc_span::sym;
-
-declare_clippy_lint! {
-    /// ### What it does
-    /// Checks for comparing a function pointer to null.
-    ///
-    /// ### Why is this bad?
-    /// Function pointers are assumed to not be null.
-    ///
-    /// ### Example
-    /// ```rust,ignore
-    /// let fn_ptr: fn() = /* somehow obtained nullable function pointer */
-    ///
-    /// if (fn_ptr as *const ()).is_null() { ... }
-    /// ```
-    /// Use instead:
-    /// ```rust,ignore
-    /// let fn_ptr: Option<fn()> = /* somehow obtained nullable function pointer */
-    ///
-    /// if fn_ptr.is_none() { ... }
-    /// ```
-    #[clippy::version = "1.68.0"]
-    pub FN_NULL_CHECK,
-    correctness,
-    "`fn()` type assumed to be nullable"
-}
-declare_lint_pass!(FnNullCheck => [FN_NULL_CHECK]);
-
-fn lint_expr(cx: &LateContext<'_>, expr: &Expr<'_>) {
-    span_lint_and_help(
-        cx,
-        FN_NULL_CHECK,
-        expr.span,
-        "function pointer assumed to be nullable, even though it isn't",
-        None,
-        "try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value",
-    );
-}
-
-fn is_fn_ptr_cast(cx: &LateContext<'_>, expr: &Expr<'_>) -> bool {
-    if let ExprKind::Cast(cast_expr, cast_ty) = expr.kind
-        && let TyKind::Ptr(_) = cast_ty.kind
-    {
-        cx.typeck_results().expr_ty_adjusted(cast_expr).is_fn()
-    } else {
-        false
-    }
-}
-
-impl<'tcx> LateLintPass<'tcx> for FnNullCheck {
-    fn check_expr(&mut self, cx: &LateContext<'tcx>, expr: &'tcx Expr<'_>) {
-        match expr.kind {
-            // Catching:
-            // (fn_ptr as *<const/mut> <ty>).is_null()
-            ExprKind::MethodCall(method_name, receiver, _, _)
-                if method_name.ident.as_str() == "is_null" && is_fn_ptr_cast(cx, receiver) =>
-            {
-                lint_expr(cx, expr);
-            },
-
-            ExprKind::Binary(op, left, right) if matches!(op.node, BinOpKind::Eq) => {
-                let to_check: &Expr<'_>;
-                if is_fn_ptr_cast(cx, left) {
-                    to_check = right;
-                } else if is_fn_ptr_cast(cx, right) {
-                    to_check = left;
-                } else {
-                    return;
-                }
-
-                match to_check.kind {
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == (0 as <ty>)
-                    ExprKind::Cast(cast_expr, _) if is_integer_literal(cast_expr, 0) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == std::ptr::null()
-                    ExprKind::Call(func, []) if is_path_diagnostic_item(cx, func, sym::ptr_null) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    // Catching:
-                    // (fn_ptr as *<const/mut> <ty>) == <const that evaluates to null_ptr>
-                    _ if matches!(constant(cx, cx.typeck_results(), to_check), Some(Constant::RawPtr(0))) => {
-                        lint_expr(cx, expr);
-                    },
-
-                    _ => {},
-                }
-            },
-            _ => {},
-        }
-    }
-}
diff --git a/src/tools/clippy/clippy_lints/src/lib.rs b/src/tools/clippy/clippy_lints/src/lib.rs
index 87329ee5e14..365cc4c59ad 100644
--- a/src/tools/clippy/clippy_lints/src/lib.rs
+++ b/src/tools/clippy/clippy_lints/src/lib.rs
@@ -131,7 +131,6 @@ mod extra_unused_type_parameters;
 mod fallible_impl_from;
 mod float_literal;
 mod floating_point_arithmetic;
-mod fn_null_check;
 mod format;
 mod format_args;
 mod format_impl;
@@ -1003,7 +1002,6 @@ pub fn register_plugins(store: &mut rustc_lint::LintStore, sess: &Session, conf:
             semicolon_outside_block_ignore_multiline,
         ))
     });
-    store.register_late_pass(|_| Box::new(fn_null_check::FnNullCheck));
     store.register_late_pass(|_| Box::new(permissions_set_readonly_false::PermissionsSetReadonlyFalse));
     store.register_late_pass(|_| Box::new(size_of_ref::SizeOfRef));
     store.register_late_pass(|_| Box::new(multiple_unsafe_ops_per_block::MultipleUnsafeOpsPerBlock));
diff --git a/src/tools/clippy/clippy_lints/src/renamed_lints.rs b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
index cbcd11debfd..d24215c2292 100644
--- a/src/tools/clippy/clippy_lints/src/renamed_lints.rs
+++ b/src/tools/clippy/clippy_lints/src/renamed_lints.rs
@@ -42,6 +42,7 @@ pub static RENAMED_LINTS: &[(&str, &str)] = &[
     ("clippy::for_loops_over_fallibles", "for_loops_over_fallibles"),
     ("clippy::forget_copy", "forgetting_copy_types"),
     ("clippy::forget_ref", "forgetting_references"),
+    ("clippy::fn_null_check", "incorrect_fn_null_checks"),
     ("clippy::into_iter_on_array", "array_into_iter"),
     ("clippy::invalid_atomic_ordering", "invalid_atomic_ordering"),
     ("clippy::invalid_ref", "invalid_value"),
diff --git a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
index 83db2a07d33..cc36ce5f487 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_doc_comments.rs
@@ -1,4 +1,7 @@
 //@aux-build:proc_macro_attr.rs:proc-macro
+// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
+//@ignore-32bit
+//@ignore-64bit
 #![warn(clippy::empty_line_after_doc_comments)]
 #![allow(clippy::assertions_on_constants)]
 #![feature(custom_inner_attributes)]
diff --git a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
index b2d7ddae427..bc54e0fd2de 100644
--- a/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
+++ b/src/tools/clippy/tests/ui/empty_line_after_outer_attribute.rs
@@ -1,4 +1,7 @@
 //@aux-build:proc_macro_attr.rs:proc-macro
+// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
+//@ignore-32bit
+//@ignore-64bit
 #![warn(clippy::empty_line_after_outer_attr)]
 #![allow(clippy::assertions_on_constants)]
 #![feature(custom_inner_attributes)]
diff --git a/src/tools/clippy/tests/ui/fn_null_check.rs b/src/tools/clippy/tests/ui/fn_null_check.rs
deleted file mode 100644
index dfdea100c8f..00000000000
--- a/src/tools/clippy/tests/ui/fn_null_check.rs
+++ /dev/null
@@ -1,22 +0,0 @@
-#![allow(unused)]
-#![warn(clippy::fn_null_check)]
-#![allow(clippy::cmp_null)]
-#![allow(clippy::needless_if)]
-#![allow(clippy::ptr_eq)]
-#![allow(clippy::zero_ptr)]
-
-pub const ZPTR: *const () = 0 as *const _;
-pub const NOT_ZPTR: *const () = 1 as *const _;
-
-fn main() {
-    let fn_ptr = main;
-
-    if (fn_ptr as *mut ()).is_null() {}
-    if (fn_ptr as *const u8).is_null() {}
-    if (fn_ptr as *const ()) == std::ptr::null() {}
-    if (fn_ptr as *const ()) == (0 as *const ()) {}
-    if (fn_ptr as *const ()) == ZPTR {}
-
-    // no lint
-    if (fn_ptr as *const ()) == NOT_ZPTR {}
-}
diff --git a/src/tools/clippy/tests/ui/fn_null_check.stderr b/src/tools/clippy/tests/ui/fn_null_check.stderr
deleted file mode 100644
index 5b9f48a961c..00000000000
--- a/src/tools/clippy/tests/ui/fn_null_check.stderr
+++ /dev/null
@@ -1,43 +0,0 @@
-error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:14:8
-   |
-LL |     if (fn_ptr as *mut ()).is_null() {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
-   = note: `-D clippy::fn-null-check` implied by `-D warnings`
-
-error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:15:8
-   |
-LL |     if (fn_ptr as *const u8).is_null() {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
-
-error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:16:8
-   |
-LL |     if (fn_ptr as *const ()) == std::ptr::null() {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
-
-error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:17:8
-   |
-LL |     if (fn_ptr as *const ()) == (0 as *const ()) {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
-
-error: function pointer assumed to be nullable, even though it isn't
-  --> $DIR/fn_null_check.rs:18:8
-   |
-LL |     if (fn_ptr as *const ()) == ZPTR {}
-   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = help: try wrapping your function pointer type in `Option<T>` instead, and using `is_none` to check for null pointer value
-
-error: aborting due to 5 previous errors
-
diff --git a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
index 876f16a3854..321aa69a1a5 100644
--- a/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
+++ b/src/tools/clippy/tests/ui/needless_arbitrary_self_type_unfixable.rs
@@ -1,4 +1,7 @@
 //@aux-build:proc_macro_attr.rs:proc-macro
+// Flaky test, see https://github.com/rust-lang/rust/issues/113585.
+//@ignore-32bit
+//@ignore-64bit
 
 #![warn(clippy::needless_arbitrary_self_type)]
 
diff --git a/src/tools/clippy/tests/ui/rename.fixed b/src/tools/clippy/tests/ui/rename.fixed
index b24c83d9a0d..cab02bb93c9 100644
--- a/src/tools/clippy/tests/ui/rename.fixed
+++ b/src/tools/clippy/tests/ui/rename.fixed
@@ -37,6 +37,7 @@
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
 #![allow(forgetting_references)]
+#![allow(incorrect_fn_null_checks)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -89,6 +90,7 @@
 #![warn(for_loops_over_fallibles)]
 #![warn(forgetting_copy_types)]
 #![warn(forgetting_references)]
+#![warn(incorrect_fn_null_checks)]
 #![warn(array_into_iter)]
 #![warn(invalid_atomic_ordering)]
 #![warn(invalid_value)]
diff --git a/src/tools/clippy/tests/ui/rename.rs b/src/tools/clippy/tests/ui/rename.rs
index baa6345a64f..e5e31452149 100644
--- a/src/tools/clippy/tests/ui/rename.rs
+++ b/src/tools/clippy/tests/ui/rename.rs
@@ -37,6 +37,7 @@
 #![allow(for_loops_over_fallibles)]
 #![allow(forgetting_copy_types)]
 #![allow(forgetting_references)]
+#![allow(incorrect_fn_null_checks)]
 #![allow(array_into_iter)]
 #![allow(invalid_atomic_ordering)]
 #![allow(invalid_value)]
@@ -89,6 +90,7 @@
 #![warn(clippy::for_loops_over_fallibles)]
 #![warn(clippy::forget_copy)]
 #![warn(clippy::forget_ref)]
+#![warn(clippy::fn_null_check)]
 #![warn(clippy::into_iter_on_array)]
 #![warn(clippy::invalid_atomic_ordering)]
 #![warn(clippy::invalid_ref)]
diff --git a/src/tools/clippy/tests/ui/rename.stderr b/src/tools/clippy/tests/ui/rename.stderr
index ae25c3b46bd..783608a0841 100644
--- a/src/tools/clippy/tests/ui/rename.stderr
+++ b/src/tools/clippy/tests/ui/rename.stderr
@@ -1,5 +1,5 @@
 error: lint `clippy::almost_complete_letter_range` has been renamed to `clippy::almost_complete_range`
-  --> $DIR/rename.rs:52:9
+  --> $DIR/rename.rs:53:9
    |
 LL | #![warn(clippy::almost_complete_letter_range)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::almost_complete_range`
@@ -7,310 +7,316 @@ LL | #![warn(clippy::almost_complete_letter_range)]
    = note: `-D renamed-and-removed-lints` implied by `-D warnings`
 
 error: lint `clippy::blacklisted_name` has been renamed to `clippy::disallowed_names`
-  --> $DIR/rename.rs:53:9
+  --> $DIR/rename.rs:54:9
    |
 LL | #![warn(clippy::blacklisted_name)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_names`
 
 error: lint `clippy::block_in_if_condition_expr` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:54:9
+  --> $DIR/rename.rs:55:9
    |
 LL | #![warn(clippy::block_in_if_condition_expr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::block_in_if_condition_stmt` has been renamed to `clippy::blocks_in_if_conditions`
-  --> $DIR/rename.rs:55:9
+  --> $DIR/rename.rs:56:9
    |
 LL | #![warn(clippy::block_in_if_condition_stmt)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::blocks_in_if_conditions`
 
 error: lint `clippy::box_vec` has been renamed to `clippy::box_collection`
-  --> $DIR/rename.rs:56:9
+  --> $DIR/rename.rs:57:9
    |
 LL | #![warn(clippy::box_vec)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::box_collection`
 
 error: lint `clippy::const_static_lifetime` has been renamed to `clippy::redundant_static_lifetimes`
-  --> $DIR/rename.rs:57:9
+  --> $DIR/rename.rs:58:9
    |
 LL | #![warn(clippy::const_static_lifetime)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::redundant_static_lifetimes`
 
 error: lint `clippy::cyclomatic_complexity` has been renamed to `clippy::cognitive_complexity`
-  --> $DIR/rename.rs:58:9
+  --> $DIR/rename.rs:59:9
    |
 LL | #![warn(clippy::cyclomatic_complexity)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::cognitive_complexity`
 
 error: lint `clippy::derive_hash_xor_eq` has been renamed to `clippy::derived_hash_with_manual_eq`
-  --> $DIR/rename.rs:59:9
+  --> $DIR/rename.rs:60:9
    |
 LL | #![warn(clippy::derive_hash_xor_eq)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::derived_hash_with_manual_eq`
 
 error: lint `clippy::disallowed_method` has been renamed to `clippy::disallowed_methods`
-  --> $DIR/rename.rs:60:9
+  --> $DIR/rename.rs:61:9
    |
 LL | #![warn(clippy::disallowed_method)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_methods`
 
 error: lint `clippy::disallowed_type` has been renamed to `clippy::disallowed_types`
-  --> $DIR/rename.rs:61:9
+  --> $DIR/rename.rs:62:9
    |
 LL | #![warn(clippy::disallowed_type)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::disallowed_types`
 
 error: lint `clippy::eval_order_dependence` has been renamed to `clippy::mixed_read_write_in_expression`
-  --> $DIR/rename.rs:62:9
+  --> $DIR/rename.rs:63:9
    |
 LL | #![warn(clippy::eval_order_dependence)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::mixed_read_write_in_expression`
 
 error: lint `clippy::identity_conversion` has been renamed to `clippy::useless_conversion`
-  --> $DIR/rename.rs:63:9
+  --> $DIR/rename.rs:64:9
    |
 LL | #![warn(clippy::identity_conversion)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::useless_conversion`
 
 error: lint `clippy::if_let_some_result` has been renamed to `clippy::match_result_ok`
-  --> $DIR/rename.rs:64:9
+  --> $DIR/rename.rs:65:9
    |
 LL | #![warn(clippy::if_let_some_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::match_result_ok`
 
 error: lint `clippy::integer_arithmetic` has been renamed to `clippy::arithmetic_side_effects`
-  --> $DIR/rename.rs:65:9
+  --> $DIR/rename.rs:66:9
    |
 LL | #![warn(clippy::integer_arithmetic)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::arithmetic_side_effects`
 
 error: lint `clippy::logic_bug` has been renamed to `clippy::overly_complex_bool_expr`
-  --> $DIR/rename.rs:66:9
+  --> $DIR/rename.rs:67:9
    |
 LL | #![warn(clippy::logic_bug)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::overly_complex_bool_expr`
 
 error: lint `clippy::new_without_default_derive` has been renamed to `clippy::new_without_default`
-  --> $DIR/rename.rs:67:9
+  --> $DIR/rename.rs:68:9
    |
 LL | #![warn(clippy::new_without_default_derive)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::new_without_default`
 
 error: lint `clippy::option_and_then_some` has been renamed to `clippy::bind_instead_of_map`
-  --> $DIR/rename.rs:68:9
+  --> $DIR/rename.rs:69:9
    |
 LL | #![warn(clippy::option_and_then_some)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::bind_instead_of_map`
 
 error: lint `clippy::option_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:69:9
+  --> $DIR/rename.rs:70:9
    |
 LL | #![warn(clippy::option_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::option_map_unwrap_or` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:70:9
+  --> $DIR/rename.rs:71:9
    |
 LL | #![warn(clippy::option_map_unwrap_or)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:71:9
+  --> $DIR/rename.rs:72:9
    |
 LL | #![warn(clippy::option_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::option_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:72:9
+  --> $DIR/rename.rs:73:9
    |
 LL | #![warn(clippy::option_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::ref_in_deref` has been renamed to `clippy::needless_borrow`
-  --> $DIR/rename.rs:73:9
+  --> $DIR/rename.rs:74:9
    |
 LL | #![warn(clippy::ref_in_deref)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::needless_borrow`
 
 error: lint `clippy::result_expect_used` has been renamed to `clippy::expect_used`
-  --> $DIR/rename.rs:74:9
+  --> $DIR/rename.rs:75:9
    |
 LL | #![warn(clippy::result_expect_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::expect_used`
 
 error: lint `clippy::result_map_unwrap_or_else` has been renamed to `clippy::map_unwrap_or`
-  --> $DIR/rename.rs:75:9
+  --> $DIR/rename.rs:76:9
    |
 LL | #![warn(clippy::result_map_unwrap_or_else)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::map_unwrap_or`
 
 error: lint `clippy::result_unwrap_used` has been renamed to `clippy::unwrap_used`
-  --> $DIR/rename.rs:76:9
+  --> $DIR/rename.rs:77:9
    |
 LL | #![warn(clippy::result_unwrap_used)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::unwrap_used`
 
 error: lint `clippy::single_char_push_str` has been renamed to `clippy::single_char_add_str`
-  --> $DIR/rename.rs:77:9
+  --> $DIR/rename.rs:78:9
    |
 LL | #![warn(clippy::single_char_push_str)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::single_char_add_str`
 
 error: lint `clippy::stutter` has been renamed to `clippy::module_name_repetitions`
-  --> $DIR/rename.rs:78:9
+  --> $DIR/rename.rs:79:9
    |
 LL | #![warn(clippy::stutter)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `clippy::module_name_repetitions`
 
 error: lint `clippy::to_string_in_display` has been renamed to `clippy::recursive_format_impl`
-  --> $DIR/rename.rs:79:9
+  --> $DIR/rename.rs:80:9
    |
 LL | #![warn(clippy::to_string_in_display)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::recursive_format_impl`
 
 error: lint `clippy::zero_width_space` has been renamed to `clippy::invisible_characters`
-  --> $DIR/rename.rs:80:9
+  --> $DIR/rename.rs:81:9
    |
 LL | #![warn(clippy::zero_width_space)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `clippy::invisible_characters`
 
 error: lint `clippy::cast_ref_to_mut` has been renamed to `cast_ref_to_mut`
-  --> $DIR/rename.rs:81:9
+  --> $DIR/rename.rs:82:9
    |
 LL | #![warn(clippy::cast_ref_to_mut)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `cast_ref_to_mut`
 
 error: lint `clippy::clone_double_ref` has been renamed to `suspicious_double_ref_op`
-  --> $DIR/rename.rs:82:9
+  --> $DIR/rename.rs:83:9
    |
 LL | #![warn(clippy::clone_double_ref)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `suspicious_double_ref_op`
 
 error: lint `clippy::cmp_nan` has been renamed to `invalid_nan_comparisons`
-  --> $DIR/rename.rs:83:9
+  --> $DIR/rename.rs:84:9
    |
 LL | #![warn(clippy::cmp_nan)]
    |         ^^^^^^^^^^^^^^^ help: use the new name: `invalid_nan_comparisons`
 
 error: lint `clippy::drop_bounds` has been renamed to `drop_bounds`
-  --> $DIR/rename.rs:84:9
+  --> $DIR/rename.rs:85:9
    |
 LL | #![warn(clippy::drop_bounds)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `drop_bounds`
 
 error: lint `clippy::drop_copy` has been renamed to `dropping_copy_types`
-  --> $DIR/rename.rs:85:9
+  --> $DIR/rename.rs:86:9
    |
 LL | #![warn(clippy::drop_copy)]
    |         ^^^^^^^^^^^^^^^^^ help: use the new name: `dropping_copy_types`
 
 error: lint `clippy::drop_ref` has been renamed to `dropping_references`
-  --> $DIR/rename.rs:86:9
+  --> $DIR/rename.rs:87:9
    |
 LL | #![warn(clippy::drop_ref)]
    |         ^^^^^^^^^^^^^^^^ help: use the new name: `dropping_references`
 
 error: lint `clippy::for_loop_over_option` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:87:9
+  --> $DIR/rename.rs:88:9
    |
 LL | #![warn(clippy::for_loop_over_option)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loop_over_result` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:88:9
+  --> $DIR/rename.rs:89:9
    |
 LL | #![warn(clippy::for_loop_over_result)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::for_loops_over_fallibles` has been renamed to `for_loops_over_fallibles`
-  --> $DIR/rename.rs:89:9
+  --> $DIR/rename.rs:90:9
    |
 LL | #![warn(clippy::for_loops_over_fallibles)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `for_loops_over_fallibles`
 
 error: lint `clippy::forget_copy` has been renamed to `forgetting_copy_types`
-  --> $DIR/rename.rs:90:9
+  --> $DIR/rename.rs:91:9
    |
 LL | #![warn(clippy::forget_copy)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_copy_types`
 
 error: lint `clippy::forget_ref` has been renamed to `forgetting_references`
-  --> $DIR/rename.rs:91:9
+  --> $DIR/rename.rs:92:9
    |
 LL | #![warn(clippy::forget_ref)]
    |         ^^^^^^^^^^^^^^^^^^ help: use the new name: `forgetting_references`
 
+error: lint `clippy::fn_null_check` has been renamed to `incorrect_fn_null_checks`
+  --> $DIR/rename.rs:93:9
+   |
+LL | #![warn(clippy::fn_null_check)]
+   |         ^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `incorrect_fn_null_checks`
+
 error: lint `clippy::into_iter_on_array` has been renamed to `array_into_iter`
-  --> $DIR/rename.rs:92:9
+  --> $DIR/rename.rs:94:9
    |
 LL | #![warn(clippy::into_iter_on_array)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `array_into_iter`
 
 error: lint `clippy::invalid_atomic_ordering` has been renamed to `invalid_atomic_ordering`
-  --> $DIR/rename.rs:93:9
+  --> $DIR/rename.rs:95:9
    |
 LL | #![warn(clippy::invalid_atomic_ordering)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_atomic_ordering`
 
 error: lint `clippy::invalid_ref` has been renamed to `invalid_value`
-  --> $DIR/rename.rs:94:9
+  --> $DIR/rename.rs:96:9
    |
 LL | #![warn(clippy::invalid_ref)]
    |         ^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_value`
 
 error: lint `clippy::invalid_utf8_in_unchecked` has been renamed to `invalid_from_utf8_unchecked`
-  --> $DIR/rename.rs:95:9
+  --> $DIR/rename.rs:97:9
    |
 LL | #![warn(clippy::invalid_utf8_in_unchecked)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `invalid_from_utf8_unchecked`
 
 error: lint `clippy::let_underscore_drop` has been renamed to `let_underscore_drop`
-  --> $DIR/rename.rs:96:9
+  --> $DIR/rename.rs:98:9
    |
 LL | #![warn(clippy::let_underscore_drop)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `let_underscore_drop`
 
 error: lint `clippy::mem_discriminant_non_enum` has been renamed to `enum_intrinsics_non_enums`
-  --> $DIR/rename.rs:97:9
+  --> $DIR/rename.rs:99:9
    |
 LL | #![warn(clippy::mem_discriminant_non_enum)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `enum_intrinsics_non_enums`
 
 error: lint `clippy::panic_params` has been renamed to `non_fmt_panics`
-  --> $DIR/rename.rs:98:9
+  --> $DIR/rename.rs:100:9
    |
 LL | #![warn(clippy::panic_params)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `non_fmt_panics`
 
 error: lint `clippy::positional_named_format_parameters` has been renamed to `named_arguments_used_positionally`
-  --> $DIR/rename.rs:99:9
+  --> $DIR/rename.rs:101:9
    |
 LL | #![warn(clippy::positional_named_format_parameters)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `named_arguments_used_positionally`
 
 error: lint `clippy::temporary_cstring_as_ptr` has been renamed to `temporary_cstring_as_ptr`
-  --> $DIR/rename.rs:100:9
+  --> $DIR/rename.rs:102:9
    |
 LL | #![warn(clippy::temporary_cstring_as_ptr)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `temporary_cstring_as_ptr`
 
 error: lint `clippy::undropped_manually_drops` has been renamed to `undropped_manually_drops`
-  --> $DIR/rename.rs:101:9
+  --> $DIR/rename.rs:103:9
    |
 LL | #![warn(clippy::undropped_manually_drops)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `undropped_manually_drops`
 
 error: lint `clippy::unknown_clippy_lints` has been renamed to `unknown_lints`
-  --> $DIR/rename.rs:102:9
+  --> $DIR/rename.rs:104:9
    |
 LL | #![warn(clippy::unknown_clippy_lints)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unknown_lints`
 
 error: lint `clippy::unused_label` has been renamed to `unused_labels`
-  --> $DIR/rename.rs:103:9
+  --> $DIR/rename.rs:105:9
    |
 LL | #![warn(clippy::unused_label)]
    |         ^^^^^^^^^^^^^^^^^^^^ help: use the new name: `unused_labels`
 
-error: aborting due to 52 previous errors
+error: aborting due to 53 previous errors
 
diff --git a/src/tools/lint-docs/src/groups.rs b/src/tools/lint-docs/src/groups.rs
index b11fb287cf4..5be8ef7996b 100644
--- a/src/tools/lint-docs/src/groups.rs
+++ b/src/tools/lint-docs/src/groups.rs
@@ -39,7 +39,6 @@ impl<'a> LintExtractor<'a> {
     fn collect_groups(&self) -> Result<LintGroups, Box<dyn Error>> {
         let mut result = BTreeMap::new();
         let mut cmd = Command::new(self.rustc_path);
-        cmd.env_remove("LD_LIBRARY_PATH");
         cmd.arg("-Whelp");
         let output = cmd.output().map_err(|e| format!("failed to run command {:?}\n{}", cmd, e))?;
         if !output.status.success() {
diff --git a/src/tools/lint-docs/src/lib.rs b/src/tools/lint-docs/src/lib.rs
index fe29b9abda3..b7c8b9ed2e3 100644
--- a/src/tools/lint-docs/src/lib.rs
+++ b/src/tools/lint-docs/src/lib.rs
@@ -403,12 +403,6 @@ impl<'a> LintExtractor<'a> {
         fs::write(&tempfile, source)
             .map_err(|e| format!("failed to write {}: {}", tempfile.display(), e))?;
         let mut cmd = Command::new(self.rustc_path);
-        // NOTE: bootstrap sets `LD_LIBRARY_PATH` for building lint-docs itself.
-        // Unfortunately, lint-docs is a bootstrap tool while rustc is built from source,
-        // and sometimes the paths conflict. In particular, when using `download-rustc`,
-        // the LLVM versions can differ between `ci-llvm` and `ci-rustc-sysroot`.
-        // Unset LD_LIBRARY_PATH here so it doesn't interfere with running the compiler.
-        cmd.env_remove("LD_LIBRARY_PATH");
         if options.contains(&"edition2015") {
             cmd.arg("--edition=2015");
         } else {
diff --git a/src/tools/miri/src/borrow_tracker/mod.rs b/src/tools/miri/src/borrow_tracker/mod.rs
index faa23fd2620..a2cf7c80950 100644
--- a/src/tools/miri/src/borrow_tracker/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/mod.rs
@@ -302,12 +302,12 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
-    fn retag_return_place(&mut self) -> InterpResult<'tcx> {
+    fn protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
         let method = this.machine.borrow_tracker.as_ref().unwrap().borrow().borrow_tracker_method;
         match method {
-            BorrowTrackerMethod::StackedBorrows => this.sb_retag_return_place(),
-            BorrowTrackerMethod::TreeBorrows => this.tb_retag_return_place(),
+            BorrowTrackerMethod::StackedBorrows => this.sb_protect_place(place),
+            BorrowTrackerMethod::TreeBorrows => this.tb_protect_place(place),
         }
     }
 
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
index de307a3c5f5..5ec8d80fb32 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/diagnostics.rs
@@ -189,7 +189,7 @@ struct RetagOp {
 #[derive(Debug, Clone, Copy, PartialEq)]
 pub enum RetagCause {
     Normal,
-    FnReturnPlace,
+    InPlaceFnPassing,
     FnEntry,
     TwoPhase,
 }
@@ -501,7 +501,7 @@ impl RetagCause {
         match self {
             RetagCause::Normal => "retag",
             RetagCause::FnEntry => "function-entry retag",
-            RetagCause::FnReturnPlace => "return-place retag",
+            RetagCause::InPlaceFnPassing => "in-place function argument/return passing protection",
             RetagCause::TwoPhase => "two-phase retag",
         }
         .to_string()
diff --git a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
index ca0f69450c9..e22b352e740 100644
--- a/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/stacked_borrows/mod.rs
@@ -994,35 +994,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
-    /// After a stack frame got pushed, retag the return place so that we are sure
-    /// it does not alias with anything.
-    ///
-    /// This is a HACK because there is nothing in MIR that would make the retag
-    /// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
-    fn sb_retag_return_place(&mut self) -> InterpResult<'tcx> {
+    /// Protect a place so that it cannot be used any more for the duration of the current function
+    /// call.
+    /// 
+    /// This is used to ensure soundness of in-place function argument/return passing.
+    fn sb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        let return_place = &this.frame().return_place;
-        if return_place.layout.is_zst() {
-            // There may not be any memory here, nothing to do.
-            return Ok(());
-        }
-        // We need this to be in-memory to use tagged pointers.
-        let return_place = this.force_allocation(&return_place.clone())?;
 
-        // We have to turn the place into a pointer to use the existing code.
+        // We have to turn the place into a pointer to use the usual retagging logic.
         // (The pointer type does not matter, so we use a raw pointer.)
-        let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?;
-        let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
-        // Reborrow it. With protection! That is part of the point.
+        let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?;
+        let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout);
+        // Reborrow it. With protection! That is the entire point.
         let new_perm = NewPermission::Uniform {
             perm: Permission::Unique,
             access: Some(AccessKind::Write),
             protector: Some(ProtectorKind::StrongProtector),
         };
-        let val = this.sb_retag_reference(&val, new_perm, RetagCause::FnReturnPlace)?;
-        // And use reborrowed pointer for return place.
-        let return_place = this.ref_to_mplace(&val)?;
-        this.frame_mut().return_place = return_place.into();
+        let _new_ptr = this.sb_retag_reference(&ptr, new_perm, RetagCause::InPlaceFnPassing)?;
+        // We just throw away `new_ptr`, so nobody can access this memory while it is protected.
 
         Ok(())
     }
diff --git a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
index 3bb38a249ff..274a4a0aaba 100644
--- a/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
+++ b/src/tools/miri/src/borrow_tracker/tree_borrows/mod.rs
@@ -178,7 +178,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         &mut self,
         place: &MPlaceTy<'tcx, Provenance>, // parent tag extracted from here
         ptr_size: Size,
-        new_perm: Option<NewPermission>,
+        new_perm: NewPermission,
         new_tag: BorTag,
     ) -> InterpResult<'tcx, Option<(AllocId, BorTag)>> {
         let this = self.eval_context_mut();
@@ -256,10 +256,6 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
             ptr_size.bytes()
         );
 
-        let Some(new_perm) = new_perm else {
-            return Ok(Some((alloc_id, orig_tag)));
-        };
-
         if let Some(protect) = new_perm.protector {
             // We register the protection in two different places.
             // This makes creating a protector slower, but checking whether a tag
@@ -305,7 +301,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
     fn tb_retag_reference(
         &mut self,
         val: &ImmTy<'tcx, Provenance>,
-        new_perm: Option<NewPermission>,
+        new_perm: NewPermission,
     ) -> InterpResult<'tcx, ImmTy<'tcx, Provenance>> {
         let this = self.eval_context_mut();
         // We want a place for where the ptr *points to*, so we get one.
@@ -317,7 +313,7 @@ trait EvalContextPrivExt<'mir: 'ecx, 'tcx: 'mir, 'ecx>: crate::MiriInterpCxExt<'
         // - if the pointer is not reborrowed (raw pointer) or if `zero_size` is set
         // then we override the size to do a zero-length reborrow.
         let reborrow_size = match new_perm {
-            Some(NewPermission { zero_size: false, .. }) =>
+            NewPermission { zero_size: false, .. } =>
                 this.size_and_align_of_mplace(&place)?
                     .map(|(size, _)| size)
                     .unwrap_or(place.layout.size),
@@ -374,7 +370,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 NewPermission::from_ref_ty(pointee, mutability, kind, this),
             _ => None,
         };
-        this.tb_retag_reference(val, new_perm)
+        if let Some(new_perm) = new_perm {
+            this.tb_retag_reference(val, new_perm)
+        } else {
+            Ok(val.clone())
+        }
     }
 
     /// Retag all pointers that are stored in this place.
@@ -405,9 +405,11 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
                 place: &PlaceTy<'tcx, Provenance>,
                 new_perm: Option<NewPermission>,
             ) -> InterpResult<'tcx> {
-                let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
-                let val = self.ecx.tb_retag_reference(&val, new_perm)?;
-                self.ecx.write_immediate(*val, place)?;
+                if let Some(new_perm) = new_perm {
+                    let val = self.ecx.read_immediate(&self.ecx.place_to_op(place)?)?;
+                    let val = self.ecx.tb_retag_reference(&val, new_perm)?;
+                    self.ecx.write_immediate(*val, place)?;
+                }
                 Ok(())
             }
         }
@@ -493,36 +495,25 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         }
     }
 
-    /// After a stack frame got pushed, retag the return place so that we are sure
-    /// it does not alias with anything.
-    ///
-    /// This is a HACK because there is nothing in MIR that would make the retag
-    /// explicit. Also see <https://github.com/rust-lang/rust/issues/71117>.
-    fn tb_retag_return_place(&mut self) -> InterpResult<'tcx> {
+    /// Protect a place so that it cannot be used any more for the duration of the current function
+    /// call.
+    /// 
+    /// This is used to ensure soundness of in-place function argument/return passing.
+    fn tb_protect_place(&mut self, place: &MPlaceTy<'tcx, Provenance>) -> InterpResult<'tcx> {
         let this = self.eval_context_mut();
-        //this.debug_hint_location();
-        let return_place = &this.frame().return_place;
-        if return_place.layout.is_zst() {
-            // There may not be any memory here, nothing to do.
-            return Ok(());
-        }
-        // We need this to be in-memory to use tagged pointers.
-        let return_place = this.force_allocation(&return_place.clone())?;
 
-        // We have to turn the place into a pointer to use the existing code.
+        // We have to turn the place into a pointer to use the usual retagging logic.
         // (The pointer type does not matter, so we use a raw pointer.)
-        let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, return_place.layout.ty))?;
-        let val = ImmTy::from_immediate(return_place.to_ref(this), ptr_layout);
-        // Reborrow it. With protection! That is part of the point.
-        let new_perm = Some(NewPermission {
+        let ptr_layout = this.layout_of(Ty::new_mut_ptr(this.tcx.tcx, place.layout.ty))?;
+        let ptr = ImmTy::from_immediate(place.to_ref(this), ptr_layout);
+        // Reborrow it. With protection! That is the entire point.
+        let new_perm = NewPermission {
             initial_state: Permission::new_active(),
             zero_size: false,
             protector: Some(ProtectorKind::StrongProtector),
-        });
-        let val = this.tb_retag_reference(&val, new_perm)?;
-        // And use reborrowed pointer for return place.
-        let return_place = this.ref_to_mplace(&val)?;
-        this.frame_mut().return_place = return_place.into();
+        };
+        let _new_ptr = this.tb_retag_reference(&ptr, new_perm)?;
+        // We just throw away `new_ptr`, so nobody can access this memory while it is protected.
 
         Ok(())
     }
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index 7e92dc7a0c7..4a093d7bcc6 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -55,6 +55,7 @@ extern crate rustc_index;
 extern crate rustc_session;
 extern crate rustc_span;
 extern crate rustc_target;
+extern crate either; // the one from rustc
 
 // Necessary to pull in object code as the rest of the rustc crates are shipped only as rmeta
 // files.
diff --git a/src/tools/miri/src/machine.rs b/src/tools/miri/src/machine.rs
index ac2bad22119..5510e3f94b7 100644
--- a/src/tools/miri/src/machine.rs
+++ b/src/tools/miri/src/machine.rs
@@ -7,6 +7,7 @@ use std::fmt;
 use std::path::Path;
 use std::process;
 
+use either::Either;
 use rand::rngs::StdRng;
 use rand::SeedableRng;
 
@@ -533,7 +534,7 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
             let target = &tcx.sess.target;
             match target.arch.as_ref() {
                 "wasm32" | "wasm64" => 64 * 1024, // https://webassembly.github.io/spec/core/exec/runtime.html#memory-instances
-                "aarch64" =>
+                "aarch64" => {
                     if target.options.vendor.as_ref() == "apple" {
                         // No "definitive" source, but see:
                         // https://www.wwdcnotes.com/notes/wwdc20/10214/
@@ -541,7 +542,8 @@ impl<'mir, 'tcx> MiriMachine<'mir, 'tcx> {
                         16 * 1024
                     } else {
                         4 * 1024
-                    },
+                    }
+                }
                 _ => 4 * 1024,
             }
         };
@@ -892,7 +894,7 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &mut MiriInterpCx<'mir, 'tcx>,
         instance: ty::Instance<'tcx>,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[FnArg<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -905,12 +907,13 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ecx: &mut MiriInterpCx<'mir, 'tcx>,
         fn_val: Dlsym,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[FnArg<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         _unwind: mir::UnwindAction,
     ) -> InterpResult<'tcx> {
-        ecx.call_dlsym(fn_val, abi, args, dest, ret)
+        let args = ecx.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+        ecx.call_dlsym(fn_val, abi, &args, dest, ret)
     }
 
     #[inline(always)]
@@ -1094,8 +1097,9 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         ptr: Pointer<Self::Provenance>,
     ) -> InterpResult<'tcx> {
         match ptr.provenance {
-            Provenance::Concrete { alloc_id, tag } =>
-                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag),
+            Provenance::Concrete { alloc_id, tag } => {
+                intptrcast::GlobalStateInner::expose_ptr(ecx, alloc_id, tag)
+            }
             Provenance::Wildcard => {
                 // No need to do anything for wildcard pointers as
                 // their provenances have already been previously exposed.
@@ -1206,6 +1210,25 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
         Ok(())
     }
 
+    fn protect_in_place_function_argument(
+        ecx: &mut InterpCx<'mir, 'tcx, Self>,
+        place: &PlaceTy<'tcx, Provenance>,
+    ) -> InterpResult<'tcx> {
+        // We do need to write `uninit` so that even after the call ends, the former contents of
+        // this place cannot be observed any more.
+        ecx.write_uninit(place)?;
+        // If we have a borrow tracker, we also have it set up protection so that all reads *and
+        // writes* during this call are insta-UB.
+        if ecx.machine.borrow_tracker.is_some() {
+            if let Either::Left(place) = place.as_mplace_or_local() {
+                ecx.protect_place(&place)?;
+            } else {
+                // Locals that don't have their address taken are as protected as they can ever be.
+            }
+        }
+        Ok(())
+    }
+
     #[inline(always)]
     fn init_frame_extra(
         ecx: &mut InterpCx<'mir, 'tcx, Self>,
@@ -1288,8 +1311,17 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             let stack_len = ecx.active_thread_stack().len();
             ecx.active_thread_mut().set_top_user_relevant_frame(stack_len - 1);
         }
-        if ecx.machine.borrow_tracker.is_some() {
-            ecx.retag_return_place()?;
+        Ok(())
+    }
+
+    fn before_stack_pop(
+        ecx: &InterpCx<'mir, 'tcx, Self>,
+        frame: &Frame<'mir, 'tcx, Self::Provenance, Self::FrameExtra>,
+    ) -> InterpResult<'tcx> {
+        // We want this *before* the return value copy, because the return place itself is protected
+        // until we do `end_call` here.
+        if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
+            borrow_tracker.borrow_mut().end_call(&frame.extra);
         }
         Ok(())
     }
@@ -1308,9 +1340,6 @@ impl<'mir, 'tcx> Machine<'mir, 'tcx> for MiriMachine<'mir, 'tcx> {
             ecx.active_thread_mut().recompute_top_user_relevant_frame();
         }
         let timing = frame.extra.timing.take();
-        if let Some(borrow_tracker) = &ecx.machine.borrow_tracker {
-            borrow_tracker.borrow_mut().end_call(&frame.extra);
-        }
         let res = ecx.handle_stack_pop_unwind(frame.extra, unwinding);
         if let Some(profiler) = ecx.machine.profiler.as_ref() {
             profiler.finish_recording_interval_event(timing.unwrap());
diff --git a/src/tools/miri/src/shims/mod.rs b/src/tools/miri/src/shims/mod.rs
index a423a0786b7..1027b24e301 100644
--- a/src/tools/miri/src/shims/mod.rs
+++ b/src/tools/miri/src/shims/mod.rs
@@ -31,7 +31,7 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
         &mut self,
         instance: ty::Instance<'tcx>,
         abi: Abi,
-        args: &[OpTy<'tcx, Provenance>],
+        args: &[FnArg<'tcx, Provenance>],
         dest: &PlaceTy<'tcx, Provenance>,
         ret: Option<mir::BasicBlock>,
         unwind: mir::UnwindAction,
@@ -41,7 +41,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
 
         // There are some more lang items we want to hook that CTFE does not hook (yet).
         if this.tcx.lang_items().align_offset_fn() == Some(instance.def.def_id()) {
-            let [ptr, align] = check_arg_count(args)?;
+            let args = this.copy_fn_args(args)?;
+            let [ptr, align] = check_arg_count(&args)?;
             if this.align_offset(ptr, align, dest, ret, unwind)? {
                 return Ok(None);
             }
@@ -55,7 +56,8 @@ pub trait EvalContextExt<'mir, 'tcx: 'mir>: crate::MiriInterpCxExt<'mir, 'tcx> {
             // to run extra MIR), and Ok(Some(body)) if we found MIR to run for the
             // foreign function
             // Any needed call to `goto_block` will be performed by `emulate_foreign_item`.
-            return this.emulate_foreign_item(instance.def_id(), abi, args, dest, ret, unwind);
+            let args = this.copy_fn_args(args)?; // FIXME: Should `InPlace` arguments be reset to uninit?
+            return this.emulate_foreign_item(instance.def_id(), abi, &args, dest, ret, unwind);
         }
 
         // Otherwise, load the MIR.
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
new file mode 100644
index 00000000000..625a8bda8af
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.rs
@@ -0,0 +1,34 @@
+//@revisions: stack tree
+//@[tree]compile-flags: -Zmiri-tree-borrows
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+pub struct S(i32);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn main() {
+    mir! {
+        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))
+        }
+        after_call = {
+            Return()
+        }
+
+    }
+}
+
+pub fn callee(x: S, ptr: *mut S) {
+    // With the setup above, if `x` is indeed moved in
+    // (i.e. we actually just get a pointer to the underlying storage),
+    // then writing to `ptr` will change the value stored in `x`!
+    unsafe { ptr.write(S(0)) };
+    //~[stack]^ ERROR: not granting access
+    //~[tree]| ERROR: /write access .* forbidden/
+    assert_eq!(x.0, 42);
+}
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
new file mode 100644
index 00000000000..471dc1dd6dd
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.stack.stderr
@@ -0,0 +1,37 @@
+error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(S(0)) };
+   |              ^^^^^^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+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 | |         {
+LL | |             let non_copy = S(42);
+...  |
+LL | |
+LL | |     }
+   | |_____^
+help: <TAG> is this argument
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(S(0)) };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC
+note: inside `main`
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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
+
+error: aborting due to previous error
+
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
new file mode 100644
index 00000000000..35c02cc2ebd
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_mutate.tree.stderr
@@ -0,0 +1,39 @@
+error: Undefined Behavior: write access through <TAG> (root of the allocation) is forbidden
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(S(0)) };
+   |              ^^^^^^^^^^^^^^^ write access through <TAG> (root of the allocation) is forbidden
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
+   = help: this foreign write access would cause the protected tag <TAG> to transition from Active to Disabled
+   = help: this transition would be a loss of read and write permissions, which is not allowed for protected tags
+help: the accessed tag <TAG> was created here
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL | /     mir! {
+LL | |         let unit: ();
+LL | |         {
+LL | |             let non_copy = S(42);
+...  |
+LL | |
+LL | |     }
+   | |_____^
+help: the protected tag <TAG> was created here, in the initial state Active
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |     unsafe { ptr.write(S(0)) };
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `callee` at $DIR/arg_inplace_mutate.rs:LL:CC
+note: inside `main`
+  --> $DIR/arg_inplace_mutate.rs:LL:CC
+   |
+LL |             Call(unit, after_call, callee(Move(*ptr), ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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
+
+error: aborting due to previous error
+
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
new file mode 100644
index 00000000000..8eda913feb4
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.rs
@@ -0,0 +1,27 @@
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+pub struct S(i32);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn main() {
+    // FIXME: the span is not great (probably caused by custom MIR)
+    mir! { //~ERROR: uninitialized
+        let unit: ();
+        {
+            let non_copy = S(42);
+            // This could change `non_copy` in-place
+            Call(unit, after_call, change_arg(Move(non_copy)))
+        }
+        after_call = {
+            // So now we must not be allowed to observe non-copy again.
+            let _observe = non_copy.0;
+            Return()
+        }
+
+    }
+}
+
+pub fn change_arg(mut x: S) {
+    x.0 = 0;
+}
diff --git a/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr
new file mode 100644
index 00000000000..3ff7976c70b
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_after.stderr
@@ -0,0 +1,22 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/arg_inplace_observe_after.rs:LL:CC
+   |
+LL | /     mir! {
+LL | |         let unit: ();
+LL | |         {
+LL | |             let non_copy = S(42);
+...  |
+LL | |
+LL | |     }
+   | |_____^ using uninitialized data, but this operation requires initialized memory
+   |
+   = 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 RUSTLIB/core/src/intrinsics/mir.rs:LL:CC
+   = 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
+
+error: aborting due to previous error
+
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
new file mode 100644
index 00000000000..baa91484793
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.none.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = 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 `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
+note: inside `main`
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/function_calls/arg_inplace_observe_during.rs b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
new file mode 100644
index 00000000000..2e57872db96
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.rs
@@ -0,0 +1,34 @@
+//@revisions: stack tree none
+//@[tree]compile-flags: -Zmiri-tree-borrows
+//@[none]compile-flags: -Zmiri-disable-stacked-borrows
+#![feature(custom_mir, core_intrinsics)]
+use std::intrinsics::mir::*;
+
+pub struct S(i32);
+
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+fn main() {
+    mir! {
+        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))
+        }
+        after_call = {
+            Return()
+        }
+
+    }
+}
+
+pub fn change_arg(mut x: S, ptr: *mut S) {
+    x.0 = 0;
+    // If `x` got passed in-place, we'd see the write through `ptr`!
+    // Make sure we are not allowed to do that read.
+    unsafe { ptr.read() };
+    //~[stack]^ ERROR: not granting access
+    //~[tree]| ERROR: /read access .* forbidden/
+    //~[none]| ERROR: uninitialized
+}
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
new file mode 100644
index 00000000000..a842d3a8044
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.stack.stderr
@@ -0,0 +1,37 @@
+error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
+   = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
+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 | |         {
+LL | |             let non_copy = S(42);
+...  |
+LL | |
+LL | |     }
+   | |_____^
+help: <TAG> is this argument
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
+note: inside `main`
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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
+
+error: aborting due to previous error
+
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
new file mode 100644
index 00000000000..cbd76c38f62
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/arg_inplace_observe_during.tree.stderr
@@ -0,0 +1,39 @@
+error: Undefined Behavior: read access through <TAG> (root of the allocation) is forbidden
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
+   |
+   = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
+   = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
+   = help: this foreign read access would cause the protected tag <TAG> to transition from Active to Frozen
+   = help: this transition would be a loss of write permissions, which is not allowed for protected tags
+help: the accessed tag <TAG> was created here
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL | /     mir! {
+LL | |         let unit: ();
+LL | |         {
+LL | |             let non_copy = S(42);
+...  |
+LL | |
+LL | |     }
+   | |_____^
+help: the protected tag <TAG> was created here, in the initial state Active
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |     x.0 = 0;
+   |     ^^^^^^^
+   = note: BACKTRACE (of the first span):
+   = note: inside `change_arg` at $DIR/arg_inplace_observe_during.rs:LL:CC
+note: inside `main`
+  --> $DIR/arg_inplace_observe_during.rs:LL:CC
+   |
+LL |             Call(unit, after_call, change_arg(Move(*ptr), ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = 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
+
+error: aborting due to previous error
+
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
new file mode 100644
index 00000000000..9d9dfc89f89
--- /dev/null
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.none.stderr
@@ -0,0 +1,20 @@
+error: Undefined Behavior: using uninitialized data, but this operation requires initialized memory
+  --> $DIR/return_pointer_aliasing.rs:LL:CC
+   |
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ using uninitialized data, but this operation requires initialized memory
+   |
+   = 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 `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
+note: inside `main`
+  --> $DIR/return_pointer_aliasing.rs:LL:CC
+   |
+LL |             Call(*ptr, after_call, myfun(ptr))
+   |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+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/both_borrows/return_pointer_aliasing.rs b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
index 03886e7874d..829809102fa 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.rs
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.rs
@@ -1,11 +1,11 @@
-//@revisions: stack tree
+//@revisions: stack tree none
 //@[tree]compile-flags: -Zmiri-tree-borrows
+//@[none]compile-flags: -Zmiri-disable-stacked-borrows
 #![feature(raw_ref_op)]
 #![feature(core_intrinsics)]
 #![feature(custom_mir)]
 
 use std::intrinsics::mir::*;
-use std::mem::MaybeUninit;
 
 #[custom_mir(dialect = "runtime", phase = "optimized")]
 pub fn main() {
@@ -25,8 +25,10 @@ pub fn main() {
 }
 
 fn myfun(ptr: *mut i32) -> i32 {
-    unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
-    //~[stack]^ ERROR: /not granting access/
+    unsafe { ptr.read() };
+    //~[stack]^ ERROR: not granting access
     //~[tree]| ERROR: /read access .* forbidden/
+    //~[none]| ERROR: uninitialized
+    // Without an aliasing model, reads are "fine" but at least they return uninit data.
     13
 }
diff --git a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
index 5bdddf5e49c..d486dcb95df 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.stack.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.stack.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |     unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ not granting access to tag <TAG> because that would remove [Unique for <TAG>] which is strongly protected because it is an argument of call ID
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Stacked Borrows rules it violated are still experimental
    = help: see https://github.com/rust-lang/unsafe-code-guidelines/blob/master/wip/stacked-borrows.md for further information
@@ -20,13 +20,8 @@ LL | |     }
 help: <TAG> is this argument
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL | / fn myfun(ptr: *mut i32) -> i32 {
-LL | |     unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
-LL | |
-LL | |
-LL | |     13
-LL | | }
-   | |_^
+LL |     unsafe { ptr.read() };
+   |     ^^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
index dd76d65c7ca..c2c9de3f4ee 100644
--- a/src/tools/miri/tests/fail/both_borrows/return_pointer_aliasing.tree.stderr
+++ b/src/tools/miri/tests/fail/function_calls/return_pointer_aliasing.tree.stderr
@@ -1,8 +1,8 @@
 error: Undefined Behavior: read access through <TAG> (root of the allocation) is forbidden
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL |     unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
-   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
+LL |     unsafe { ptr.read() };
+   |              ^^^^^^^^^^ read access through <TAG> (root of the allocation) is forbidden
    |
    = help: this indicates a potential bug in the program: it performed an invalid operation, but the Tree Borrows rules it violated are still experimental
    = help: the accessed tag <TAG> (root of the allocation) is foreign to the protected tag <TAG> (i.e., it is not a child)
@@ -22,13 +22,8 @@ LL | |     }
 help: the protected tag <TAG> was created here, in the initial state Active
   --> $DIR/return_pointer_aliasing.rs:LL:CC
    |
-LL | / fn myfun(ptr: *mut i32) -> i32 {
-LL | |     unsafe { ptr.cast::<MaybeUninit<i32>>().read() };
-LL | |
-LL | |
-LL | |     13
-LL | | }
-   | |_^
+LL |     unsafe { ptr.read() };
+   |     ^^^^^^^^^^^^^^^^^^^^^
    = note: BACKTRACE (of the first span):
    = note: inside `myfun` at $DIR/return_pointer_aliasing.rs:LL:CC
 note: inside `main`
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
index 6d31ded75c6..555aa57de30 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
+++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.rs
@@ -1,5 +1,6 @@
-// should find the bug even without validation and stacked borrows, but gets masked by optimizations
-//@compile-flags: -Zmiri-disable-validation -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
+// should find the bug even without, but gets masked by optimizations
+//@compile-flags: -Zmiri-disable-stacked-borrows -Zmir-opt-level=0 -Cdebug-assertions=no
+//@normalize-stderr-test: "but found [0-9]+" -> "but found $$ALIGN"
 
 #[repr(align(256))]
 #[derive(Debug)]
@@ -19,6 +20,6 @@ fn main() {
             (&mut ptr as *mut _ as *mut *const u8).write(&buf as *const _ as *const u8);
         }
         // Re-borrow that. This should be UB.
-        let _ptr = &*ptr; //~ERROR: alignment 256 is required
+        let _ptr = &*ptr; //~ERROR: required 256 byte alignment
     }
 }
diff --git a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
index a900b46612b..503721b9551 100644
--- a/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
+++ b/src/tools/miri/tests/fail/unaligned_pointers/dyn_alignment.stderr
@@ -1,8 +1,8 @@
-error: Undefined Behavior: accessing memory with alignment ALIGN, but alignment ALIGN is required
+error: Undefined Behavior: constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $ALIGN)
   --> $DIR/dyn_alignment.rs:LL:CC
    |
 LL |         let _ptr = &*ptr;
-   |                    ^^^^^ accessing memory with alignment ALIGN, but alignment ALIGN is required
+   |                    ^^^^^ constructing invalid value: encountered an unaligned reference (required 256 byte alignment but found $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
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
new file mode 100644
index 00000000000..dcfebd0f82b
--- /dev/null
+++ b/src/tools/miri/tests/pass/function_calls/return_place_on_heap.rs
@@ -0,0 +1,25 @@
+#![feature(raw_ref_op)]
+#![feature(core_intrinsics)]
+#![feature(custom_mir)]
+
+use std::intrinsics::mir::*;
+
+// Make sure calls with the return place "on the heap" work.
+#[custom_mir(dialect = "runtime", phase = "optimized")]
+pub fn main() {
+    mir! {
+        {
+            let x = 0;
+            let ptr = &raw mut x;
+            Call(*ptr, after_call, myfun())
+        }
+
+        after_call = {
+            Return()
+        }
+    }
+}
+
+fn myfun() -> i32 {
+    13
+}
diff --git a/src/tools/rls/Cargo.toml b/src/tools/rls/Cargo.toml
index b84647eb332..b7aa659c25a 100644
--- a/src/tools/rls/Cargo.toml
+++ b/src/tools/rls/Cargo.toml
@@ -5,5 +5,4 @@ edition = "2021"
 license = "Apache-2.0/MIT"
 
 [dependencies]
-serde = { version = "1.0.143", features = ["derive"] }
 serde_json = "1.0.83"
diff --git a/src/tools/rls/src/main.rs b/src/tools/rls/src/main.rs
index f96f1325d96..d7be108e89c 100644
--- a/src/tools/rls/src/main.rs
+++ b/src/tools/rls/src/main.rs
@@ -3,7 +3,7 @@
 //! This is a small stub that replaces RLS to alert the user that RLS is no
 //! longer available.
 
-use serde::Deserialize;
+use serde_json::Value;
 use std::error::Error;
 use std::io::BufRead;
 use std::io::Write;
@@ -21,7 +21,6 @@ fn main() {
     }
 }
 
-#[derive(Deserialize)]
 struct Message {
     method: Option<String>,
 }
@@ -88,8 +87,10 @@ fn read_message_raw<R: BufRead>(reader: &mut R) -> Result<String, Box<dyn Error>
 
 fn read_message<R: BufRead>(reader: &mut R) -> Result<Message, Box<dyn Error>> {
     let m = read_message_raw(reader)?;
-    match serde_json::from_str(&m) {
-        Ok(m) => Ok(m),
+    match serde_json::from_str::<Value>(&m) {
+        Ok(message) => Ok(Message {
+            method: message.get("method").and_then(|value| value.as_str().map(String::from)),
+        }),
         Err(e) => Err(format!("failed to parse message {m}\n{e}").into()),
     }
 }
diff --git a/src/tools/tidy/src/pal.rs b/src/tools/tidy/src/pal.rs
index 62c070221dc..b386b000bef 100644
--- a/src/tools/tidy/src/pal.rs
+++ b/src/tools/tidy/src/pal.rs
@@ -39,7 +39,6 @@ const EXCEPTION_PATHS: &[&str] = &[
     "library/panic_unwind",
     "library/unwind",
     "library/rtstartup", // Not sure what to do about this. magic stuff for mingw
-    "library/term",      // Not sure how to make this crate portable, but test crate needs it.
     "library/test",      // Probably should defer to unstable `std::sys` APIs.
     // The `VaList` implementation must have platform specific code.
     // The Windows implementation of a `va_list` is always a character
diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.rs b/tests/ui-fulldeps/missing-rustc-driver-error.rs
index 654cd6f6dc9..b627a207c98 100644
--- a/tests/ui-fulldeps/missing-rustc-driver-error.rs
+++ b/tests/ui-fulldeps/missing-rustc-driver-error.rs
@@ -1,8 +1,8 @@
 // Test that we get the following hint when trying to use a compiler crate without rustc_driver.
 // error-pattern: try adding `extern crate rustc_driver;` at the top level of this crate
 // compile-flags: --emit link
-// The exactly list of required crates depends on the target. as such only test Unix targets.
-// only-unix
+// normalize-stderr-test ".*crate .* required.*\n\n" -> ""
+// normalize-stderr-test: "aborting due to [0-9]+" -> "aborting due to NUMBER"
 
 #![feature(rustc_private)]
 
diff --git a/tests/ui-fulldeps/missing-rustc-driver-error.stderr b/tests/ui-fulldeps/missing-rustc-driver-error.stderr
index 939e888e5cb..d7bf27d6349 100644
--- a/tests/ui-fulldeps/missing-rustc-driver-error.stderr
+++ b/tests/ui-fulldeps/missing-rustc-driver-error.stderr
@@ -2,15 +2,5 @@ error: crate `rustc_serialize` required to be available in rlib format, but was
    |
    = help: try adding `extern crate rustc_driver;` at the top level of this crate
 
-error: crate `smallvec` required to be available in rlib format, but was not found in this form
-
-error: crate `thin_vec` required to be available in rlib format, but was not found in this form
-
-error: crate `indexmap` required to be available in rlib format, but was not found in this form
-
-error: crate `hashbrown` required to be available in rlib format, but was not found in this form
-
-error: crate `equivalent` required to be available in rlib format, but was not found in this form
-
-error: aborting due to 6 previous errors
+error: aborting due to NUMBER previous errors
 
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
index 771acb6c4e7..58ce41d1a89 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
new file mode 100644
index 00000000000..95ef7d82fca
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/bad-inputs-and-output.stderr
@@ -0,0 +1,48 @@
+error: return type notation uses `()` instead of `(..)` for elided arguments
+  --> $DIR/bad-inputs-and-output.rs:18:24
+   |
+LL | fn baz<T: Trait<method(..): Send>>() {}
+   |                        ^^ help: remove the `..`
+
+error[E0658]: associated type bounds are unstable
+  --> $DIR/bad-inputs-and-output.rs:10:17
+   |
+LL | fn foo<T: Trait<method(i32): Send>>() {}
+   |                 ^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+error[E0658]: associated type bounds are unstable
+  --> $DIR/bad-inputs-and-output.rs:14:17
+   |
+LL | fn bar<T: Trait<method() -> (): Send>>() {}
+   |                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #52662 <https://github.com/rust-lang/rust/issues/52662> for more information
+   = help: add `#![feature(associated_type_bounds)]` to the crate attributes to enable
+
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/bad-inputs-and-output.rs:3:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: argument types not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:10:23
+   |
+LL | fn foo<T: Trait<method(i32): Send>>() {}
+   |                       ^^^^^ help: remove the input types: `()`
+
+error: return type not allowed with return type notation
+  --> $DIR/bad-inputs-and-output.rs:14:25
+   |
+LL | fn bar<T: Trait<method() -> (): Send>>() {}
+   |                         ^^^^^^ help: remove the return type
+
+error: aborting due to 5 previous errors; 1 warning emitted
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/associated-type-bounds/return-type-notation/basic.rs b/tests/ui/associated-type-bounds/return-type-notation/basic.rs
index d443c9dc11b..3dd9249a791 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/basic.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/basic.rs
@@ -1,9 +1,6 @@
-// revisions: current_with current_without next_with next_without
-// [next_with] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// [next_without] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: with without
 // edition: 2021
-// [current_with] check-pass
-// [next_with] check-pass
+// [with] check-pass
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
@@ -20,12 +17,11 @@ async fn foo<T: Foo>() -> Result<(), ()> {
 fn is_send(_: impl Send) {}
 
 fn test<
-    #[cfg(any(current_with, next_with))] T: Foo<method(): Send>,
-    #[cfg(any(current_without, next_without))] T: Foo,
+    #[cfg(with)] T: Foo<method(): Send>,
+    #[cfg(without)] T: Foo,
 >() {
     is_send(foo::<T>());
-    //[current_without]~^ ERROR future cannot be sent between threads safely
-    //[next_without]~^^ ERROR future cannot be sent between threads safely
+    //[without]~^ ERROR future cannot be sent between threads safely
 }
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.rs b/tests/ui/associated-type-bounds/return-type-notation/equality.rs
index 0d6545cc298..6884305d7b3 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/equality.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_type_notation, async_fn_in_trait)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/associated-type-bounds/return-type-notation/equality.stderr b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr
new file mode 100644
index 00000000000..490bfdc4c3c
--- /dev/null
+++ b/tests/ui/associated-type-bounds/return-type-notation/equality.stderr
@@ -0,0 +1,17 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/equality.rs:3:12
+   |
+LL | #![feature(return_type_notation, async_fn_in_trait)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed to use type equality
+  --> $DIR/equality.rs:12:18
+   |
+LL | fn test<T: Trait<method() = Box<dyn Future<Output = ()>>>>() {}
+   |                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error; 1 warning emitted
+
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.rs b/tests/ui/async-await/edition-deny-async-fns-2015.rs
index d4c30dc9d82..6bd6d879a4a 100644
--- a/tests/ui/async-await/edition-deny-async-fns-2015.rs
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.rs
@@ -1,6 +1,4 @@
 // edition:2015
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 async fn foo() {} //~ ERROR `async fn` is not permitted in Rust 2015
 
diff --git a/tests/ui/async-await/edition-deny-async-fns-2015.stderr b/tests/ui/async-await/edition-deny-async-fns-2015.stderr
new file mode 100644
index 00000000000..ba918eb28de
--- /dev/null
+++ b/tests/ui/async-await/edition-deny-async-fns-2015.stderr
@@ -0,0 +1,98 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:3:1
+   |
+LL | async fn foo() {}
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:5:12
+   |
+LL | fn baz() { async fn foo() {} }
+   |            ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:7:1
+   |
+LL | async fn async_baz() {
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:8:5
+   |
+LL |     async fn bar() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:14:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:18:5
+   |
+LL |     async fn foo() {}
+   |     ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:36:9
+   |
+LL |         async fn bar() {}
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:26:9
+   |
+LL |         async fn foo() {}
+   |         ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/edition-deny-async-fns-2015.rs:31:13
+   |
+LL |             async fn bar() {}
+   |             ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error[E0706]: functions in traits cannot be declared `async`
+  --> $DIR/edition-deny-async-fns-2015.rs:18:5
+   |
+LL |     async fn foo() {}
+   |     -----^^^^^^^^^
+   |     |
+   |     `async` because of this
+   |
+   = note: `async` trait functions are not currently supported
+   = note: consider using the `async-trait` crate: https://crates.io/crates/async-trait
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(async_fn_in_trait)]` to the crate attributes to enable
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0670, E0706.
+For more information about an error, try `rustc --explain E0670`.
diff --git a/tests/ui/async-await/in-trait/async-associated-types.rs b/tests/ui/async-await/in-trait/async-associated-types.rs
index 89ca4039bce..974f5aaff83 100644
--- a/tests/ui/async-await/in-trait/async-associated-types.rs
+++ b/tests/ui/async-await/in-trait/async-associated-types.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(impl_trait_projections)]
diff --git a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
index 99c3ba6a3c2..06413fe6f82 100644
--- a/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
+++ b/tests/ui/async-await/in-trait/async-default-fn-overridden.rs
@@ -1,7 +1,5 @@
 // run-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
index 7b53379b24b..38ba297189c 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
new file mode 100644
index 00000000000..168ef8e9ee4
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -0,0 +1,17 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/async-example-desugared-boxed-in-trait.rs:15:28
+   |
+LL |     async fn foo(&self) -> i32 {
+   |                            ^^^ expected `Pin<Box<dyn Future<Output = i32>>>`, found future
+   |
+note: type in trait
+  --> $DIR/async-example-desugared-boxed-in-trait.rs:11:22
+   |
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
+              found signature `fn(&i32) -> impl Future<Output = i32>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
index 916488ffafa..1b1b3cffd58 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
new file mode 100644
index 00000000000..60fa534a64f
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-boxed.rs:15:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>> {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
index edac0b374a3..81e1e59a362 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-extra.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
index 934f7643dd1..feeda719e03 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-in-trait.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
index 4883828d32f..71473e7455f 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
new file mode 100644
index 00000000000..567a36a86d1
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-example-desugared-manual.stderr
@@ -0,0 +1,11 @@
+error: method `foo` should be async because the method from the trait is async
+  --> $DIR/async-example-desugared-manual.rs:23:5
+   |
+LL |     async fn foo(&self) -> i32;
+   |     --------------------------- required because the trait method is async
+...
+LL |     fn foo(&self) -> MyFuture {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/async-example-desugared.rs b/tests/ui/async-await/in-trait/async-example-desugared.rs
index 214171b2e2c..fb92ec78674 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared.rs
+++ b/tests/ui/async-await/in-trait/async-example-desugared.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
index 146e74ec2d0..a73d55adfec 100644
--- a/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.rs
@@ -1,8 +1,6 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
new file mode 100644
index 00000000000..f1f0d7e5907
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics-and-bounds.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:12:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics-and-bounds.rs:12:18
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics-and-bounds.rs:12:28
+   |
+LL |     async fn foo(&self) -> &(T, U) where T: Debug + Sized, U: Hash;
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-generics.rs b/tests/ui/async-await/in-trait/async-generics.rs
index 507500abf4e..67000e5770e 100644
--- a/tests/ui/async-await/in-trait/async-generics.rs
+++ b/tests/ui/async-await/in-trait/async-generics.rs
@@ -1,8 +1,6 @@
 // check-fail
 // known-bug: #102682
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-generics.stderr b/tests/ui/async-await/in-trait/async-generics.stderr
new file mode 100644
index 00000000000..2f05564564c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-generics.stderr
@@ -0,0 +1,37 @@
+error[E0311]: the parameter type `U` may not live long enough
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `U` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:9:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error[E0311]: the parameter type `T` may not live long enough
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+   |
+note: the parameter type `T` must be valid for the anonymous lifetime defined here...
+  --> $DIR/async-generics.rs:9:18
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                  ^^^^^
+note: ...so that the reference type `&(T, U)` does not outlive the data it points at
+  --> $DIR/async-generics.rs:9:28
+   |
+LL |     async fn foo(&self) -> &(T, U);
+   |                            ^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0311`.
diff --git a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
index 9869a8d71c2..d5481d277e4 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes-and-bounds.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-lifetimes.rs b/tests/ui/async-await/in-trait/async-lifetimes.rs
index ecbd1910ac4..f298e45d239 100644
--- a/tests/ui/async-await/in-trait/async-lifetimes.rs
+++ b/tests/ui/async-await/in-trait/async-lifetimes.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.rs b/tests/ui/async-await/in-trait/async-recursive-generic.rs
index 64c6ba15c0c..6839abd381c 100644
--- a/tests/ui/async-await/in-trait/async-recursive-generic.rs
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-recursive-generic.stderr b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
new file mode 100644
index 00000000000..cab173bdd5b
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive-generic.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/async-recursive-generic.rs:11:48
+   |
+LL |     async fn foo_recursive(&self, n: usize) -> T {
+   |                                                ^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/async-recursive.rs b/tests/ui/async-await/in-trait/async-recursive.rs
index d928909e3ae..61119f8095b 100644
--- a/tests/ui/async-await/in-trait/async-recursive.rs
+++ b/tests/ui/async-await/in-trait/async-recursive.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/async-recursive.stderr b/tests/ui/async-await/in-trait/async-recursive.stderr
new file mode 100644
index 00000000000..9feff37b3fe
--- /dev/null
+++ b/tests/ui/async-await/in-trait/async-recursive.stderr
@@ -0,0 +1,12 @@
+error[E0733]: recursion in an `async fn` requires boxing
+  --> $DIR/async-recursive.rs:11:48
+   |
+LL |     async fn foo_recursive(&self, n: usize) -> i32 {
+   |                                                ^^^ recursive `async fn`
+   |
+   = note: a recursive `async fn` must be rewritten to return a boxed `dyn Future`
+   = note: consider using the `async_recursion` crate: https://crates.io/crates/async_recursion
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0733`.
diff --git a/tests/ui/async-await/in-trait/bad-signatures.rs b/tests/ui/async-await/in-trait/bad-signatures.rs
index 4baddd8ccb8..98dddc126c5 100644
--- a/tests/ui/async-await/in-trait/bad-signatures.rs
+++ b/tests/ui/async-await/in-trait/bad-signatures.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/bad-signatures.stderr b/tests/ui/async-await/in-trait/bad-signatures.stderr
new file mode 100644
index 00000000000..7cbd96e2487
--- /dev/null
+++ b/tests/ui/async-await/in-trait/bad-signatures.stderr
@@ -0,0 +1,17 @@
+error: expected identifier, found keyword `self`
+  --> $DIR/bad-signatures.rs:6:23
+   |
+LL |     async fn bar(&abc self);
+   |                       ^^^^ expected identifier, found keyword
+
+error: expected one of `:`, `@`, or `|`, found keyword `self`
+  --> $DIR/bad-signatures.rs:6:23
+   |
+LL |     async fn bar(&abc self);
+   |                  -----^^^^
+   |                  |    |
+   |                  |    expected one of `:`, `@`, or `|`
+   |                  help: declare the type after the parameter binding: `<identifier>: <type>`
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
index 7183eaccc93..afd3db5e052 100644
--- a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.rs
@@ -1,7 +1,5 @@
 // edition: 2021
 // known-bug: #108309
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(min_specialization)]
diff --git a/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
new file mode 100644
index 00000000000..7c750bf5101
--- /dev/null
+++ b/tests/ui/async-await/in-trait/dont-project-to-specializable-projection.stderr
@@ -0,0 +1,25 @@
+error[E0053]: method `foo` has an incompatible type for trait
+  --> $DIR/dont-project-to-specializable-projection.rs:14:35
+   |
+LL |     default async fn foo(_: T) -> &'static str {
+   |                                   ^^^^^^^^^^^^ expected associated type, found future
+   |
+note: type in trait
+  --> $DIR/dont-project-to-specializable-projection.rs:10:27
+   |
+LL |     async fn foo(_: T) -> &'static str;
+   |                           ^^^^^^^^^^^^
+   = note: expected signature `fn(_) -> impl Future<Output = &'static str>`
+              found signature `fn(_) -> impl Future<Output = &'static str>`
+
+error: async associated function in trait cannot be specialized
+  --> $DIR/dont-project-to-specializable-projection.rs:14:5
+   |
+LL |     default async fn foo(_: T) -> &'static str {
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(async_fn_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/async-await/in-trait/early-bound-1.rs b/tests/ui/async-await/in-trait/early-bound-1.rs
index 30843473def..6b3b142014b 100644
--- a/tests/ui/async-await/in-trait/early-bound-1.rs
+++ b/tests/ui/async-await/in-trait/early-bound-1.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/early-bound-2.rs b/tests/ui/async-await/in-trait/early-bound-2.rs
index 1c5a68c2a5a..270443229b0 100644
--- a/tests/ui/async-await/in-trait/early-bound-2.rs
+++ b/tests/ui/async-await/in-trait/early-bound-2.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.rs b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
index 5fdb7296aaf..78017429f73 100644
--- a/tests/ui/async-await/in-trait/fn-not-async-err2.rs
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/fn-not-async-err2.stderr b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
new file mode 100644
index 00000000000..37d9669c012
--- /dev/null
+++ b/tests/ui/async-await/in-trait/fn-not-async-err2.stderr
@@ -0,0 +1,12 @@
+error[E0562]: `impl Trait` only allowed in function and inherent method return types, not in `impl` method return types
+  --> $DIR/fn-not-async-err2.rs:13:22
+   |
+LL |     fn foo(&self) -> impl Future<Output = i32> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #91611 <https://github.com/rust-lang/rust/issues/91611> for more information
+   = help: add `#![feature(return_position_impl_trait_in_trait)]` to the crate attributes to enable
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0562`.
diff --git a/tests/ui/async-await/in-trait/implied-bounds.rs b/tests/ui/async-await/in-trait/implied-bounds.rs
index 45ada1d84c3..52bceb3cc5c 100644
--- a/tests/ui/async-await/in-trait/implied-bounds.rs
+++ b/tests/ui/async-await/in-trait/implied-bounds.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/issue-102138.rs b/tests/ui/async-await/in-trait/issue-102138.rs
index ced30b7e4e4..f61b34ed99e 100644
--- a/tests/ui/async-await/in-trait/issue-102138.rs
+++ b/tests/ui/async-await/in-trait/issue-102138.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/issue-102219.rs b/tests/ui/async-await/in-trait/issue-102219.rs
index f3fdfa3459a..9a35f6515cb 100644
--- a/tests/ui/async-await/in-trait/issue-102219.rs
+++ b/tests/ui/async-await/in-trait/issue-102219.rs
@@ -1,8 +1,6 @@
 // compile-flags:--crate-type=lib
 // edition:2021
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/issue-102310.rs b/tests/ui/async-await/in-trait/issue-102310.rs
index 8e5dbd08eb9..49c3e9feeb4 100644
--- a/tests/ui/async-await/in-trait/issue-102310.rs
+++ b/tests/ui/async-await/in-trait/issue-102310.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/issue-104678.rs b/tests/ui/async-await/in-trait/issue-104678.rs
index 3d010f18009..e396df4e5d1 100644
--- a/tests/ui/async-await/in-trait/issue-104678.rs
+++ b/tests/ui/async-await/in-trait/issue-104678.rs
@@ -1,7 +1,5 @@
 // edition:2021
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.rs b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
index 46183f72bce..bb793df5d85 100644
--- a/tests/ui/async-await/in-trait/lifetime-mismatch.rs
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/lifetime-mismatch.stderr b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
new file mode 100644
index 00000000000..86592269c02
--- /dev/null
+++ b/tests/ui/async-await/in-trait/lifetime-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0195]: lifetime parameters or bounds on method `foo` do not match the trait declaration
+  --> $DIR/lifetime-mismatch.rs:11:17
+   |
+LL |     async fn foo<'a>(&self);
+   |                 ---- lifetimes in impl do not match this method in trait
+...
+LL |     async fn foo(&self) {}
+   |                 ^ lifetimes do not match method in trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0195`.
diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.rs b/tests/ui/async-await/in-trait/missing-feature-flag.rs
index 6481f4a7059..34dd50a1c30 100644
--- a/tests/ui/async-await/in-trait/missing-feature-flag.rs
+++ b/tests/ui/async-await/in-trait/missing-feature-flag.rs
@@ -1,6 +1,4 @@
 // edition:2018
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 #![feature(min_specialization)]
diff --git a/tests/ui/async-await/in-trait/missing-feature-flag.stderr b/tests/ui/async-await/in-trait/missing-feature-flag.stderr
new file mode 100644
index 00000000000..f6aba1fcdbf
--- /dev/null
+++ b/tests/ui/async-await/in-trait/missing-feature-flag.stderr
@@ -0,0 +1,30 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/missing-feature-flag.rs:12:1
+   |
+LL |     async fn foo(_: T) -> &'static str;
+   |     ----------------------------------- `foo` from trait
+...
+LL | impl<T> MyTrait<T> for MyStruct {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error[E0520]: `foo` specializes an item from a parent `impl`, but that item is not marked `default`
+  --> $DIR/missing-feature-flag.rs:16:5
+   |
+LL | impl<T> MyTrait<T> for MyStruct {}
+   | ------------------------------- parent `impl` is here
+...
+LL |     async fn foo(_: i32) -> &'static str {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot specialize default item `foo`
+   |
+   = note: to specialize, `foo` in the parent `impl` must be marked `default`
+
+error[E0308]: mismatched types
+  --> $DIR/missing-feature-flag.rs:16:42
+   |
+LL |     async fn foo(_: i32) -> &'static str {}
+   |                                          ^^ expected `&str`, found `()`
+
+error: aborting due to 3 previous errors
+
+Some errors have detailed explanations: E0046, E0308, E0520.
+For more information about an error, try `rustc --explain E0046`.
diff --git a/tests/ui/async-await/in-trait/missing-send-bound.rs b/tests/ui/async-await/in-trait/missing-send-bound.rs
index b602865cbb1..dbcc6657618 100644
--- a/tests/ui/async-await/in-trait/missing-send-bound.rs
+++ b/tests/ui/async-await/in-trait/missing-send-bound.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/missing-send-bound.stderr b/tests/ui/async-await/in-trait/missing-send-bound.stderr
new file mode 100644
index 00000000000..18185b75554
--- /dev/null
+++ b/tests/ui/async-await/in-trait/missing-send-bound.stderr
@@ -0,0 +1,20 @@
+error: future cannot be sent between threads safely
+  --> $DIR/missing-send-bound.rs:14:20
+   |
+LL |     assert_is_send(test::<T>());
+   |                    ^^^^^^^^^^^ future returned by `test` is not `Send`
+   |
+   = help: within `impl Future<Output = ()>`, the trait `Send` is not implemented for `impl Future<Output = ()>`
+note: future is not `Send` as it awaits another future which is not `Send`
+  --> $DIR/missing-send-bound.rs:10:5
+   |
+LL |     T::bar().await;
+   |     ^^^^^^^^ await occurs here on type `impl Future<Output = ()>`, which is not `Send`
+note: required by a bound in `assert_is_send`
+  --> $DIR/missing-send-bound.rs:18:27
+   |
+LL | fn assert_is_send(_: impl Send) {}
+   |                           ^^^^ required by this bound in `assert_is_send`
+
+error: aborting due to previous error
+
diff --git a/tests/ui/async-await/in-trait/object-safety.rs b/tests/ui/async-await/in-trait/object-safety.rs
index 4edad1512e9..441539e5dd4 100644
--- a/tests/ui/async-await/in-trait/object-safety.rs
+++ b/tests/ui/async-await/in-trait/object-safety.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/object-safety.stderr b/tests/ui/async-await/in-trait/object-safety.stderr
new file mode 100644
index 00000000000..ccdf9d88708
--- /dev/null
+++ b/tests/ui/async-await/in-trait/object-safety.stderr
@@ -0,0 +1,18 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:10:12
+   |
+LL |     let x: &dyn Foo = todo!();
+   |            ^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:6:14
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     async fn foo(&self);
+   |              ^^^ ...because method `foo` is `async`
+   = help: consider moving `foo` to another trait
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.rs b/tests/ui/async-await/in-trait/return-not-existing-pair.rs
index d1b3832d12b..a14dfceed75 100644
--- a/tests/ui/async-await/in-trait/return-not-existing-pair.rs
+++ b/tests/ui/async-await/in-trait/return-not-existing-pair.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/return-not-existing-pair.stderr b/tests/ui/async-await/in-trait/return-not-existing-pair.stderr
new file mode 100644
index 00000000000..e573b851706
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-not-existing-pair.stderr
@@ -0,0 +1,39 @@
+error[E0726]: implicit elided lifetime not allowed here
+  --> $DIR/return-not-existing-pair.rs:10:20
+   |
+LL | impl<'a, 'b, T, U> MyTrait<T> for U {
+   |                    ^^^^^^^^^^ expected lifetime parameters
+   |
+help: indicate the anonymous lifetimes
+   |
+LL | impl<'a, 'b, T, U> MyTrait<'_, '_, T> for U {
+   |                            +++++++
+
+error[E0412]: cannot find type `ConnImpl` in this scope
+  --> $DIR/return-not-existing-pair.rs:6:48
+   |
+LL |     async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T);
+   |                                                ^^^^^^^^ not found in this scope
+
+error[E0186]: method `foo` has a `&self` declaration in the trait, but not in the impl
+  --> $DIR/return-not-existing-pair.rs:12:5
+   |
+LL |     async fn foo(&'a self, key: &'b T) -> (&'a ConnImpl, &'b T);
+   |     ------------------------------------------------------------ `&self` used in trait
+...
+LL |     async fn foo(_: T) -> (&'a U, &'b T) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `&self` in impl
+
+error[E0308]: mismatched types
+  --> $DIR/return-not-existing-pair.rs:12:42
+   |
+LL |     async fn foo(_: T) -> (&'a U, &'b T) {}
+   |                                          ^^ expected `(&U, &T)`, found `()`
+   |
+   = note:  expected tuple `(&'a U, &'b T)`
+           found unit type `()`
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0186, E0308, E0412, E0726.
+For more information about an error, try `rustc --explain E0186`.
diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs
index 37c02827e8d..254b9a7824f 100644
--- a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs
+++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr
new file mode 100644
index 00000000000..059934d245c
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-not-existing-type-wrapping-rpitit.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type `Missing` in this scope
+  --> $DIR/return-not-existing-type-wrapping-rpitit.rs:8:25
+   |
+LL |     fn bar() -> Wrapper<Missing<impl Sized>>;
+   |                         ^^^^^^^ not found in this scope
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.rs b/tests/ui/async-await/in-trait/return-type-suggestion.rs
index d63bccefa9f..92a9e035e89 100644
--- a/tests/ui/async-await/in-trait/return-type-suggestion.rs
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait)]
 
diff --git a/tests/ui/async-await/in-trait/return-type-suggestion.stderr b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
new file mode 100644
index 00000000000..d9309459812
--- /dev/null
+++ b/tests/ui/async-await/in-trait/return-type-suggestion.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/return-type-suggestion.rs:7:9
+   |
+LL |         Ok(())
+   |         ^^^^^^- help: consider using a semicolon here: `;`
+   |         |
+   |         expected `()`, found `Result<(), _>`
+   |
+   = note: expected unit type `()`
+                   found enum `Result<(), _>`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.rs b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
index eee31aa1fe5..0ecbca5c13b 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-early.rs
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.rs
@@ -1,7 +1,5 @@
 // edition: 2021
 // known-bug: #110963
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_type_notation)]
 #![feature(async_fn_in_trait)]
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-early.stderr b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
new file mode 100644
index 00000000000..33e22dec3f7
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-early.stderr
@@ -0,0 +1,37 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-early.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:15:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+
+error: higher-ranked lifetime error
+  --> $DIR/issue-110963-early.rs:15:5
+   |
+LL | /     spawn(async move {
+LL | |         let mut hc = hc;
+LL | |         if !hc.check().await {
+LL | |             log_health_check_failure().await;
+LL | |         }
+LL | |     });
+   | |______^
+   |
+   = note: could not prove `[async block@$DIR/issue-110963-early.rs:15:11: 20:6]: Send`
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.rs b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
index ea047cd3b16..17b5d775d44 100644
--- a/tests/ui/async-await/return-type-notation/issue-110963-late.rs
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.rs
@@ -1,7 +1,5 @@
 // edition: 2021
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/return-type-notation/issue-110963-late.stderr b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr
new file mode 100644
index 00000000000..9c6966537a7
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/issue-110963-late.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/issue-110963-late.rs:4:12
+   |
+LL | #![feature(return_type_notation)]
+   |            ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.rs b/tests/ui/async-await/return-type-notation/super-method-bound.rs
index 0163c62f545..58ea3578db6 100644
--- a/tests/ui/async-await/return-type-notation/super-method-bound.rs
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.rs
@@ -1,7 +1,5 @@
 // edition:2021
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound.stderr b/tests/ui/async-await/return-type-notation/super-method-bound.stderr
new file mode 100644
index 00000000000..ac0668d3c44
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/super-method-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/super-method-bound.rs:4:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.rs b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
index 09de32c5d4a..19bcfe3046b 100644
--- a/tests/ui/async-await/return-type-notation/supertrait-bound.rs
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete and may not be safe to use
diff --git a/tests/ui/async-await/return-type-notation/supertrait-bound.stderr b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
new file mode 100644
index 00000000000..c8cec4946b4
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/supertrait-bound.stderr
@@ -0,0 +1,11 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/supertrait-bound.rs:3:49
+   |
+LL | #![feature(return_position_impl_trait_in_trait, return_type_notation)]
+   |                                                 ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
index 3141da1d296..7871a2fed03 100644
--- a/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
+++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.rs
@@ -1,6 +1,4 @@
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait, return_type_notation)]
 //~^ WARN the feature `return_type_notation` is incomplete
diff --git a/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr b/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr
new file mode 100644
index 00000000000..76928c5d7a3
--- /dev/null
+++ b/tests/ui/async-await/return-type-notation/ty-or-ct-params.stderr
@@ -0,0 +1,29 @@
+warning: the feature `return_type_notation` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/ty-or-ct-params.rs:3:31
+   |
+LL | #![feature(async_fn_in_trait, return_type_notation)]
+   |                               ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: return type notation is not allowed for functions that have type parameters
+  --> $DIR/ty-or-ct-params.rs:14:12
+   |
+LL |     async fn bar<T>() {}
+   |                  - type parameter declared here
+...
+LL |     T: Foo<bar(): Send, baz(): Send>,
+   |            ^^^^^^^^^^^
+
+error: return type notation is not allowed for functions that have const parameters
+  --> $DIR/ty-or-ct-params.rs:14:25
+   |
+LL |     async fn baz<const N: usize>() {}
+   |                  -------------- const parameter declared here
+...
+LL |     T: Foo<bar(): Send, baz(): Send>,
+   |                         ^^^^^^^^^^^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
index 3bae23a4aaa..7de67da9b5d 100644
--- a/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
+++ b/tests/ui/feature-gates/feature-gate-extern_absolute_paths.stderr
@@ -13,6 +13,15 @@ LL |     let _: u8 = ::core::default::Default();
    |                   ^^^^ maybe a missing crate `core`?
    |
    = help: consider adding `extern crate core` to use the `core` crate
+help: consider importing this module
+   |
+LL + use std::default;
+   |
+help: if you import `default`, refer to it directly
+   |
+LL -     let _: u8 = ::core::default::Default();
+LL +     let _: u8 = default::Default();
+   |
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
index 7e8c1eb95ca..ae12495b5dc 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
@@ -1,10 +1,7 @@
 // edition: 2021
-// revisions: cfg_current cfg_next no_current no_next
-// [cfg_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// [no_next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
+// revisions: cfg no
 
-// [no_current] check-pass
-// [no_next] check-pass
+// [no] check-pass
 // Since we're not adding new syntax, `cfg`'d out RTN must pass.
 
 #![feature(async_fn_in_trait)]
@@ -13,17 +10,12 @@ trait Trait {
     async fn m();
 }
 
-#[cfg(any(cfg_current, cfg_next))]
+#[cfg(cfg)]
 fn foo<T: Trait<m(): Send>>() {}
-//[cfg_current]~^ ERROR return type notation is experimental
-//[cfg_current]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
-//[cfg_current]~| ERROR associated type `m` not found for `Trait`
-//[cfg_next]~^^^^ ERROR return type notation is experimental
-//[cfg_next]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
-//[cfg_next]~| ERROR associated type `m` not found for `Trait`
-//[no_current]~^^^^^^^ WARN return type notation is experimental
-//[no_current]~| WARN unstable syntax can change at any point in the future, causing a hard error!
-//[no_next]~^^^^^^^^^ WARN return type notation is experimental
-//[no_next]~| WARN unstable syntax can change at any point in the future, causing a hard error!
+//[cfg]~^ ERROR return type notation is experimental
+//[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
+//[cfg]~| ERROR associated type `m` not found for `Trait`
+//[no]~^^^^ WARN return type notation is experimental
+//[no]~| WARN unstable syntax can change at any point in the future, causing a hard error!
 
 fn main() {}
diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs
new file mode 100644
index 00000000000..40c5eacee3b
--- /dev/null
+++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.rs
@@ -0,0 +1,29 @@
+// edition:2018
+#![feature(decl_macro)]
+
+macro a() {
+    extern crate core as my_core;
+    mod v {
+        // Early resolution.
+        use my_core; //~ ERROR unresolved import `my_core`
+    }
+    mod u {
+        // Late resolution.
+        fn f() { my_core::mem::drop(0); }
+        //~^ ERROR failed to resolve: use of undeclared crate or module `my_core`
+    }
+}
+
+a!();
+
+mod v {
+    // Early resolution.
+    use my_core; //~ ERROR unresolved import `my_core`
+}
+mod u {
+    // Late resolution.
+    fn f() { my_core::mem::drop(0); }
+    //~^ ERROR failed to resolve: use of undeclared crate or module `my_core`
+}
+
+fn main() {}
diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
new file mode 100644
index 00000000000..7ed15e89caa
--- /dev/null
+++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail-2018.stderr
@@ -0,0 +1,53 @@
+error[E0432]: unresolved import `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail-2018.rs:21:9
+   |
+LL |     use my_core;
+   |         ^^^^^^^ no external crate `my_core`
+
+error[E0432]: unresolved import `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail-2018.rs:8:13
+   |
+LL |         use my_core;
+   |             ^^^^^^^ no external crate `my_core`
+...
+LL | a!();
+   | ---- in this macro invocation
+   |
+   = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail-2018.rs:12:18
+   |
+LL |         fn f() { my_core::mem::drop(0); }
+   |                  ^^^^^^^ use of undeclared crate or module `my_core`
+...
+LL | a!();
+   | ---- in this macro invocation
+   |
+   = help: consider importing one of these items:
+           std::mem
+           core::mem
+   = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
+  --> $DIR/extern-prelude-from-opaque-fail-2018.rs:25:14
+   |
+LL |     fn f() { my_core::mem::drop(0); }
+   |              ^^^^^^^ use of undeclared crate or module `my_core`
+   |
+help: consider importing one of these items
+   |
+LL +     use core::mem;
+   |
+LL +     use std::mem;
+   |
+help: if you import `mem`, refer to it directly
+   |
+LL -     fn f() { my_core::mem::drop(0); }
+LL +     fn f() { mem::drop(0); }
+   |
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0432, E0433.
+For more information about an error, try `rustc --explain E0432`.
diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs
index 571017df4d7..f3fa2dddaef 100644
--- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs
+++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.rs
@@ -1,3 +1,4 @@
+// edition:2015
 #![feature(decl_macro)]
 
 macro a() {
diff --git a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr
index f1f4caee361..13b2827ef39 100644
--- a/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr
+++ b/tests/ui/hygiene/extern-prelude-from-opaque-fail.stderr
@@ -1,11 +1,11 @@
 error[E0432]: unresolved import `my_core`
-  --> $DIR/extern-prelude-from-opaque-fail.rs:20:9
+  --> $DIR/extern-prelude-from-opaque-fail.rs:21:9
    |
 LL |     use my_core;
    |         ^^^^^^^ no `my_core` in the root
 
 error[E0432]: unresolved import `my_core`
-  --> $DIR/extern-prelude-from-opaque-fail.rs:7:13
+  --> $DIR/extern-prelude-from-opaque-fail.rs:8:13
    |
 LL |         use my_core;
    |             ^^^^^^^ no `my_core` in the root
@@ -16,7 +16,7 @@ LL | a!();
    = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
-  --> $DIR/extern-prelude-from-opaque-fail.rs:11:18
+  --> $DIR/extern-prelude-from-opaque-fail.rs:12:18
    |
 LL |         fn f() { my_core::mem::drop(0); }
    |                  ^^^^^^^ use of undeclared crate or module `my_core`
@@ -24,13 +24,25 @@ LL |         fn f() { my_core::mem::drop(0); }
 LL | a!();
    | ---- in this macro invocation
    |
+   = help: consider importing this module:
+           my_core::mem
    = note: this error originates in the macro `a` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0433]: failed to resolve: use of undeclared crate or module `my_core`
-  --> $DIR/extern-prelude-from-opaque-fail.rs:24:14
+  --> $DIR/extern-prelude-from-opaque-fail.rs:25:14
    |
 LL |     fn f() { my_core::mem::drop(0); }
    |              ^^^^^^^ use of undeclared crate or module `my_core`
+   |
+help: consider importing this module
+   |
+LL +     use my_core::mem;
+   |
+help: if you import `mem`, refer to it directly
+   |
+LL -     fn f() { my_core::mem::drop(0); }
+LL +     fn f() { mem::drop(0); }
+   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
index 776006124dc..cfc2193f633 100644
--- a/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
+++ b/tests/ui/impl-trait/in-trait/auxiliary/rpitit.rs
@@ -1,5 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-
 #![feature(return_position_impl_trait_in_trait)]
 
 use std::ops::Deref;
@@ -10,5 +8,7 @@ pub trait Foo {
 
 pub struct Foreign;
 impl Foo for Foreign {
-    fn bar(self) -> &'static () { &() }
+    fn bar(self) -> &'static () {
+        &()
+    }
 }
diff --git a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
index f5290a5f4af..f5ee4690fa9 100644
--- a/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
+++ b/tests/ui/impl-trait/in-trait/box-coerce-span-in-default.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/deep-match-works.rs b/tests/ui/impl-trait/in-trait/deep-match-works.rs
index 5c9d2e356fc..78cff97c616 100644
--- a/tests/ui/impl-trait/in-trait/deep-match-works.rs
+++ b/tests/ui/impl-trait/in-trait/deep-match-works.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/deep-match.rs b/tests/ui/impl-trait/in-trait/deep-match.rs
index 413d054e148..0cae88f349f 100644
--- a/tests/ui/impl-trait/in-trait/deep-match.rs
+++ b/tests/ui/impl-trait/in-trait/deep-match.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/deep-match.stderr b/tests/ui/impl-trait/in-trait/deep-match.stderr
new file mode 100644
index 00000000000..f0ad3c16e9c
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/deep-match.stderr
@@ -0,0 +1,15 @@
+error[E0053]: method `bar` has an incompatible return type for trait
+  --> $DIR/deep-match.rs:11:17
+   |
+LL |     fn bar() -> i32 {
+   |                 ^^^
+   |                 |
+   |                 expected `Wrapper<_>`, found `i32`
+   |                 return type in trait
+   |
+   = note: expected struct `Wrapper<_>`
+                found type `i32`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
index 62323776310..45ae2b8ad3a 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![allow(incomplete_features)]
 #![feature(async_fn_in_trait)]
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
new file mode 100644
index 00000000000..cc3bdf0e571
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err-2.stderr
@@ -0,0 +1,11 @@
+error[E0308]: mismatched types
+  --> $DIR/default-body-type-err-2.rs:8:9
+   |
+LL |         42
+   |         ^^- help: try using a conversion method: `.to_string()`
+   |         |
+   |         expected `String`, found integer
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.rs b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
index 9bd5b777989..ac9baf91cae 100644
--- a/tests/ui/impl-trait/in-trait/default-body-type-err.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![allow(incomplete_features)]
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/default-body-type-err.stderr b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
new file mode 100644
index 00000000000..4742eb37d3e
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-type-err.stderr
@@ -0,0 +1,12 @@
+error[E0271]: type mismatch resolving `<&i32 as Deref>::Target == String`
+  --> $DIR/default-body-type-err.rs:7:22
+   |
+LL |     fn lol(&self) -> impl Deref<Target = String> {
+   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `i32`, found `String`
+LL |
+LL |         &1i32
+   |         ----- return type was inferred to be `&i32` here
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0271`.
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
index 6bcc7b9ef95..0558d95128f 100644
--- a/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.rs
@@ -1,7 +1,5 @@
 // edition:2021
 // known-bug: #108304
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr b/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr
new file mode 100644
index 00000000000..b5fc9d44d36
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/default-body-with-rpit.stderr
@@ -0,0 +1,24 @@
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/default-body-with-rpit.rs:11:9
+   |
+LL |         ""
+   |         ^^ expected `impl Debug`, got `&'static str`
+   |
+note: previous use here
+  --> $DIR/default-body-with-rpit.rs:10:39
+   |
+LL |       async fn baz(&self) -> impl Debug {
+   |  _______________________________________^
+LL | |         ""
+LL | |     }
+   | |_____^
+
+error[E0720]: cannot resolve opaque type
+  --> $DIR/default-body-with-rpit.rs:10:28
+   |
+LL |     async fn baz(&self) -> impl Debug {
+   |                            ^^^^^^^^^^ cannot resolve opaque type
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0720`.
diff --git a/tests/ui/impl-trait/in-trait/default-body.rs b/tests/ui/impl-trait/in-trait/default-body.rs
index ab6a51c6bcb..b0baf5bb10d 100644
--- a/tests/ui/impl-trait/in-trait/default-body.rs
+++ b/tests/ui/impl-trait/in-trait/default-body.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs
index 187039f449c..817a4d7dbbe 100644
--- a/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs
+++ b/tests/ui/impl-trait/in-trait/default-method-binder-shifting.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/default-method-constraint.rs b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
index 4f0bf2e7dfe..28d76241f27 100644
--- a/tests/ui/impl-trait/in-trait/default-method-constraint.rs
+++ b/tests/ui/impl-trait/in-trait/default-method-constraint.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 // This didn't work in the previous default RPITIT method hack attempt
 
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
index fcd0b51eea4..bb4e0d44f3e 100644
--- a/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
new file mode 100644
index 00000000000..7c56ffa10e1
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/doesnt-satisfy.stderr
@@ -0,0 +1,17 @@
+error[E0277]: `()` doesn't implement `std::fmt::Display`
+  --> $DIR/doesnt-satisfy.rs:9:17
+   |
+LL |     fn bar() -> () {}
+   |                 ^^ `()` cannot be formatted with the default formatter
+   |
+   = help: the trait `std::fmt::Display` is not implemented for `()`
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `Foo::{opaque#0}`
+  --> $DIR/doesnt-satisfy.rs:5:22
+   |
+LL |     fn bar() -> impl std::fmt::Display;
+   |                      ^^^^^^^^^^^^^^^^^ required by this bound in `Foo::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs
index 4d50b8c9278..4719d5d3c67 100644
--- a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs
+++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 
 trait MyTrait {
diff --git a/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr
new file mode 100644
index 00000000000..66ee142ccc4
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/dont-project-to-rpitit-with-no-value.stderr
@@ -0,0 +1,12 @@
+error[E0046]: not all trait items implemented, missing: `foo`
+  --> $DIR/dont-project-to-rpitit-with-no-value.rs:8:1
+   |
+LL |     fn foo(&self) -> impl Sized;
+   |     ---------------------------- `foo` from trait
+...
+LL | impl MyTrait for i32 {
+   | ^^^^^^^^^^^^^^^^^^^^ missing `foo` in implementation
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0046`.
diff --git a/tests/ui/impl-trait/in-trait/early.rs b/tests/ui/impl-trait/in-trait/early.rs
index 831033a5880..9c1c2b50339 100644
--- a/tests/ui/impl-trait/in-trait/early.rs
+++ b/tests/ui/impl-trait/in-trait/early.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(async_fn_in_trait, return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/encode.rs b/tests/ui/impl-trait/in-trait/encode.rs
index 98aaf4a6553..efb9f6498ba 100644
--- a/tests/ui/impl-trait/in-trait/encode.rs
+++ b/tests/ui/impl-trait/in-trait/encode.rs
@@ -1,7 +1,5 @@
 // build-pass
 // compile-flags: --crate-type=lib
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
index 6eef392c05f..bfb2be8cbc1 100644
--- a/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
+++ b/tests/ui/impl-trait/in-trait/foreign-dyn-error.stderr
@@ -5,7 +5,7 @@ LL |     let _: &dyn rpitit::Foo = todo!();
    |            ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
    |
 note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
-  --> $DIR/auxiliary/rpitit.rs:8:21
+  --> $DIR/auxiliary/rpitit.rs:6:21
    |
 LL |     fn bar(self) -> impl Deref<Target = impl Sized>;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait cannot be made into an object because method `bar` references an `impl Trait` type in its return type
diff --git a/tests/ui/impl-trait/in-trait/foreign.rs b/tests/ui/impl-trait/in-trait/foreign.rs
index b0fbe3a3d4a..b0c93a02935 100644
--- a/tests/ui/impl-trait/in-trait/foreign.rs
+++ b/tests/ui/impl-trait/in-trait/foreign.rs
@@ -1,7 +1,5 @@
 // check-pass
 // aux-build: rpitit.rs
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 extern crate rpitit;
 
@@ -11,7 +9,9 @@ use std::sync::Arc;
 // Implement an RPITIT from another crate.
 struct Local;
 impl Foo for Local {
-    fn bar(self) -> Arc<String> { Arc::new(String::new()) }
+    fn bar(self) -> Arc<String> {
+        Arc::new(String::new())
+    }
 }
 
 fn generic(f: impl Foo) {
diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.rs b/tests/ui/impl-trait/in-trait/generics-mismatch.rs
index 9259ca193d1..cc0fc720ebb 100644
--- a/tests/ui/impl-trait/in-trait/generics-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/generics-mismatch.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/generics-mismatch.stderr b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr
new file mode 100644
index 00000000000..cd42683e022
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/generics-mismatch.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `bar` has 1 type parameter but its trait declaration has 0 type parameters
+  --> $DIR/generics-mismatch.rs:11:12
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |           - expected 0 type parameters
+...
+LL |     fn bar<T>(&self) {}
+   |            ^ found 1 type parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/impl-trait/in-trait/issue-102140.rs b/tests/ui/impl-trait/in-trait/issue-102140.rs
index 4dcac4f5b0e..be1e012acb1 100644
--- a/tests/ui/impl-trait/in-trait/issue-102140.rs
+++ b/tests/ui/impl-trait/in-trait/issue-102140.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/issue-102140.stderr b/tests/ui/impl-trait/in-trait/issue-102140.stderr
new file mode 100644
index 00000000000..5d55b9fa4f9
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/issue-102140.stderr
@@ -0,0 +1,29 @@
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+  --> $DIR/issue-102140.rs:23:22
+   |
+LL |         MyTrait::foo(&self)
+   |         ------------ ^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+   |         |
+   |         required by a bound introduced by this call
+   |
+   = help: the trait `MyTrait` is implemented for `Outer`
+
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+  --> $DIR/issue-102140.rs:23:9
+   |
+LL |         MyTrait::foo(&self)
+   |         ^^^^^^^^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+   |
+   = help: the trait `MyTrait` is implemented for `Outer`
+
+error[E0277]: the trait bound `&dyn MyTrait: MyTrait` is not satisfied
+  --> $DIR/issue-102140.rs:23:9
+   |
+LL |         MyTrait::foo(&self)
+   |         ^^^^^^^^^^^^ the trait `MyTrait` is not implemented for `&dyn MyTrait`
+   |
+   = help: the trait `MyTrait` is implemented for `Outer`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/issue-102301.rs b/tests/ui/impl-trait/in-trait/issue-102301.rs
index 1329ca29d06..a93714a658e 100644
--- a/tests/ui/impl-trait/in-trait/issue-102301.rs
+++ b/tests/ui/impl-trait/in-trait/issue-102301.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.rs b/tests/ui/impl-trait/in-trait/issue-102571.rs
index f0ddab5e7f2..61c91e64417 100644
--- a/tests/ui/impl-trait/in-trait/issue-102571.rs
+++ b/tests/ui/impl-trait/in-trait/issue-102571.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/issue-102571.stderr b/tests/ui/impl-trait/in-trait/issue-102571.stderr
new file mode 100644
index 00000000000..87219941d91
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/issue-102571.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-102571.rs:20:9
+   |
+LL |     let () = t.bar();
+   |         ^^   ------- this expression has type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+   |         |
+   |         expected associated type, found `()`
+   |
+   = note: expected associated type `impl Deref<Target = impl std::fmt::Display + ?Sized>`
+                    found unit type `()`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/nested-rpitit.rs b/tests/ui/impl-trait/in-trait/nested-rpitit.rs
index 36020753726..65285e3a3cc 100644
--- a/tests/ui/impl-trait/in-trait/nested-rpitit.rs
+++ b/tests/ui/impl-trait/in-trait/nested-rpitit.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/object-safety.rs b/tests/ui/impl-trait/in-trait/object-safety.rs
index 016a0aaae4b..dd35b9a2d8a 100644
--- a/tests/ui/impl-trait/in-trait/object-safety.rs
+++ b/tests/ui/impl-trait/in-trait/object-safety.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/object-safety.stderr b/tests/ui/impl-trait/in-trait/object-safety.stderr
new file mode 100644
index 00000000000..4a3b3b11465
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/object-safety.stderr
@@ -0,0 +1,49 @@
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:17:33
+   |
+LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
+   |                                 ^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:7:22
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> impl Debug;
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
+   = help: consider moving `baz` to another trait
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:20:13
+   |
+LL |     let s = i.baz();
+   |             ^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:7:22
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> impl Debug;
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
+   = help: consider moving `baz` to another trait
+
+error[E0038]: the trait `Foo` cannot be made into an object
+  --> $DIR/object-safety.rs:17:13
+   |
+LL |     let i = Box::new(42_u32) as Box<dyn Foo>;
+   |             ^^^^^^^^^^^^^^^^ `Foo` cannot be made into an object
+   |
+note: for a trait to be "object safe" it needs to allow building a vtable to allow the call to be resolvable dynamically; for more information visit <https://doc.rust-lang.org/reference/items/traits.html#object-safety>
+  --> $DIR/object-safety.rs:7:22
+   |
+LL | trait Foo {
+   |       --- this trait cannot be made into an object...
+LL |     fn baz(&self) -> impl Debug;
+   |                      ^^^^^^^^^^ ...because method `baz` references an `impl Trait` type in its return type
+   = help: consider moving `baz` to another trait
+   = note: required for the cast from `Box<u32>` to `Box<dyn Foo>`
+
+error: aborting due to 3 previous errors
+
+For more information about this error, try `rustc --explain E0038`.
diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs
index c07ece15a83..3ac264e8eba 100644
--- a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs
+++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr
new file mode 100644
index 00000000000..15edda48340
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/opaque-in-impl-is-opaque.stderr
@@ -0,0 +1,17 @@
+error[E0308]: mismatched types
+  --> $DIR/opaque-in-impl-is-opaque.rs:17:19
+   |
+LL |     fn bar(&self) -> impl Display {
+   |                      ------------ the found opaque type
+...
+LL |     let x: &str = ().bar();
+   |            ----   ^^^^^^^^ expected `&str`, found opaque type
+   |            |
+   |            expected due to this
+   |
+   = note: expected reference `&str`
+            found opaque type `impl std::fmt::Display`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs
index f48d9fa26c0..2e06629699a 100644
--- a/tests/ui/impl-trait/in-trait/opaque-in-impl.rs
+++ b/tests/ui/impl-trait/in-trait/opaque-in-impl.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
index 65528f212e2..5d9a224ccd6 100644
--- a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 
 trait Foo<T> {
diff --git a/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
new file mode 100644
index 00000000000..668fc6cbe7f
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/return-dont-satisfy-bounds.stderr
@@ -0,0 +1,16 @@
+error[E0277]: the trait bound `impl Foo<u8>: Foo<char>` is not satisfied
+  --> $DIR/return-dont-satisfy-bounds.rs:10:34
+   |
+LL |     fn foo<F2: Foo<u8>>(self) -> impl Foo<u8> {
+   |                                  ^^^^^^^^^^^^ the trait `Foo<char>` is not implemented for `impl Foo<u8>`
+   |
+   = help: the trait `Foo<char>` is implemented for `Bar`
+note: required by a bound in `Foo::{opaque#0}`
+  --> $DIR/return-dont-satisfy-bounds.rs:4:30
+   |
+LL |     fn foo<F2>(self) -> impl Foo<T>;
+   |                              ^^^^^^ required by this bound in `Foo::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/reveal.rs b/tests/ui/impl-trait/in-trait/reveal.rs
index 1f42ec744db..d6ede1cc495 100644
--- a/tests/ui/impl-trait/in-trait/reveal.rs
+++ b/tests/ui/impl-trait/in-trait/reveal.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.rs b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
index 23dd71acecb..1d63a6f3ce2 100644
--- a/tests/ui/impl-trait/in-trait/signature-mismatch.rs
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.rs
@@ -1,6 +1,4 @@
 // edition:2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/signature-mismatch.stderr b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr
new file mode 100644
index 00000000000..616f1ac35a9
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/signature-mismatch.stderr
@@ -0,0 +1,61 @@
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:34:47
+   |
+LL |     fn async_fn<'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                 -- this lifetime was captured ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:15:40
+   |
+LL |     fn async_fn(&self, buff: &[u8]) -> impl Future<Output = Vec<u8>>;
+   |                                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:39:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>> + 'a {
+   |                       -- this lifetime was captured     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:16:57
+   |
+LL |     fn async_fn_early<'a: 'a>(&self, buff: &'a [u8]) -> impl Future<Output = Vec<u8>>;
+   |                                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + 'a`
+
+error: return type captures more lifetimes than trait definition
+  --> $DIR/signature-mismatch.rs:47:10
+   |
+LL |     fn async_fn_multiple<'a, 'b>(
+   |                              -- this lifetime was captured
+...
+LL |     ) -> impl Future<Output = Vec<u8>> + Captures2<'a, 'b> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+note: hidden type must only reference lifetimes captured by this impl trait
+  --> $DIR/signature-mismatch.rs:18:12
+   |
+LL |         -> impl Future<Output = Vec<u8>> + Captures<'a>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   = note: hidden type inferred to be `impl Future<Output = Vec<u8>> + Captures2<'a, 'b>`
+
+error[E0309]: the parameter type `T` may not live long enough
+  --> $DIR/signature-mismatch.rs:56:10
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> {
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ ...so that the type `impl Future<Output = Vec<u8>>` will meet its required lifetime bounds...
+   |
+note: ...that is required by this bound
+  --> $DIR/signature-mismatch.rs:23:42
+   |
+LL |     ) -> impl Future<Output = Vec<u8>> + 'a;
+   |                                          ^^
+help: consider adding an explicit lifetime bound...
+   |
+LL |     fn async_fn_reduce_outlive<'a, 'b, T: 'a>(
+   |                                         ++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0309`.
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.rs b/tests/ui/impl-trait/in-trait/specialization-broken.rs
index 658d0709717..2fcffdf3f9a 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 // FIXME(compiler-errors): I'm not exactly sure if this is expected to pass or not.
 // But we fixed an ICE anyways.
 
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
new file mode 100644
index 00000000000..dc621d6b8a8
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -0,0 +1,31 @@
+error[E0053]: method `bar` has an incompatible type for trait
+  --> $DIR/specialization-broken.rs:16:22
+   |
+LL | default impl<U> Foo for U
+   |              - this type parameter
+...
+LL |     fn bar(&self) -> U {
+   |                      ^
+   |                      |
+   |                      expected associated type, found type parameter `U`
+   |                      help: change the output type to match the trait: `impl Sized`
+   |
+note: type in trait
+  --> $DIR/specialization-broken.rs:9:22
+   |
+LL |     fn bar(&self) -> impl Sized;
+   |                      ^^^^^^^^^^
+   = note: expected signature `fn(&U) -> impl Sized`
+              found signature `fn(&U) -> U`
+
+error: method with return-position `impl Trait` in trait cannot be specialized
+  --> $DIR/specialization-broken.rs:16:5
+   |
+LL |     fn bar(&self) -> U {
+   |     ^^^^^^^^^^^^^^^^^^
+   |
+   = note: specialization behaves in inconsistent and surprising ways with `#![feature(return_position_impl_trait_in_trait)]`, and for now is disallowed
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0053`.
diff --git a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs
index dbc5d38f192..c9ee877db8e 100644
--- a/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs
+++ b/tests/ui/impl-trait/in-trait/specialization-substs-remap.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(specialization)]
 #![feature(return_position_impl_trait_in_trait)]
diff --git a/tests/ui/impl-trait/in-trait/success.rs b/tests/ui/impl-trait/in-trait/success.rs
index 0e69e0490c7..4cbe682b46f 100644
--- a/tests/ui/impl-trait/in-trait/success.rs
+++ b/tests/ui/impl-trait/in-trait/success.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
index c2e394a1f66..0bbe50ea6fd 100644
--- a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
+++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
new file mode 100644
index 00000000000..8ff54cad951
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/trait-more-generics-than-impl.stderr
@@ -0,0 +1,12 @@
+error[E0049]: method `bar` has 0 type parameters but its trait declaration has 1 type parameter
+  --> $DIR/trait-more-generics-than-impl.rs:11:11
+   |
+LL |     fn bar<T>() -> impl Sized;
+   |            - expected 1 type parameter
+...
+LL |     fn bar() -> impl Sized {}
+   |           ^ found 0 type parameters
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.rs b/tests/ui/impl-trait/in-trait/unconstrained-lt.rs
index f966be43a6e..07c8606f9fe 100644
--- a/tests/ui/impl-trait/in-trait/unconstrained-lt.rs
+++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 
 trait Foo {
@@ -10,7 +7,9 @@ trait Foo {
 impl<'a, T> Foo for T {
     //~^ ERROR the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
 
-    fn test() -> &'a () { &() }
+    fn test() -> &'a () {
+        &()
+    }
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr
new file mode 100644
index 00000000000..cfce3556720
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/unconstrained-lt.stderr
@@ -0,0 +1,9 @@
+error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
+  --> $DIR/unconstrained-lt.rs:7:6
+   |
+LL | impl<'a, T> Foo for T {
+   |      ^^ unconstrained lifetime parameter
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0207`.
diff --git a/tests/ui/impl-trait/in-trait/variances-of-gat.rs b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
index 4008ece94da..0d19e1ff416 100644
--- a/tests/ui/impl-trait/in-trait/variances-of-gat.rs
+++ b/tests/ui/impl-trait/in-trait/variances-of-gat.rs
@@ -1,6 +1,4 @@
 // check-pass
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.rs b/tests/ui/impl-trait/in-trait/wf-bounds.rs
index f8c1e561d5c..ee873f94b26 100644
--- a/tests/ui/impl-trait/in-trait/wf-bounds.rs
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.rs
@@ -1,6 +1,4 @@
 // issue #101663
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/impl-trait/in-trait/wf-bounds.stderr b/tests/ui/impl-trait/in-trait/wf-bounds.stderr
new file mode 100644
index 00000000000..beac6620911
--- /dev/null
+++ b/tests/ui/impl-trait/in-trait/wf-bounds.stderr
@@ -0,0 +1,57 @@
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:15:22
+   |
+LL |     fn nya() -> impl Wf<Vec<[u8]>>;
+   |                      ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:18:23
+   |
+LL |     fn nya2() -> impl Wf<[u8]>;
+   |                       ^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Wf`
+  --> $DIR/wf-bounds.rs:8:10
+   |
+LL | trait Wf<T> {
+   |          ^ required by this bound in `Wf`
+help: consider relaxing the implicit `Sized` restriction
+   |
+LL | trait Wf<T: ?Sized> {
+   |           ++++++++
+
+error[E0277]: the size for values of type `[u8]` cannot be known at compilation time
+  --> $DIR/wf-bounds.rs:21:44
+   |
+LL |     fn nya3() -> impl Wf<(), Output = impl Wf<Vec<[u8]>>>;
+   |                                            ^^^^^^^^^^^^^ doesn't have a size known at compile-time
+   |
+   = help: the trait `Sized` is not implemented for `[u8]`
+note: required by a bound in `Vec`
+  --> $SRC_DIR/alloc/src/vec/mod.rs:LL:COL
+
+error[E0277]: `T` doesn't implement `std::fmt::Display`
+  --> $DIR/wf-bounds.rs:24:26
+   |
+LL |     fn nya4<T>() -> impl Wf<NeedsDisplay<T>>;
+   |                          ^^^^^^^^^^^^^^^^^^^ `T` cannot be formatted with the default formatter
+   |
+   = note: in format strings you may be able to use `{:?}` (or {:#?} for pretty-print) instead
+note: required by a bound in `NeedsDisplay`
+  --> $DIR/wf-bounds.rs:12:24
+   |
+LL | struct NeedsDisplay<T: Display>(T);
+   |                        ^^^^^^^ required by this bound in `NeedsDisplay`
+help: consider restricting type parameter `T`
+   |
+LL |     fn nya4<T: std::fmt::Display>() -> impl Wf<NeedsDisplay<T>>;
+   |              +++++++++++++++++++
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/impl-trait/in-trait/where-clause.rs b/tests/ui/impl-trait/in-trait/where-clause.rs
index 88d86e2b541..87bac519cf3 100644
--- a/tests/ui/impl-trait/in-trait/where-clause.rs
+++ b/tests/ui/impl-trait/in-trait/where-clause.rs
@@ -1,7 +1,5 @@
 // check-pass
 // edition: 2021
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
 
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
diff --git a/tests/ui/inference/issue-113354.fixed b/tests/ui/inference/issue-113354.fixed
new file mode 100644
index 00000000000..804db985ae1
--- /dev/null
+++ b/tests/ui/inference/issue-113354.fixed
@@ -0,0 +1,4 @@
+//run-rustfix
+fn main() {
+    let _ = || { while let Some(_) = Some(1) { } }; //~ ERROR mismatched types
+}
diff --git a/tests/ui/inference/issue-113354.rs b/tests/ui/inference/issue-113354.rs
new file mode 100644
index 00000000000..ec33d1f8b84
--- /dev/null
+++ b/tests/ui/inference/issue-113354.rs
@@ -0,0 +1,4 @@
+//run-rustfix
+fn main() {
+    let _ = || { while Some(_) = Some(1) { } }; //~ ERROR mismatched types
+}
diff --git a/tests/ui/inference/issue-113354.stderr b/tests/ui/inference/issue-113354.stderr
new file mode 100644
index 00000000000..045a5aa7bf0
--- /dev/null
+++ b/tests/ui/inference/issue-113354.stderr
@@ -0,0 +1,14 @@
+error[E0308]: mismatched types
+  --> $DIR/issue-113354.rs:3:24
+   |
+LL |     let _ = || { while Some(_) = Some(1) { } };
+   |                        ^^^^^^^^^^^^^^^^^ expected `bool`, found `()`
+   |
+help: consider adding `let`
+   |
+LL |     let _ = || { while let Some(_) = Some(1) { } };
+   |                        +++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs
new file mode 100644
index 00000000000..5a893f2d8ad
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.rs
@@ -0,0 +1,12 @@
+trait T {}
+
+struct S {}
+
+impl S {
+    fn owo(&self, _: Option<&impl T>) {}
+}
+
+fn main() {
+    (S {}).owo(None)
+    //~^ ERROR type annotations needed
+}
diff --git a/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr
new file mode 100644
index 00000000000..0ec219415ab
--- /dev/null
+++ b/tests/ui/inference/need_type_info/issue-113264-incorrect-impl-trait-in-path-suggestion.stderr
@@ -0,0 +1,14 @@
+error[E0282]: type annotations needed
+  --> $DIR/issue-113264-incorrect-impl-trait-in-path-suggestion.rs:10:16
+   |
+LL |     (S {}).owo(None)
+   |                ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
+   |
+help: consider specifying the generic argument
+   |
+LL |     (S {}).owo(None::<&_>)
+   |                    ++++++
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0282`.
diff --git a/tests/ui/lint/fn_null_check.rs b/tests/ui/lint/fn_null_check.rs
new file mode 100644
index 00000000000..7f01f2c4283
--- /dev/null
+++ b/tests/ui/lint/fn_null_check.rs
@@ -0,0 +1,30 @@
+// check-pass
+
+fn main() {
+    let fn_ptr = main;
+
+    if (fn_ptr as *mut ()).is_null() {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as *const u8).is_null() {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as *const ()) == std::ptr::null() {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as *const ()) == (0 as *const ()) {}
+    //~^ WARN function pointers are not nullable
+    if <*const _>::is_null(fn_ptr as *const ()) {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
+    //~^ WARN function pointers are not nullable
+    if (fn_ptr as fn() as *const ()).is_null() {}
+    //~^ WARN function pointers are not nullable
+
+    const ZPTR: *const () = 0 as *const _;
+    const NOT_ZPTR: *const () = 1 as *const _;
+
+    // unlike the uplifted clippy::fn_null_check lint we do
+    // not lint on them
+    if (fn_ptr as *const ()) == ZPTR {}
+    if (fn_ptr as *const ()) == NOT_ZPTR {}
+}
diff --git a/tests/ui/lint/fn_null_check.stderr b/tests/ui/lint/fn_null_check.stderr
new file mode 100644
index 00000000000..0398c0da50f
--- /dev/null
+++ b/tests/ui/lint/fn_null_check.stderr
@@ -0,0 +1,67 @@
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:6:8
+   |
+LL |     if (fn_ptr as *mut ()).is_null() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+   = note: `#[warn(incorrect_fn_null_checks)]` on by default
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:8:8
+   |
+LL |     if (fn_ptr as *const u8).is_null() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:10:8
+   |
+LL |     if (fn_ptr as *const ()) == std::ptr::null() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:12:8
+   |
+LL |     if (fn_ptr as *mut ()) == std::ptr::null_mut() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:14:8
+   |
+LL |     if (fn_ptr as *const ()) == (0 as *const ()) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:16:8
+   |
+LL |     if <*const _>::is_null(fn_ptr as *const ()) {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:18:8
+   |
+LL |     if (fn_ptr as *mut fn() as *const fn() as *const ()).is_null() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: function pointers are not nullable, so checking them for null will always return false
+  --> $DIR/fn_null_check.rs:20:8
+   |
+LL |     if (fn_ptr as fn() as *const ()).is_null() {}
+   |        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = help: wrap the function pointer inside an `Option` and use `Option::is_none` to check for null pointer value
+
+warning: 8 warnings emitted
+
diff --git a/tests/ui/macros/builtin-prelude-no-accidents.stderr b/tests/ui/macros/builtin-prelude-no-accidents.stderr
index b726e186241..c1054230bc9 100644
--- a/tests/ui/macros/builtin-prelude-no-accidents.stderr
+++ b/tests/ui/macros/builtin-prelude-no-accidents.stderr
@@ -26,10 +26,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `vec`
 LL |     type B = vec::Vec<u8>;
    |              ^^^ use of undeclared crate or module `vec`
    |
-help: a struct with a similar name exists
-   |
-LL |     type B = Vec::Vec<u8>;
-   |              ~~~
 help: consider importing this module
    |
 LL + use std::vec;
diff --git a/tests/ui/panics/abort-on-panic.rs b/tests/ui/panics/abort-on-panic.rs
index 1f6ad64c071..7fbee85ffd1 100644
--- a/tests/ui/panics/abort-on-panic.rs
+++ b/tests/ui/panics/abort-on-panic.rs
@@ -1,4 +1,6 @@
 // run-pass
+// revisions: current next
+//[next] compile-flags: -Ztrait-solver=next
 
 #![allow(unused_must_use)]
 #![feature(c_unwind)]
diff --git a/tests/ui/resolve/112590-2.fixed b/tests/ui/resolve/112590-2.fixed
new file mode 100644
index 00000000000..3bfe81ae8d0
--- /dev/null
+++ b/tests/ui/resolve/112590-2.fixed
@@ -0,0 +1,34 @@
+// run-rustfix
+use std::vec;
+
+use std::sync::atomic::AtomicBool;
+
+mod foo {
+    pub mod bar {
+        pub mod baz {
+            pub use std::vec::Vec as MyVec;
+        }
+    }
+}
+
+mod u {
+    use foo::bar::baz::MyVec;
+
+fn _a() {
+        let _: Vec<i32> = MyVec::new(); //~ ERROR failed to resolve
+    }
+}
+
+mod v {
+    use foo::bar::baz::MyVec;
+
+fn _b() {
+        let _: Vec<i32> = MyVec::new(); //~ ERROR failed to resolve
+    }
+}
+
+fn main() {
+    let _t: Vec<i32> = Vec::new(); //~ ERROR failed to resolve
+    type _B = vec::Vec::<u8>; //~ ERROR failed to resolve
+    let _t = AtomicBool::new(true); //~ ERROR failed to resolve
+}
diff --git a/tests/ui/resolve/112590-2.rs b/tests/ui/resolve/112590-2.rs
new file mode 100644
index 00000000000..e5914cd676e
--- /dev/null
+++ b/tests/ui/resolve/112590-2.rs
@@ -0,0 +1,26 @@
+// run-rustfix
+mod foo {
+    pub mod bar {
+        pub mod baz {
+            pub use std::vec::Vec as MyVec;
+        }
+    }
+}
+
+mod u {
+    fn _a() {
+        let _: Vec<i32> = super::foo::baf::baz::MyVec::new(); //~ ERROR failed to resolve
+    }
+}
+
+mod v {
+    fn _b() {
+        let _: Vec<i32> = fox::bar::baz::MyVec::new(); //~ ERROR failed to resolve
+    }
+}
+
+fn main() {
+    let _t: Vec<i32> = vec::new(); //~ ERROR failed to resolve
+    type _B = vec::Vec::<u8>; //~ ERROR failed to resolve
+    let _t = std::sync_error::atomic::AtomicBool::new(true); //~ ERROR failed to resolve
+}
diff --git a/tests/ui/resolve/112590-2.stderr b/tests/ui/resolve/112590-2.stderr
new file mode 100644
index 00000000000..0db20249d27
--- /dev/null
+++ b/tests/ui/resolve/112590-2.stderr
@@ -0,0 +1,71 @@
+error[E0433]: failed to resolve: could not find `baf` in `foo`
+  --> $DIR/112590-2.rs:12:39
+   |
+LL |         let _: Vec<i32> = super::foo::baf::baz::MyVec::new();
+   |                                       ^^^ could not find `baf` in `foo`
+   |
+help: consider importing this struct through its public re-export
+   |
+LL +     use foo::bar::baz::MyVec;
+   |
+help: if you import `MyVec`, refer to it directly
+   |
+LL -         let _: Vec<i32> = super::foo::baf::baz::MyVec::new();
+LL +         let _: Vec<i32> = MyVec::new();
+   |
+
+error[E0433]: failed to resolve: use of undeclared crate or module `fox`
+  --> $DIR/112590-2.rs:18:27
+   |
+LL |         let _: Vec<i32> = fox::bar::baz::MyVec::new();
+   |                           ^^^ use of undeclared crate or module `fox`
+   |
+help: consider importing this struct through its public re-export
+   |
+LL +     use foo::bar::baz::MyVec;
+   |
+help: if you import `MyVec`, refer to it directly
+   |
+LL -         let _: Vec<i32> = fox::bar::baz::MyVec::new();
+LL +         let _: Vec<i32> = MyVec::new();
+   |
+
+error[E0433]: failed to resolve: use of undeclared crate or module `vec`
+  --> $DIR/112590-2.rs:24:15
+   |
+LL |     type _B = vec::Vec::<u8>;
+   |               ^^^ use of undeclared crate or module `vec`
+   |
+help: consider importing this module
+   |
+LL + use std::vec;
+   |
+
+error[E0433]: failed to resolve: could not find `sync_error` in `std`
+  --> $DIR/112590-2.rs:25:19
+   |
+LL |     let _t = std::sync_error::atomic::AtomicBool::new(true);
+   |                   ^^^^^^^^^^ could not find `sync_error` in `std`
+   |
+help: consider importing this struct
+   |
+LL + use std::sync::atomic::AtomicBool;
+   |
+help: if you import `AtomicBool`, refer to it directly
+   |
+LL -     let _t = std::sync_error::atomic::AtomicBool::new(true);
+LL +     let _t = AtomicBool::new(true);
+   |
+
+error[E0433]: failed to resolve: use of undeclared crate or module `vec`
+  --> $DIR/112590-2.rs:23:24
+   |
+LL |     let _t: Vec<i32> = vec::new();
+   |                        ^^^
+   |                        |
+   |                        use of undeclared crate or module `vec`
+   |                        help: a struct with a similar name exists (notice the capitalization): `Vec`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0433`.
diff --git a/tests/ui/resolve/export-fully-qualified-2018.stderr b/tests/ui/resolve/export-fully-qualified-2018.stderr
index 366ffd9bb2b..b724da930df 100644
--- a/tests/ui/resolve/export-fully-qualified-2018.stderr
+++ b/tests/ui/resolve/export-fully-qualified-2018.stderr
@@ -3,11 +3,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo`
    |
 LL |     pub fn bar() { foo::baz(); }
    |                    ^^^ use of undeclared crate or module `foo`
-   |
-help: consider importing this module
-   |
-LL +     use crate::foo;
-   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/resolve/export-fully-qualified.stderr b/tests/ui/resolve/export-fully-qualified.stderr
index 0cd516ee1b1..a8af0c7c9b8 100644
--- a/tests/ui/resolve/export-fully-qualified.stderr
+++ b/tests/ui/resolve/export-fully-qualified.stderr
@@ -3,11 +3,6 @@ error[E0433]: failed to resolve: use of undeclared crate or module `foo`
    |
 LL |     pub fn bar() { foo::baz(); }
    |                    ^^^ use of undeclared crate or module `foo`
-   |
-help: consider importing this module
-   |
-LL +     use foo;
-   |
 
 error: aborting due to previous error
 
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
index ca5fa6df2a6..77227ebd834 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.rs
@@ -1,6 +1,3 @@
-// [next] compile-flags: -Zlower-impl-trait-in-trait-to-assoc-ty
-// revisions: current next
-
 #![feature(return_position_impl_trait_in_trait)]
 #![allow(incomplete_features)]
 
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
new file mode 100644
index 00000000000..c4371a0024c
--- /dev/null
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/issue-103052-2.stderr
@@ -0,0 +1,15 @@
+error[E0277]: the trait bound `Something: Termination` is not satisfied
+  --> $DIR/issue-103052-2.rs:12:22
+   |
+LL |         fn main() -> Something {
+   |                      ^^^^^^^^^ the trait `Termination` is not implemented for `Something`
+   |
+note: required by a bound in `Main::{opaque#0}`
+  --> $DIR/issue-103052-2.rs:6:27
+   |
+LL |         fn main() -> impl std::process::Termination;
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Main::{opaque#0}`
+
+error: aborting due to previous error
+
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/sanitize/address.rs b/tests/ui/sanitize/address.rs
index 5b2cea87560..1faab1fd2fc 100644
--- a/tests/ui/sanitize/address.rs
+++ b/tests/ui/sanitize/address.rs
@@ -1,11 +1,12 @@
 // needs-sanitizer-support
 // needs-sanitizer-address
+// ignore-cross-compile
 //
 // compile-flags: -Z sanitizer=address -O -g
 //
 // run-fail
 // error-pattern: AddressSanitizer: stack-buffer-overflow
-// error-pattern: 'xs' (line 13) <== Memory access at offset
+// error-pattern: 'xs' (line 14) <== Memory access at offset
 
 use std::hint::black_box;
 
diff --git a/tests/ui/sanitize/badfree.rs b/tests/ui/sanitize/badfree.rs
index 095a6f4697b..c8d1ce7dff2 100644
--- a/tests/ui/sanitize/badfree.rs
+++ b/tests/ui/sanitize/badfree.rs
@@ -1,5 +1,6 @@
 // needs-sanitizer-support
 // needs-sanitizer-address
+// ignore-cross-compile
 //
 // compile-flags: -Z sanitizer=address -O
 //
diff --git a/tests/ui/sanitize/issue-72154-lifetime-markers.rs b/tests/ui/sanitize/issue-72154-lifetime-markers.rs
index b2e182238ce..3d9c51daa65 100644
--- a/tests/ui/sanitize/issue-72154-lifetime-markers.rs
+++ b/tests/ui/sanitize/issue-72154-lifetime-markers.rs
@@ -5,6 +5,7 @@
 //
 // needs-sanitizer-support
 // needs-sanitizer-address
+// ignore-cross-compile
 //
 // compile-flags: -Copt-level=0 -Zsanitizer=address
 // run-pass
diff --git a/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
index 33e18e35522..052a40598a8 100644
--- a/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
+++ b/tests/ui/sanitize/new-llvm-pass-manager-thin-lto.rs
@@ -4,6 +4,7 @@
 //
 // needs-sanitizer-support
 // needs-sanitizer-address
+// ignore-cross-compile
 //
 // no-prefer-dynamic
 // revisions: opt0 opt1
diff --git a/tests/ui/sanitize/use-after-scope.rs b/tests/ui/sanitize/use-after-scope.rs
index 30be2ae6f09..de63eea194b 100644
--- a/tests/ui/sanitize/use-after-scope.rs
+++ b/tests/ui/sanitize/use-after-scope.rs
@@ -1,5 +1,6 @@
 // needs-sanitizer-support
 // needs-sanitizer-address
+// ignore-cross-compile
 //
 // compile-flags: -Zsanitizer=address
 // run-fail
diff --git a/tests/ui/suggestions/crate-or-module-typo.stderr b/tests/ui/suggestions/crate-or-module-typo.stderr
index 5e7a7685ab0..9ece31e76f0 100644
--- a/tests/ui/suggestions/crate-or-module-typo.stderr
+++ b/tests/ui/suggestions/crate-or-module-typo.stderr
@@ -30,17 +30,23 @@ help: there is a crate or module with a similar name
    |
 LL |     bar: std::cell::Cell<bool>
    |          ~~~
+help: consider importing one of these items
+   |
+LL + use core::cell;
+   |
+LL + use std::cell;
+   |
+help: if you import `cell`, refer to it directly
+   |
+LL -     bar: st::cell::Cell<bool>
+LL +     bar: cell::Cell<bool>
+   |
 
 error[E0433]: failed to resolve: use of undeclared crate or module `bar`
   --> $DIR/crate-or-module-typo.rs:6:20
    |
 LL |     pub fn bar() { bar::baz(); }
    |                    ^^^ use of undeclared crate or module `bar`
-   |
-help: consider importing this module
-   |
-LL +     use crate::bar;
-   |
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs
index 3ea80173afa..709d8cdc762 100644
--- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs
+++ b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.rs
@@ -1,5 +1,4 @@
-// check-fail
-// FIXME(bryangarza): Change to check-pass when coinduction is supported for BikeshedIntrinsicFrom
+// check-pass
 #![feature(transmutability)]
 
 mod assert {
@@ -22,5 +21,5 @@ mod assert {
 fn main() {
     #[repr(C)] struct A(bool, &'static A);
     #[repr(C)] struct B(u8, &'static B);
-    assert::is_maybe_transmutable::<&'static A, &'static B>(); //~ ERROR overflow evaluating the requirement
+    assert::is_maybe_transmutable::<&'static A, &'static B>();
 }
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr b/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr
deleted file mode 100644
index fae332e6af9..00000000000
--- a/tests/ui/transmutability/references/recursive-wrapper-types-bit-compatible.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0275]: overflow evaluating the requirement `B: BikeshedIntrinsicFrom<A, assert::Context, Assume { alignment: true, lifetimes: false, safety: true, validity: false }>`
-  --> $DIR/recursive-wrapper-types-bit-compatible.rs:25:5
-   |
-LL |     assert::is_maybe_transmutable::<&'static A, &'static B>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by a bound in `is_maybe_transmutable`
-  --> $DIR/recursive-wrapper-types-bit-compatible.rs:11:14
-   |
-LL |       pub fn is_maybe_transmutable<Src, Dst>()
-   |              --------------------- required by a bound in this function
-LL |       where
-LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
-   |  ______________^
-LL | |             Assume {
-LL | |                 alignment: true,
-LL | |                 lifetimes: false,
-...  |
-LL | |             }
-LL | |         }>
-   | |__________^ required by this bound in `is_maybe_transmutable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.rs b/tests/ui/transmutability/references/recursive-wrapper-types.rs
index 59d1ad84a5d..090c1fea6db 100644
--- a/tests/ui/transmutability/references/recursive-wrapper-types.rs
+++ b/tests/ui/transmutability/references/recursive-wrapper-types.rs
@@ -1,5 +1,4 @@
-// check-fail
-// FIXME(bryangarza): Change to check-pass when coinduction is supported for BikeshedIntrinsicFrom
+// check-pass
 #![feature(transmutability)]
 
 mod assert {
@@ -22,6 +21,6 @@ mod assert {
 fn main() {
     #[repr(C)] struct A(&'static B);
     #[repr(C)] struct B(&'static A);
-    assert::is_maybe_transmutable::<&'static A, &'static B>(); //~ overflow evaluating the requirement
+    assert::is_maybe_transmutable::<&'static A, &'static B>();
     assert::is_maybe_transmutable::<&'static B, &'static A>();
 }
diff --git a/tests/ui/transmutability/references/recursive-wrapper-types.stderr b/tests/ui/transmutability/references/recursive-wrapper-types.stderr
deleted file mode 100644
index 35a60c22643..00000000000
--- a/tests/ui/transmutability/references/recursive-wrapper-types.stderr
+++ /dev/null
@@ -1,25 +0,0 @@
-error[E0275]: overflow evaluating the requirement `A: BikeshedIntrinsicFrom<B, assert::Context, Assume { alignment: true, lifetimes: false, safety: true, validity: false }>`
-  --> $DIR/recursive-wrapper-types.rs:25:5
-   |
-LL |     assert::is_maybe_transmutable::<&'static A, &'static B>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: required by a bound in `is_maybe_transmutable`
-  --> $DIR/recursive-wrapper-types.rs:11:14
-   |
-LL |       pub fn is_maybe_transmutable<Src, Dst>()
-   |              --------------------- required by a bound in this function
-LL |       where
-LL |           Dst: BikeshedIntrinsicFrom<Src, Context, {
-   |  ______________^
-LL | |             Assume {
-LL | |                 alignment: true,
-LL | |                 lifetimes: false,
-...  |
-LL | |             }
-LL | |         }>
-   | |__________^ required by this bound in `is_maybe_transmutable`
-
-error: aborting due to previous error
-
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/parser/type-alias-where-fixable.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed
index 2f47c0d91fa..2f47c0d91fa 100644
--- a/tests/ui/parser/type-alias-where-fixable.fixed
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.fixed
diff --git a/tests/ui/parser/type-alias-where-fixable.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs
index b20aa9398b5..b20aa9398b5 100644
--- a/tests/ui/parser/type-alias-where-fixable.rs
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.rs
diff --git a/tests/ui/parser/type-alias-where-fixable.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr
index f0acb388b97..b4de051845f 100644
--- a/tests/ui/parser/type-alias-where-fixable.stderr
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-impl.stderr
@@ -1,5 +1,5 @@
 warning: where clause not allowed here
-  --> $DIR/type-alias-where-fixable.rs:13:16
+  --> $DIR/where-clause-placement-assoc-type-in-impl.rs:13:16
    |
 LL |     type Assoc where u32: Copy = ();
    |                ^^^^^^^^^^^^^^^
@@ -13,7 +13,7 @@ LL +     type Assoc  = () where u32: Copy;
    |
 
 warning: where clause not allowed here
-  --> $DIR/type-alias-where-fixable.rs:16:17
+  --> $DIR/where-clause-placement-assoc-type-in-impl.rs:16:17
    |
 LL |     type Assoc2 where u32: Copy = () where i32: Copy;
    |                 ^^^^^^^^^^^^^^^
@@ -26,7 +26,7 @@ LL +     type Assoc2  = () where i32: Copy, u32: Copy;
    |
 
 warning: where clause not allowed here
-  --> $DIR/type-alias-where-fixable.rs:24:17
+  --> $DIR/where-clause-placement-assoc-type-in-impl.rs:24:17
    |
 LL |     type Assoc2 where u32: Copy, i32: Copy = ();
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed
new file mode 100644
index 00000000000..d171eba50b7
--- /dev/null
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.fixed
@@ -0,0 +1,15 @@
+// check-pass
+// run-rustfix
+
+#![feature(associated_type_defaults)]
+
+trait Trait {
+    // Not fine, suggests moving.
+    type Assoc  = () where u32: Copy;
+    //~^ WARNING where clause not allowed here
+    // Not fine, suggests moving `u32: Copy`
+    type Assoc2  = () where i32: Copy, u32: Copy;
+    //~^ WARNING where clause not allowed here
+}
+
+fn main() {}
diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs
new file mode 100644
index 00000000000..59afee65794
--- /dev/null
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.rs
@@ -0,0 +1,15 @@
+// check-pass
+// run-rustfix
+
+#![feature(associated_type_defaults)]
+
+trait Trait {
+    // Not fine, suggests moving.
+    type Assoc where u32: Copy = ();
+    //~^ WARNING where clause not allowed here
+    // Not fine, suggests moving `u32: Copy`
+    type Assoc2 where u32: Copy = () where i32: Copy;
+    //~^ WARNING where clause not allowed here
+}
+
+fn main() {}
diff --git a/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr
new file mode 100644
index 00000000000..a81cb8c8cd6
--- /dev/null
+++ b/tests/ui/where-clauses/where-clause-placement-assoc-type-in-trait.stderr
@@ -0,0 +1,29 @@
+warning: where clause not allowed here
+  --> $DIR/where-clause-placement-assoc-type-in-trait.rs:8:16
+   |
+LL |     type Assoc where u32: Copy = ();
+   |                ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+   = note: `#[warn(deprecated_where_clause_location)]` on by default
+help: move it to the end of the type declaration
+   |
+LL -     type Assoc where u32: Copy = ();
+LL +     type Assoc  = () where u32: Copy;
+   |
+
+warning: where clause not allowed here
+  --> $DIR/where-clause-placement-assoc-type-in-trait.rs:11:17
+   |
+LL |     type Assoc2 where u32: Copy = () where i32: Copy;
+   |                 ^^^^^^^^^^^^^^^
+   |
+   = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
+help: move it to the end of the type declaration
+   |
+LL -     type Assoc2 where u32: Copy = () where i32: Copy;
+LL +     type Assoc2  = () where i32: Copy, u32: Copy;
+   |
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/parser/type-alias-where.rs b/tests/ui/where-clauses/where-clause-placement-type-alias.rs
index 62e301cb408..62e301cb408 100644
--- a/tests/ui/parser/type-alias-where.rs
+++ b/tests/ui/where-clauses/where-clause-placement-type-alias.rs
diff --git a/tests/ui/parser/type-alias-where.stderr b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr
index fb838179266..b3c155a48dd 100644
--- a/tests/ui/parser/type-alias-where.stderr
+++ b/tests/ui/where-clauses/where-clause-placement-type-alias.stderr
@@ -1,5 +1,5 @@
 error: where clauses are not allowed after the type for type aliases
-  --> $DIR/type-alias-where.rs:6:15
+  --> $DIR/where-clause-placement-type-alias.rs:6:15
    |
 LL | type Bar = () where u32: Copy;
    |               ^^^^^^^^^^^^^^^
@@ -7,7 +7,7 @@ LL | type Bar = () where u32: Copy;
    = note: see issue #89122 <https://github.com/rust-lang/rust/issues/89122> for more information
 
 error: where clauses are not allowed after the type for type aliases
-  --> $DIR/type-alias-where.rs:8:15
+  --> $DIR/where-clause-placement-type-alias.rs:8:15
    |
 LL | type Baz = () where;
    |               ^^^^^
diff --git a/triagebot.toml b/triagebot.toml
index e6c593204ca..da9d167bd3e 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -257,6 +257,9 @@ new_pr = true
 
 [autolabel."needs-triage"]
 new_issue = true
+exclude_labels = [
+    "C-tracking-issue"
+]
 
 [autolabel."WG-trait-system-refactor"]
 trigger_files = [
@@ -483,10 +486,6 @@ message = "This PR changes src/bootstrap/defaults/config.codegen.toml. If approp
 
 [mentions."src/bootstrap/llvm.rs"]
 message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp."
-[mentions."compiler/rustc_llvm/build.rs"]
-message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp."
-[mentions."compiler/rustc_llvm/llvm-wrapper"]
-message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp."
 
 [mentions."tests/ui/deriving/deriving-all-codegen.stdout"]
 message = "Changes to the code generated for builtin derived traits."