about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/post-merge.yml2
-rw-r--r--Cargo.lock17
-rw-r--r--compiler/rustc_abi/Cargo.toml8
-rw-r--r--compiler/rustc_ast/src/ast.rs3
-rw-r--r--compiler/rustc_ast/src/format.rs2
-rw-r--r--compiler/rustc_ast/src/mut_visit.rs16
-rw-r--r--compiler/rustc_ast/src/visit.rs14
-rw-r--r--compiler/rustc_ast_lowering/src/expr.rs24
-rw-r--r--compiler/rustc_ast_lowering/src/format.rs2
-rw-r--r--compiler/rustc_ast_lowering/src/item.rs55
-rw-r--r--compiler/rustc_ast_lowering/src/lib.rs9
-rw-r--r--compiler/rustc_ast_passes/src/ast_validation.rs5
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state.rs11
-rw-r--r--compiler/rustc_ast_pretty/src/pprust/state/item.rs13
-rw-r--r--compiler/rustc_attr_data_structures/src/lib.rs52
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_attr_parsing/src/parser.rs4
-rw-r--r--compiler/rustc_borrowck/src/type_check/input_output.rs54
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/mod.rs20
-rw-r--r--compiler/rustc_borrowck/src/type_check/liveness/trace.rs44
-rw-r--r--compiler/rustc_borrowck/src/type_check/mod.rs210
-rw-r--r--compiler/rustc_borrowck/src/type_check/opaque_types.rs1
-rw-r--r--compiler/rustc_builtin_macros/Cargo.toml4
-rw-r--r--compiler/rustc_builtin_macros/messages.ftl3
-rw-r--r--compiler/rustc_builtin_macros/src/alloc_error_handler.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/autodiff.rs18
-rw-r--r--compiler/rustc_builtin_macros/src/define_opaque.rs54
-rw-r--r--compiler/rustc_builtin_macros/src/deriving/generic/mod.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/errors.rs9
-rw-r--r--compiler/rustc_builtin_macros/src/global_allocator.rs1
-rw-r--r--compiler/rustc_builtin_macros/src/lib.rs2
-rw-r--r--compiler/rustc_builtin_macros/src/test_harness.rs1
-rw-r--r--compiler/rustc_codegen_cranelift/example/issue-72793.rs24
-rw-r--r--compiler/rustc_codegen_cranelift/src/lib.rs13
-rw-r--r--compiler/rustc_codegen_gcc/src/gcc_util.rs2
-rw-r--r--compiler/rustc_codegen_gcc/src/lib.rs68
-rw-r--r--compiler/rustc_codegen_llvm/src/lib.rs4
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs115
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl28
-rw-r--r--compiler/rustc_codegen_ssa/src/codegen_attrs.rs125
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs104
-rw-r--r--compiler/rustc_codegen_ssa/src/target_features.rs2
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/backend.rs9
-rw-r--r--compiler/rustc_const_eval/src/interpret/memory.rs4
-rw-r--r--compiler/rustc_data_structures/Cargo.toml5
-rw-r--r--compiler/rustc_data_structures/src/lib.rs1
-rw-r--r--compiler/rustc_data_structures/src/marker.rs2
-rw-r--r--compiler/rustc_data_structures/src/obligation_forest/mod.rs1
-rw-r--r--compiler/rustc_data_structures/src/sharded.rs95
-rw-r--r--compiler/rustc_error_codes/src/error_codes/E0792.md4
-rw-r--r--compiler/rustc_error_messages/src/lib.rs1
-rw-r--r--compiler/rustc_expand/src/expand.rs4
-rw-r--r--compiler/rustc_expand/src/mbe/quoted.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir/src/hir.rs21
-rw-r--r--compiler/rustc_hir/src/intravisit.rs4
-rw-r--r--compiler/rustc_hir/src/stable_hash_impls.rs2
-rw-r--r--compiler/rustc_hir_analysis/messages.ftl9
-rw-r--r--compiler/rustc_hir_analysis/src/check/check.rs20
-rw-r--r--compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs80
-rw-r--r--compiler/rustc_hir_analysis/src/errors.rs10
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs127
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs25
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs37
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs2
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs24
-rw-r--r--compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs15
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs52
-rw-r--r--compiler/rustc_incremental/Cargo.toml2
-rw-r--r--compiler/rustc_incremental/src/persist/fs.rs4
-rw-r--r--compiler/rustc_index/src/slice.rs41
-rw-r--r--compiler/rustc_index/src/vec.rs4
-rw-r--r--compiler/rustc_interface/src/util.rs8
-rw-r--r--compiler/rustc_lint/src/context.rs16
-rw-r--r--compiler/rustc_lint/src/default_could_be_derived.rs2
-rw-r--r--compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs1
-rw-r--r--compiler/rustc_macros/src/print_attribute.rs27
-rw-r--r--compiler/rustc_middle/src/mir/interpret/allocation.rs5
-rw-r--r--compiler/rustc_middle/src/mir/interpret/mod.rs20
-rw-r--r--compiler/rustc_middle/src/mir/terminator.rs3
-rw-r--r--compiler/rustc_middle/src/query/erase.rs2
-rw-r--r--compiler/rustc_middle/src/ty/adt.rs8
-rw-r--r--compiler/rustc_middle/src/ty/context.rs4
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/builder/expr/as_constant.rs7
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/util.rs22
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs51
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/inspect/build.rs2
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/mod.rs4
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/project_goals.rs3
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/search_graph.rs30
-rw-r--r--compiler/rustc_parse/src/parser/diagnostics.rs2
-rw-r--r--compiler/rustc_parse/src/parser/item.rs46
-rw-r--r--compiler/rustc_parse_format/src/lib.rs18
-rw-r--r--compiler/rustc_privacy/src/lib.rs6
-rw-r--r--compiler/rustc_query_system/src/dep_graph/graph.rs31
-rw-r--r--compiler/rustc_query_system/src/lib.rs1
-rw-r--r--compiler/rustc_query_system/src/query/caches.rs14
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs2
-rw-r--r--compiler/rustc_resolve/src/late.rs67
-rw-r--r--compiler/rustc_span/src/symbol.rs24
-rw-r--r--compiler/rustc_target/src/spec/base/linux_wasm.rs159
-rw-r--r--compiler/rustc_target/src/spec/base/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/mod.rs1
-rw-r--r--compiler/rustc_target/src/spec/targets/wasm32_wali_linux_musl.rs29
-rw-r--r--compiler/rustc_target/src/target_features.rs12
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs27
-rw-r--r--compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs2
-rw-r--r--compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs19
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/mod.rs9
-rw-r--r--compiler/rustc_ty_utils/Cargo.toml1
-rw-r--r--compiler/rustc_ty_utils/src/layout.rs28
-rw-r--r--compiler/rustc_ty_utils/src/opaque_types.rs132
-rw-r--r--compiler/rustc_type_ir/Cargo.toml3
-rw-r--r--compiler/rustc_type_ir/src/search_graph/mod.rs165
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs19
-rw-r--r--config.example.toml10
-rw-r--r--library/Cargo.lock4
-rw-r--r--library/alloc/src/collections/binary_heap/mod.rs82
-rw-r--r--library/core/src/ffi/primitives.rs5
-rw-r--r--library/core/src/fmt/float.rs12
-rw-r--r--library/core/src/fmt/mod.rs51
-rw-r--r--library/core/src/fmt/rt.rs14
-rw-r--r--library/core/src/iter/traits/iterator.rs18
-rw-r--r--library/core/src/macros/mod.rs15
-rw-r--r--library/core/src/prelude/v1.rs8
-rw-r--r--library/core/src/sync/atomic.rs10
-rw-r--r--library/core/src/time.rs3
-rw-r--r--library/coretests/tests/num/flt2dec/mod.rs30
-rw-r--r--library/std/Cargo.toml2
-rw-r--r--library/std/src/backtrace.rs1
-rw-r--r--library/std/src/net/test.rs11
-rw-r--r--library/std/src/net/udp/tests.rs12
-rw-r--r--library/std/src/prelude/v1.rs9
-rw-r--r--library/std/src/sys/fs/hermit.rs6
-rw-r--r--library/std/src/sys/fs/uefi.rs99
-rw-r--r--library/std/src/sys/fs/unix.rs14
-rw-r--r--library/std/src/sys/pal/hermit/fd.rs21
-rw-r--r--library/std/src/sys/pal/unix/fd.rs3
-rw-r--r--library/std/src/sys/pal/unix/process/process_unix.rs3
-rw-r--r--library/std/src/sys/pal/unix/thread.rs3
-rw-r--r--library/std/src/sys/pal/unix/time.rs11
-rw-r--r--library/std/src/sys/pal/unix/weak.rs3
-rw-r--r--library/unwind/src/libunwind.rs5
-rw-r--r--src/bootstrap/Cargo.toml2
-rwxr-xr-xsrc/bootstrap/configure.py5
-rw-r--r--src/bootstrap/download-ci-gcc-stamp4
-rw-r--r--src/bootstrap/src/bin/sccache-plus-cl.rs9
-rw-r--r--src/bootstrap/src/core/build_steps/compile.rs48
-rw-r--r--src/bootstrap/src/core/build_steps/format.rs2
-rw-r--r--src/bootstrap/src/core/build_steps/gcc.rs309
-rw-r--r--src/bootstrap/src/core/build_steps/vendor.rs1
-rw-r--r--src/bootstrap/src/core/builder/tests.rs10
-rw-r--r--src/bootstrap/src/core/config/config.rs38
-rw-r--r--src/bootstrap/src/core/download.rs28
-rw-r--r--src/bootstrap/src/core/sanity.rs1
-rw-r--r--src/bootstrap/src/utils/cc_detect/tests.rs56
-rw-r--r--src/bootstrap/src/utils/change_tracker.rs5
-rw-r--r--src/bootstrap/src/utils/helpers.rs2
-rw-r--r--src/bootstrap/src/utils/job.rs65
-rw-r--r--src/ci/citool/Cargo.lock7
-rw-r--r--src/ci/citool/Cargo.toml1
-rw-r--r--src/ci/citool/src/jobs.rs244
-rw-r--r--src/ci/citool/src/jobs/tests.rs64
-rw-r--r--src/ci/citool/src/main.rs257
-rw-r--r--src/ci/citool/src/merge_report.rs2
m---------src/doc/book0
m---------src/doc/edition-guide0
m---------src/doc/nomicon0
m---------src/doc/reference0
m---------src/doc/rust-by-example0
-rw-r--r--src/doc/rustc-dev-guide/src/tests/ci.md28
-rw-r--r--src/doc/rustc/src/SUMMARY.md2
-rw-r--r--src/doc/rustc/src/platform-support.md3
-rw-r--r--src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-gnu.md47
-rw-r--r--src/doc/rustc/src/platform-support/wasm32-wali-linux.md98
-rw-r--r--src/doc/unstable-book/src/compiler-flags/crate-attr.md16
-rw-r--r--src/doc/unstable-book/src/language-features/default-field-values.md2
-rw-r--r--src/etc/test-float-parse/Cargo.toml4
-rw-r--r--src/etc/test-float-parse/src/gen/fuzz.rs8
-rw-r--r--src/etc/test-float-parse/src/gen/many_digits.rs14
-rw-r--r--src/etc/test-float-parse/src/lib.rs4
-rw-r--r--src/librustdoc/html/render/span_map.rs2
-rw-r--r--src/tools/clippy/clippy_utils/src/ast_utils/mod.rs6
-rw-r--r--src/tools/clippy/tests/ui/crashes/ice-10972-tait.rs10
-rw-r--r--src/tools/clippy/tests/ui/implied_bounds_in_impls.fixed1
-rw-r--r--src/tools/clippy/tests/ui/implied_bounds_in_impls.rs1
-rw-r--r--src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs1
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs1
-rw-r--r--src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr2
-rw-r--r--src/tools/miri/src/alloc_addresses/mod.rs4
-rw-r--r--src/tools/miri/src/shims/native_lib.rs2
-rw-r--r--src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs2
-rw-r--r--src/tools/tidy/src/deps.rs40
-rw-r--r--src/tools/tidy/src/issues.txt1
-rw-r--r--tests/assembly/targets/targets-elf.rs3
-rw-r--r--tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs24
-rw-r--r--tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs22
-rw-r--r--tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs88
-rw-r--r--tests/crashes/120016.rs1
-rw-r--r--tests/crashes/122904-2.rs2
-rw-r--r--tests/crashes/122904.rs1
-rw-r--r--tests/crashes/125185.rs14
-rw-r--r--tests/crashes/126680.rs22
-rw-r--r--tests/crashes/131298.rs12
-rw-r--r--tests/crashes/131886.rs5
-rw-r--r--tests/crashes/135528.rs2
-rw-r--r--tests/crashes/137049.rs1
-rw-r--r--tests/crashes/137865.rs5
-rw-r--r--tests/crashes/138048.rs8
-rw-r--r--tests/debuginfo/pretty-huge-vec.rs1
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff (renamed from tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff)45
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff (renamed from tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff)45
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff180
-rw-r--r--tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff180
-rw-r--r--tests/mir-opt/funky_arms.rs1
-rw-r--r--tests/pretty/hir-pretty-attr.pp2
-rw-r--r--tests/run-make/musl-default-linking/rmake.rs15
-rw-r--r--tests/run-make/rust-lld/rmake.rs5
-rw-r--r--tests/rustdoc-json/enums/discriminant/struct.rs2
-rw-r--r--tests/rustdoc-json/enums/discriminant/tuple.rs2
-rw-r--r--tests/ui/associated-inherent-types/constrain_opaque_types_during_projection.rs3
-rw-r--r--tests/ui/associated-inherent-types/issue-109299-1.stderr2
-rw-r--r--tests/ui/associated-type-bounds/dont-imply-atb-in-closure-inference.rs6
-rw-r--r--tests/ui/associated-type-bounds/duplicate.rs6
-rw-r--r--tests/ui/associated-type-bounds/duplicate.stderr126
-rw-r--r--tests/ui/associated-type-bounds/hrtb.rs3
-rw-r--r--tests/ui/associated-type-bounds/supertrait-defines-ty.rs3
-rw-r--r--tests/ui/associated-type-bounds/trait-alias-impl-trait.rs4
-rw-r--r--tests/ui/associated-types/issue-59324.rs1
-rw-r--r--tests/ui/associated-types/issue-59324.stderr21
-rw-r--r--tests/ui/async-await/async-fn/impl-trait.rs5
-rw-r--r--tests/ui/async-await/issues/issue-60655-latebound-regions.rs4
-rw-r--r--tests/ui/async-await/normalize-output-in-signature-deduction.rs1
-rw-r--r--tests/ui/attributes/collapse-debuginfo-invalid.rs19
-rw-r--r--tests/ui/attributes/collapse-debuginfo-invalid.stderr6
-rw-r--r--tests/ui/attributes/z-crate-attr/basic.rs (renamed from tests/ui/attributes/z-crate-attr.rs)0
-rw-r--r--tests/ui/attributes/z-crate-attr/cfg-false.rs7
-rw-r--r--tests/ui/attributes/z-crate-attr/comments.rs5
-rw-r--r--tests/ui/attributes/z-crate-attr/crate-name.rs6
-rw-r--r--tests/ui/attributes/z-crate-attr/crate-type.rs3
-rw-r--r--tests/ui/attributes/z-crate-attr/garbage.rs4
-rw-r--r--tests/ui/attributes/z-crate-attr/garbage.stderr20
-rw-r--r--tests/ui/attributes/z-crate-attr/injection.rs3
-rw-r--r--tests/ui/attributes/z-crate-attr/injection.stderr8
-rw-r--r--tests/ui/attributes/z-crate-attr/inner-attr.rs4
-rw-r--r--tests/ui/attributes/z-crate-attr/inner-attr.stderr8
-rw-r--r--tests/ui/attributes/z-crate-attr/multiple.rs3
-rw-r--r--tests/ui/attributes/z-crate-attr/multiple.stderr8
-rw-r--r--tests/ui/attributes/z-crate-attr/respect-existing-attrs.rs9
-rw-r--r--tests/ui/attributes/z-crate-attr/shebang.rs6
-rw-r--r--tests/ui/attributes/z-crate-attr/unbalanced-paren.rs4
-rw-r--r--tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr10
-rw-r--r--tests/ui/autodiff/autodiff_illegal.rs52
-rw-r--r--tests/ui/autodiff/autodiff_illegal.stderr52
-rw-r--r--tests/ui/borrowck/overwrite-anon-late-param-regions.rs1
-rw-r--r--tests/ui/borrowck/overwrite-anon-late-param-regions.stderr4
-rw-r--r--tests/ui/check-cfg/allow-same-level.rs2
-rw-r--r--tests/ui/coherence/coherence-with-closure.rs1
-rw-r--r--tests/ui/coherence/coherence-with-closure.stderr2
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.rs1
-rw-r--r--tests/ui/coherence/coherence-with-coroutine.stock.stderr2
-rw-r--r--tests/ui/coherence/issue-99663-2.rs1
-rw-r--r--tests/ui/coherence/issue-99663.rs1
-rw-r--r--tests/ui/coherence/occurs-check/opaques.current.stderr6
-rw-r--r--tests/ui/coherence/occurs-check/opaques.next.stderr12
-rw-r--r--tests/ui/coherence/occurs-check/opaques.rs17
-rw-r--r--tests/ui/coherence/orphan-check-opaque-types-not-covering.rs2
-rw-r--r--tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/opaque_type.rs4
-rw-r--r--tests/ui/const-generics/generic_const_exprs/opaque_type.stderr4
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs10
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr11
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr25
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr16
-rw-r--r--tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs18
-rw-r--r--tests/ui/const-generics/opaque_types.rs3
-rw-r--r--tests/ui/const-generics/opaque_types.stderr116
-rw-r--r--tests/ui/const-generics/opaque_types2.rs13
-rw-r--r--tests/ui/const-generics/opaque_types2.stderr6
-rw-r--r--tests/ui/consts/const-eval/ice-unhandled-type-122191.rs14
-rw-r--r--tests/ui/consts/const-eval/ice-unhandled-type-122191.stderr33
-rw-r--r--tests/ui/consts/const-promoted-opaque.atomic.stderr8
-rw-r--r--tests/ui/consts/const-promoted-opaque.rs30
-rw-r--r--tests/ui/consts/const-promoted-opaque.string.stderr6
-rw-r--r--tests/ui/consts/const-promoted-opaque.unit.stderr24
-rw-r--r--tests/ui/consts/large_const_alloc.rs3
-rw-r--r--tests/ui/consts/large_const_alloc.stderr4
-rw-r--r--tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs3
-rw-r--r--tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr2
-rw-r--r--tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs1
-rw-r--r--tests/ui/coroutine/layout-error.rs24
-rw-r--r--tests/ui/coroutine/layout-error.stderr6
-rw-r--r--tests/ui/coroutine/metadata-sufficient-for-layout.rs1
-rw-r--r--tests/ui/drop/drop_elaboration_with_errors.rs1
-rw-r--r--tests/ui/drop/drop_elaboration_with_errors.stderr2
-rw-r--r--tests/ui/dyn-keyword/dyn-2021-edition-error.rs6
-rw-r--r--tests/ui/dyn-keyword/dyn-2021-edition-error.stderr13
-rw-r--r--tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.rs (renamed from tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.rs)13
-rw-r--r--tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr (renamed from tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.stderr)29
-rw-r--r--tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs6
-rw-r--r--tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs9
-rw-r--r--tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr1
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion.rs5
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs3
-rw-r--r--tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr4
-rw-r--r--tests/ui/generic-associated-types/issue-87258_b.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-87258_b.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-88287.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-88287.stderr2
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait.stderr15
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.rs1
-rw-r--r--tests/ui/generic-associated-types/issue-90014-tait2.stderr2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr10
-rw-r--r--tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs1
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs36
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr14
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs13
-rw-r--r--tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr15
-rw-r--r--tests/ui/impl-trait/associated-type-undefine.rs1
-rw-r--r--tests/ui/impl-trait/associated-type-undefine.stderr17
-rw-r--r--tests/ui/impl-trait/async_scope_creep.rs2
-rw-r--r--tests/ui/impl-trait/auto-trait-coherence.rs1
-rw-r--r--tests/ui/impl-trait/auto-trait-coherence.stderr2
-rw-r--r--tests/ui/impl-trait/bound-normalization-pass.rs1
-rw-r--r--tests/ui/impl-trait/coherence-treats-tait-ambig.rs3
-rw-r--r--tests/ui/impl-trait/deduce-signature-from-supertrait.rs3
-rw-r--r--tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs11
-rw-r--r--tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr2
-rw-r--r--tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr2
-rw-r--r--tests/ui/impl-trait/hidden-type-is-opaque-2.rs1
-rw-r--r--tests/ui/impl-trait/hidden-type-is-opaque.rs1
-rw-r--r--tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr14
-rw-r--r--tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr18
-rw-r--r--tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs1
-rw-r--r--tests/ui/impl-trait/in-assoc-type-unconstrained.stderr5
-rw-r--r--tests/ui/impl-trait/in-assoc-type.stderr5
-rw-r--r--tests/ui/impl-trait/issue-108591.rs1
-rw-r--r--tests/ui/impl-trait/issue-108592.rs11
-rw-r--r--tests/ui/impl-trait/issue-99642-2.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-53457.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-70877.rs38
-rw-r--r--tests/ui/impl-trait/issues/issue-70877.stderr63
-rw-r--r--tests/ui/impl-trait/issues/issue-74282.rs3
-rw-r--r--tests/ui/impl-trait/issues/issue-74282.stderr10
-rw-r--r--tests/ui/impl-trait/issues/issue-77987.rs13
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-78722-2.stderr8
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.rs1
-rw-r--r--tests/ui/impl-trait/issues/issue-78722.stderr6
-rw-r--r--tests/ui/impl-trait/issues/issue-86201.rs7
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.rs24
-rw-r--r--tests/ui/impl-trait/issues/issue-86800.stderr40
-rw-r--r--tests/ui/impl-trait/issues/issue-89312.rs24
-rw-r--r--tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs1
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs1
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr4
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling.rs1
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr2
-rw-r--r--tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs1
-rw-r--r--tests/ui/impl-trait/negative-reasoning.rs1
-rw-r--r--tests/ui/impl-trait/negative-reasoning.stderr2
-rw-r--r--tests/ui/impl-trait/nested-return-type2-tait.rs4
-rw-r--r--tests/ui/impl-trait/nested-return-type2-tait.stderr2
-rw-r--r--tests/ui/impl-trait/nested-return-type2-tait2.rs4
-rw-r--r--tests/ui/impl-trait/nested-return-type2-tait3.rs4
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait.rs4
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait.stderr2
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait2.rs4
-rw-r--r--tests/ui/impl-trait/nested-return-type3-tait3.rs4
-rw-r--r--tests/ui/impl-trait/normalize-tait-in-const.stderr32
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs10
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs1
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr20
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs1
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr2
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other.current.stderr2
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other.rs1
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr10
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr2
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other2.rs1
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr2
-rw-r--r--tests/ui/impl-trait/two_tait_defining_each_other3.rs1
-rw-r--r--tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs1
-rw-r--r--tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.stderr6
-rw-r--r--tests/ui/impl-trait/where-allowed.rs1
-rw-r--r--tests/ui/impl-trait/where-allowed.stderr58
-rw-r--r--tests/ui/implied-bounds/dyn-erasure-tait.rs1
-rw-r--r--tests/ui/layout/debug.rs1
-rw-r--r--tests/ui/layout/debug.stderr30
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/branches.rs8
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/branches.stderr2
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/branches2.rs13
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/branches3.rs3
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/branches3.stderr8
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion.rs5
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion2.rs3
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion3.rs5
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion3.stderr4
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion4.rs1
-rw-r--r--tests/ui/lazy-type-alias-impl-trait/recursion4.stderr4
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr7
-rw-r--r--tests/ui/lazy-type-alias/inherent-impls-overflow.rs2
-rw-r--r--tests/ui/linking/no-gc-encapsulation-symbols.rs25
-rw-r--r--tests/ui/lint/invalid_from_utf8.rs41
-rw-r--r--tests/ui/lint/invalid_from_utf8.stderr65
-rw-r--r--tests/ui/lint/issue-99387.rs1
-rw-r--r--tests/ui/lint/issue-99387.stderr6
-rw-r--r--tests/ui/lint/let_underscore/issue-119697-extra-let.rs2
-rw-r--r--tests/ui/lint/let_underscore/issue-119697-extra-let.stderr4
-rw-r--r--tests/ui/lint/lint-ctypes-73249-2.rs1
-rw-r--r--tests/ui/lint/lint-ctypes-73249-2.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-73249-3.rs1
-rw-r--r--tests/ui/lint/lint-ctypes-73249-3.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-73249-5.rs1
-rw-r--r--tests/ui/lint/lint-ctypes-73249-5.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-73251-1.rs1
-rw-r--r--tests/ui/lint/lint-ctypes-73251-1.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-73251-2.rs2
-rw-r--r--tests/ui/lint/lint-ctypes-73251-2.stderr2
-rw-r--r--tests/ui/lint/lint-ctypes-73251.rs1
-rw-r--r--tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs2
-rw-r--r--tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr2
-rw-r--r--tests/ui/lint/opaque-ty-ffi-unsafe.rs1
-rw-r--r--tests/ui/lint/opaque-ty-ffi-unsafe.stderr2
-rw-r--r--tests/ui/methods/opaque_param_in_ufc.rs2
-rw-r--r--tests/ui/mir/issue-75053.rs12
-rw-r--r--tests/ui/mir/issue-75053.stderr2
-rw-r--r--tests/ui/never_type/impl_trait_fallback2.rs2
-rw-r--r--tests/ui/never_type/impl_trait_fallback2.stderr2
-rw-r--r--tests/ui/never_type/impl_trait_fallback3.rs1
-rw-r--r--tests/ui/never_type/impl_trait_fallback3.stderr2
-rw-r--r--tests/ui/never_type/impl_trait_fallback4.rs1
-rw-r--r--tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr2
-rw-r--r--tests/ui/pattern/usefulness/impl-trait.rs6
-rw-r--r--tests/ui/pattern/usefulness/impl-trait.stderr80
-rw-r--r--tests/ui/privacy/private-in-public-type-alias-impl-trait.rs1
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs13
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr53
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs7
-rw-r--r--tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr6
-rw-r--r--tests/ui/self/arbitrary-self-opaque.rs1
-rw-r--r--tests/ui/self/arbitrary-self-opaque.stderr10
-rw-r--r--tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs38
-rw-r--r--tests/ui/self/dyn-dispatch-requires-supertrait.rs38
-rw-r--r--tests/ui/specialization/min_specialization/impl-on-opaque.rs1
-rw-r--r--tests/ui/specialization/min_specialization/impl-on-opaque2.rs1
-rw-r--r--tests/ui/traits/alias/issue-83613.rs1
-rw-r--r--tests/ui/traits/alias/issue-83613.stderr2
-rw-r--r--tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs3
-rw-r--r--tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs3
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs8
-rw-r--r--tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr16
-rw-r--r--tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs21
-rw-r--r--tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs21
-rw-r--r--tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr11
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs3
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr2
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr2
-rw-r--r--tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs4
-rw-r--r--tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr14
-rw-r--r--tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs4
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs7
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr54
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs7
-rw-r--r--tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr54
-rw-r--r--tests/ui/traits/pointee-tail-is-generic-errors.rs1
-rw-r--r--tests/ui/traits/pointee-tail-is-generic-errors.stderr8
-rw-r--r--tests/ui/traits/pointee-tail-is-generic.rs11
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs1
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/argument-types.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/assoc-projection-ice.rs24
-rw-r--r--tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/bound_reduction.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bound_reduction2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/bound_reduction2.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/bounds-are-checked3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/bounds.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/closure-normalization-ice-109020.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/closure_args.rs24
-rw-r--r--tests/ui/type-alias-impl-trait/closure_args2.rs34
-rw-r--r--tests/ui/type-alias-impl-trait/closure_infer.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/closure_parent_substs.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/closure_wf_outlives.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/closures_in_branches.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/closures_in_branches.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.classic.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.next.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/coherence.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_cross_crate.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/coherence_generalization.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr28
-rw-r--r--tests/ui/type-alias-impl-trait/const_generic_type.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_in_projection2.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_inputs.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_inputs.stderr30
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/generics.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/generics.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/defining-use-submodule.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal3.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/different_args_considered_equal3.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs36
-rw-r--r--tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr25
-rw-r--r--tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/escaping-bound-var.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr36
-rw-r--r--tests/ui/type-alias-impl-trait/fallback.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/fallback.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/field-types.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/future.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/future.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr38
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_lifetime_param.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr38
-rw-r--r--tests/ui/type-alias-impl-trait/generic_not_used.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_not_used.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr20
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr42
-rw-r--r--tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/impl_trait_in_trait_defined_outside_trait.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds2.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs14
-rw-r--r--tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr24
-rw-r--r--tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs20
-rw-r--r--tests/ui/type-alias-impl-trait/in-where-clause.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/in-where-clause.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/incomplete-inference.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/incomplete-inference.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/inference-cycle.rs28
-rw-r--r--tests/ui/type-alias-impl-trait/inference-cycle.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr19
-rw-r--r--tests/ui/type-alias-impl-trait/issue-101750.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/issue-104817.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-104817.stock.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-109054.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-109054.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-52843.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092-2.stderr77
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53092.stderr16
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53096.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53096.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs19
-rw-r--r--tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-57961.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58662-simplified.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58951-2.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-58951.rs11
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60407.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60407.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60564.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-60564.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63279.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63355.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63355.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65384.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs23
-rw-r--r--tests/ui/type-alias-impl-trait/issue-65918.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-69323.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-70121.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/issue-72793.rs25
-rw-r--r--tests/ui/type-alias-impl-trait/issue-74244.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-74280.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-74280.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs29
-rw-r--r--tests/ui/type-alias-impl-trait/issue-77179.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/issue-77179.stderr40
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/issue-89686.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-89686.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/issue-93411.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/itiat-forbid-nested-items.stderr5
-rw-r--r--tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.next.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution2.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.next.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution4.rs10
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution5.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr7
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/nested.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/nested_inference_failure.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs24
-rw-r--r--tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr36
-rw-r--r--tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr18
-rw-r--r--tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr26
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-alias-type.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/normalize-hidden-types.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr17
-rw-r--r--tests/ui/type-alias-impl-trait/not_a_defining_use.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/not_a_defining_use.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/not_well_formed.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/obligation_ice.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/outlives-bound-var.rs8
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch2.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch3.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch3.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/param_mismatch4.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/path_resolution_taint.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/path_resolution_taint.stderr9
-rw-r--r--tests/ui/type-alias-impl-trait/privacy.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/privacy.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-fn-tait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr8
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs25
-rw-r--r--tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr12
-rw-r--r--tests/ui/type-alias-impl-trait/reveal_local.rs7
-rw-r--r--tests/ui/type-alias-impl-trait/reveal_local.stderr22
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.current.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-2.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-3.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-4.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential-4.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/self-referential.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/self_implication.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/static-const-types.rs13
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match-no-leak.rs16
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match.rs17
-rw-r--r--tests/ui/type-alias-impl-trait/structural-match.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/taint.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/taint.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs12
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr57
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs4
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs15
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr11
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs20
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs105
-rw-r--r--tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/type_of_a_let.rs2
-rw-r--r--tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs9
-rw-r--r--tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/under-binder.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/under-binder.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_generic.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_generic.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr14
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/unnameable_type.stderr4
-rw-r--r--tests/ui/type-alias-impl-trait/unused_generic_param.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/variance.rs1
-rw-r--r--tests/ui/type-alias-impl-trait/variance.stderr10
-rw-r--r--tests/ui/type-alias-impl-trait/weird-return-types.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/wf-check-definition-site.rs6
-rw-r--r--tests/ui/type-alias-impl-trait/wf-check-fn-def.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr6
-rw-r--r--tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs5
-rw-r--r--tests/ui/type-alias-impl-trait/wf-nested.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/wf-nested.stderr2
-rw-r--r--tests/ui/type-alias-impl-trait/wf_check_closures.rs3
-rw-r--r--tests/ui/type-alias-impl-trait/wf_check_closures.stderr8
-rw-r--r--tests/ui/type/pattern_types/literals.rs136
-rw-r--r--tests/ui/type/pattern_types/literals.stderr193
-rw-r--r--tests/ui/type/pattern_types/nested.rs4
-rw-r--r--tests/ui/type/pattern_types/nested.stderr9
-rw-r--r--tests/ui/type/pattern_types/range_patterns.rs21
-rw-r--r--tests/ui/type/pattern_types/range_patterns.stderr117
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.rs1
-rw-r--r--tests/ui/typeck/typeck_type_placeholder_item.stderr42
-rw-r--r--tests/ui/unpretty/deprecated-attr.rs2
-rw-r--r--tests/ui/unpretty/deprecated-attr.stdout21
-rw-r--r--triagebot.toml5
892 files changed, 7107 insertions, 4159 deletions
diff --git a/.github/workflows/post-merge.yml b/.github/workflows/post-merge.yml
index 2bc06d83c5b..31e075f45d6 100644
--- a/.github/workflows/post-merge.yml
+++ b/.github/workflows/post-merge.yml
@@ -36,7 +36,7 @@ jobs:
           cd src/ci/citool
 
           echo "Post-merge analysis result" > output.log
-          cargo run --release post-merge-analysis ${PARENT_COMMIT} ${{ github.sha }} >> output.log
+          cargo run --release post-merge-report ${PARENT_COMMIT} ${{ github.sha }} >> output.log
           cat output.log
 
           gh pr comment ${HEAD_PR} -F output.log
diff --git a/Cargo.lock b/Cargo.lock
index ecd26d6199c..7625b38401d 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -1491,6 +1491,7 @@ version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
 checksum = "bf151400ff0baff5465007dd2f3e717f3fe502074ca563069ce3a6629d07b289"
 dependencies = [
+ "allocator-api2",
  "foldhash",
  "serde",
 ]
@@ -2881,11 +2882,11 @@ dependencies = [
 
 [[package]]
 name = "rand_xoshiro"
-version = "0.6.0"
+version = "0.7.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "6f97cdb2a36ed4183de61b2f824cc45c9f1037f28afe0a322e9fff4c108b5aaa"
+checksum = "f703f4665700daf5512dcca5f43afa6af89f09db47fb56be587f80636bda2d41"
 dependencies = [
- "rand_core 0.6.4",
+ "rand_core 0.9.0",
 ]
 
 [[package]]
@@ -3155,7 +3156,7 @@ name = "rustc_abi"
 version = "0.0.0"
 dependencies = [
  "bitflags",
- "rand 0.8.5",
+ "rand 0.9.0",
  "rand_xoshiro",
  "rustc_data_structures",
  "rustc_hashes",
@@ -3492,6 +3493,7 @@ dependencies = [
  "either",
  "elsa",
  "ena",
+ "hashbrown 0.15.2",
  "indexmap",
  "jobserver",
  "libc",
@@ -3789,7 +3791,7 @@ dependencies = [
 name = "rustc_incremental"
 version = "0.0.0"
 dependencies = [
- "rand 0.8.5",
+ "rand 0.9.0",
  "rustc_ast",
  "rustc_data_structures",
  "rustc_errors",
@@ -4529,6 +4531,7 @@ version = "0.0.0"
 dependencies = [
  "itertools",
  "rustc_abi",
+ "rustc_attr_parsing",
  "rustc_data_structures",
  "rustc_errors",
  "rustc_fluent_macro",
@@ -5176,8 +5179,8 @@ version = "0.1.0"
 dependencies = [
  "indicatif",
  "num",
- "rand 0.8.5",
- "rand_chacha 0.3.1",
+ "rand 0.9.0",
+ "rand_chacha 0.9.0",
  "rayon",
 ]
 
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 86dc84e2016..5f9afc46a1a 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -6,13 +6,13 @@ edition = "2024"
 [dependencies]
 # tidy-alphabetical-start
 bitflags = "2.4.1"
-rand = { version = "0.8.4", default-features = false, optional = true }
-rand_xoshiro = { version = "0.6.0", optional = true }
-rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
+rand = { version = "0.9.0", default-features = false, optional = true }
+rand_xoshiro = { version = "0.7.0", optional = true }
+rustc_data_structures = { path = "../rustc_data_structures", optional = true }
 rustc_hashes = { path = "../rustc_hashes" }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
-rustc_serialize = { path = "../rustc_serialize", optional = true  }
+rustc_serialize = { path = "../rustc_serialize", optional = true }
 rustc_span = { path = "../rustc_span", optional = true }
 tracing = "0.1"
 # tidy-alphabetical-end
diff --git a/compiler/rustc_ast/src/ast.rs b/compiler/rustc_ast/src/ast.rs
index 002435b2d03..1b831c454e6 100644
--- a/compiler/rustc_ast/src/ast.rs
+++ b/compiler/rustc_ast/src/ast.rs
@@ -3466,6 +3466,7 @@ pub struct Fn {
     pub generics: Generics,
     pub sig: FnSig,
     pub contract: Option<P<FnContract>>,
+    pub define_opaque: Option<ThinVec<(NodeId, Path)>>,
     pub body: Option<P<Block>>,
 }
 
@@ -3763,7 +3764,7 @@ mod size_asserts {
     static_assert_size!(Block, 32);
     static_assert_size!(Expr, 72);
     static_assert_size!(ExprKind, 40);
-    static_assert_size!(Fn, 168);
+    static_assert_size!(Fn, 176);
     static_assert_size!(ForeignItem, 88);
     static_assert_size!(ForeignItemKind, 16);
     static_assert_size!(GenericArg, 24);
diff --git a/compiler/rustc_ast/src/format.rs b/compiler/rustc_ast/src/format.rs
index b93846c1fe6..b611ddea1d9 100644
--- a/compiler/rustc_ast/src/format.rs
+++ b/compiler/rustc_ast/src/format.rs
@@ -266,7 +266,7 @@ pub enum FormatAlignment {
 #[derive(Clone, Encodable, Decodable, Debug, PartialEq, Eq)]
 pub enum FormatCount {
     /// `{:5}` or `{:.5}`
-    Literal(usize),
+    Literal(u16),
     /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
     Argument(FormatArgPosition),
 }
diff --git a/compiler/rustc_ast/src/mut_visit.rs b/compiler/rustc_ast/src/mut_visit.rs
index ee894db7b96..fc31912283a 100644
--- a/compiler/rustc_ast/src/mut_visit.rs
+++ b/compiler/rustc_ast/src/mut_visit.rs
@@ -973,7 +973,14 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
             _ctxt,
             _ident,
             _vis,
-            Fn { defaultness, generics, contract, body, sig: FnSig { header, decl, span } },
+            Fn {
+                defaultness,
+                generics,
+                contract,
+                body,
+                sig: FnSig { header, decl, span },
+                define_opaque,
+            },
         ) => {
             // Identifier and visibility are visited as a part of the item.
             visit_defaultness(vis, defaultness);
@@ -987,6 +994,11 @@ fn walk_fn<T: MutVisitor>(vis: &mut T, kind: FnKind<'_>) {
                 vis.visit_block(body);
             }
             vis.visit_span(span);
+
+            for (id, path) in define_opaque.iter_mut().flatten() {
+                vis.visit_id(id);
+                vis.visit_path(path)
+            }
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
             vis.visit_closure_binder(binder);
@@ -1936,7 +1948,7 @@ impl DummyAstNode for Item {
                 span: Default::default(),
                 tokens: Default::default(),
             },
-            ident: Ident::empty(),
+            ident: Ident::dummy(),
             kind: ItemKind::ExternCrate(None),
             tokens: Default::default(),
         }
diff --git a/compiler/rustc_ast/src/visit.rs b/compiler/rustc_ast/src/visit.rs
index 43ffbe9b071..cfcb0e23cb5 100644
--- a/compiler/rustc_ast/src/visit.rs
+++ b/compiler/rustc_ast/src/visit.rs
@@ -892,7 +892,14 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
             _ctxt,
             _ident,
             _vis,
-            Fn { defaultness: _, sig: FnSig { header, decl, span: _ }, generics, contract, body },
+            Fn {
+                defaultness: _,
+                sig: FnSig { header, decl, span: _ },
+                generics,
+                contract,
+                body,
+                define_opaque,
+            },
         ) => {
             // Identifier and visibility are visited as a part of the item.
             try_visit!(visitor.visit_fn_header(header));
@@ -900,6 +907,9 @@ pub fn walk_fn<'a, V: Visitor<'a>>(visitor: &mut V, kind: FnKind<'a>) -> V::Resu
             try_visit!(visitor.visit_fn_decl(decl));
             visit_opt!(visitor, visit_contract, contract);
             visit_opt!(visitor, visit_block, body);
+            for (id, path) in define_opaque.iter().flatten() {
+                try_visit!(visitor.visit_path(path, *id))
+            }
         }
         FnKind::Closure(binder, coroutine_kind, decl, body) => {
             try_visit!(visitor.visit_closure_binder(binder));
@@ -1203,7 +1213,7 @@ pub fn walk_expr<'a, V: Visitor<'a>>(visitor: &mut V, expression: &'a Expr) -> V
                 FnKind::Closure(binder, coroutine_kind, fn_decl, body),
                 *span,
                 *id
-            ))
+            ));
         }
         ExprKind::Block(block, opt_label) => {
             visit_opt!(visitor, visit_label, opt_label);
diff --git a/compiler/rustc_ast_lowering/src/expr.rs b/compiler/rustc_ast_lowering/src/expr.rs
index acf35b75e4d..5bb6704dde4 100644
--- a/compiler/rustc_ast_lowering/src/expr.rs
+++ b/compiler/rustc_ast_lowering/src/expr.rs
@@ -2130,26 +2130,24 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.arena.alloc(self.expr(sp, hir::ExprKind::Tup(&[])))
     }
 
-    pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
+    fn expr_uint(&mut self, sp: Span, ty: ast::UintTy, value: u128) -> hir::Expr<'hir> {
         let lit = self.arena.alloc(hir::Lit {
             span: sp,
-            node: ast::LitKind::Int(
-                (value as u128).into(),
-                ast::LitIntType::Unsigned(ast::UintTy::Usize),
-            ),
+            node: ast::LitKind::Int(value.into(), ast::LitIntType::Unsigned(ty)),
         });
         self.expr(sp, hir::ExprKind::Lit(lit))
     }
 
+    pub(super) fn expr_usize(&mut self, sp: Span, value: usize) -> hir::Expr<'hir> {
+        self.expr_uint(sp, ast::UintTy::Usize, value as u128)
+    }
+
     pub(super) fn expr_u32(&mut self, sp: Span, value: u32) -> hir::Expr<'hir> {
-        let lit = self.arena.alloc(hir::Lit {
-            span: sp,
-            node: ast::LitKind::Int(
-                u128::from(value).into(),
-                ast::LitIntType::Unsigned(ast::UintTy::U32),
-            ),
-        });
-        self.expr(sp, hir::ExprKind::Lit(lit))
+        self.expr_uint(sp, ast::UintTy::U32, value as u128)
+    }
+
+    pub(super) fn expr_u16(&mut self, sp: Span, value: u16) -> hir::Expr<'hir> {
+        self.expr_uint(sp, ast::UintTy::U16, value as u128)
     }
 
     pub(super) fn expr_char(&mut self, sp: Span, value: char) -> hir::Expr<'hir> {
diff --git a/compiler/rustc_ast_lowering/src/format.rs b/compiler/rustc_ast_lowering/src/format.rs
index 07b94dbc2ae..faa47274f96 100644
--- a/compiler/rustc_ast_lowering/src/format.rs
+++ b/compiler/rustc_ast_lowering/src/format.rs
@@ -292,7 +292,7 @@ fn make_count<'hir>(
                 hir::LangItem::FormatCount,
                 sym::Is,
             ));
-            let value = ctx.arena.alloc_from_iter([ctx.expr_usize(sp, *n)]);
+            let value = ctx.arena.alloc_from_iter([ctx.expr_u16(sp, *n)]);
             ctx.expr_call_mut(sp, count_is, value)
         }
         Some(FormatCount::Argument(arg)) => {
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index b01ca54fb6f..9adc8bdd361 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -3,10 +3,9 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::AssocCtxt;
 use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
-use rustc_hir as hir;
-use rustc_hir::PredicateOrigin;
 use rustc_hir::def::{DefKind, Res};
 use rustc_hir::def_id::{CRATE_DEF_ID, LocalDefId};
+use rustc_hir::{self as hir, HirId, PredicateOrigin};
 use rustc_index::{IndexSlice, IndexVec};
 use rustc_middle::span_bug;
 use rustc_middle::ty::{ResolverAstLowering, TyCtxt};
@@ -209,6 +208,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 generics,
                 body,
                 contract,
+                define_opaque,
                 ..
             }) => {
                 self.with_new_scopes(*fn_sig_span, |this| {
@@ -237,6 +237,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                         header: this.lower_fn_header(*header, hir::Safety::Safe, attrs),
                         span: this.lower_span(*fn_sig_span),
                     };
+                    this.lower_define_opaque(hir_id, &define_opaque);
                     hir::ItemKind::Fn { sig, generics, body: body_id, has_body: body.is_some() }
                 })
             }
@@ -779,7 +780,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                 );
                 (generics, kind, expr.is_some())
             }
-            AssocItemKind::Fn(box Fn { sig, generics, body: None, .. }) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body: None, define_opaque, .. }) => {
                 // FIXME(contracts): Deny contract here since it won't apply to
                 // any impl method or callees.
                 let names = self.lower_fn_params_to_names(&sig.decl);
@@ -791,9 +792,22 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     sig.header.coroutine_kind,
                     attrs,
                 );
+                if define_opaque.is_some() {
+                    self.dcx().span_err(
+                        i.span,
+                        "only trait methods with default bodies can define opaque types",
+                    );
+                }
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Required(names)), false)
             }
-            AssocItemKind::Fn(box Fn { sig, generics, body: Some(body), contract, .. }) => {
+            AssocItemKind::Fn(box Fn {
+                sig,
+                generics,
+                body: Some(body),
+                contract,
+                define_opaque,
+                ..
+            }) => {
                 let body_id = self.lower_maybe_coroutine_body(
                     sig.span,
                     i.span,
@@ -812,6 +826,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     sig.header.coroutine_kind,
                     attrs,
                 );
+                self.lower_define_opaque(hir_id, &define_opaque);
                 (generics, hir::TraitItemKind::Fn(sig, hir::TraitFn::Provided(body_id)), true)
             }
             AssocItemKind::Type(box TyAlias { generics, where_clauses, bounds, ty, .. }) => {
@@ -911,7 +926,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     hir::ImplItemKind::Const(ty, body)
                 },
             ),
-            AssocItemKind::Fn(box Fn { sig, generics, body, contract, .. }) => {
+            AssocItemKind::Fn(box Fn { sig, generics, body, contract, define_opaque, .. }) => {
                 let body_id = self.lower_maybe_coroutine_body(
                     sig.span,
                     i.span,
@@ -930,6 +945,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
                     sig.header.coroutine_kind,
                     attrs,
                 );
+                self.lower_define_opaque(hir_id, &define_opaque);
 
                 (generics, hir::ImplItemKind::Fn(sig, body_id))
             }
@@ -1657,6 +1673,35 @@ impl<'hir> LoweringContext<'_, 'hir> {
         (lowered_generics, res)
     }
 
+    pub(super) fn lower_define_opaque(
+        &mut self,
+        hir_id: HirId,
+        define_opaque: &Option<ThinVec<(NodeId, Path)>>,
+    ) {
+        assert_eq!(self.define_opaque, None);
+        assert!(hir_id.is_owner());
+        let Some(define_opaque) = define_opaque.as_ref() else {
+            return;
+        };
+        let define_opaque = define_opaque.iter().filter_map(|(id, path)| {
+            let res = self.resolver.get_partial_res(*id).unwrap();
+            let Some(did) = res.expect_full_res().opt_def_id() else {
+                self.dcx().span_delayed_bug(path.span, "should have errored in resolve");
+                return None;
+            };
+            let Some(did) = did.as_local() else {
+                self.dcx().span_err(
+                    path.span,
+                    "only opaque types defined in the local crate can be defined",
+                );
+                return None;
+            };
+            Some((self.lower_span(path.span), did))
+        });
+        let define_opaque = self.arena.alloc_from_iter(define_opaque);
+        self.define_opaque = Some(define_opaque);
+    }
+
     pub(super) fn lower_generic_bound_predicate(
         &mut self,
         ident: Ident,
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 4cecc56909e..e5569458dbd 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -35,6 +35,7 @@
 #![doc(rust_logo)]
 #![feature(assert_matches)]
 #![feature(box_patterns)]
+#![feature(exact_size_is_empty)]
 #![feature(if_let_guard)]
 #![feature(let_chains)]
 #![feature(rustdoc_internals)]
@@ -97,6 +98,8 @@ struct LoweringContext<'a, 'hir> {
 
     /// Bodies inside the owner being lowered.
     bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>,
+    /// `#[define_opaque]` attributes
+    define_opaque: Option<&'hir [(Span, LocalDefId)]>,
     /// Attributes inside the owner being lowered.
     attrs: SortedMap<hir::ItemLocalId, &'hir [hir::Attribute]>,
     /// Collect items that were created by lowering the current owner.
@@ -154,6 +157,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
             // HirId handling.
             bodies: Vec::new(),
+            define_opaque: None,
             attrs: SortedMap::default(),
             children: Vec::default(),
             contract_ensures: None,
@@ -546,6 +550,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         let current_attrs = std::mem::take(&mut self.attrs);
         let current_bodies = std::mem::take(&mut self.bodies);
+        let current_define_opaque = std::mem::take(&mut self.define_opaque);
         let current_ident_and_label_to_local_id =
             std::mem::take(&mut self.ident_and_label_to_local_id);
 
@@ -579,6 +584,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
 
         self.attrs = current_attrs;
         self.bodies = current_bodies;
+        self.define_opaque = current_define_opaque;
         self.ident_and_label_to_local_id = current_ident_and_label_to_local_id;
 
         #[cfg(debug_assertions)]
@@ -598,6 +604,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
     fn make_owner_info(&mut self, node: hir::OwnerNode<'hir>) -> &'hir hir::OwnerInfo<'hir> {
         let attrs = std::mem::take(&mut self.attrs);
         let mut bodies = std::mem::take(&mut self.bodies);
+        let define_opaque = std::mem::take(&mut self.define_opaque);
         let trait_map = std::mem::take(&mut self.trait_map);
 
         #[cfg(debug_assertions)]
@@ -617,7 +624,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
         let num_nodes = self.item_local_id_counter.as_usize();
         let (nodes, parenting) = index::index_hir(self.tcx, node, &bodies, num_nodes);
         let nodes = hir::OwnerNodes { opt_hash_including_bodies, nodes, bodies };
-        let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash };
+        let attrs = hir::AttributeMap { map: attrs, opt_hash: attrs_hash, define_opaque };
 
         self.arena.alloc(hir::OwnerInfo { nodes, parenting, attrs, trait_map })
     }
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index f9f4035cb22..232d60be4eb 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -917,7 +917,10 @@ impl<'a> Visitor<'a> for AstValidator<'a> {
                 walk_list!(self, visit_attribute, &item.attrs);
                 return; // Avoid visiting again.
             }
-            ItemKind::Fn(func @ box Fn { defaultness, generics: _, sig, contract: _, body }) => {
+            ItemKind::Fn(
+                func
+                @ box Fn { defaultness, generics: _, sig, contract: _, body, define_opaque: _ },
+            ) => {
                 self.check_defaultness(item.span, *defaultness);
 
                 let is_intrinsic =
diff --git a/compiler/rustc_ast_pretty/src/pprust/state.rs b/compiler/rustc_ast_pretty/src/pprust/state.rs
index 01fc272a458..a8eaff7346b 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state.rs
@@ -24,7 +24,6 @@ use rustc_span::edition::Edition;
 use rustc_span::source_map::{SourceMap, Spanned};
 use rustc_span::symbol::IdentPrinter;
 use rustc_span::{BytePos, CharPos, DUMMY_SP, FileName, Ident, Pos, Span, Symbol, kw, sym};
-use thin_vec::ThinVec;
 
 use crate::pp::Breaks::{Consistent, Inconsistent};
 use crate::pp::{self, Breaks};
@@ -1978,15 +1977,7 @@ impl<'a> State<'a> {
     ) {
         self.ibox(INDENT_UNIT);
         self.print_formal_generic_params(generic_params);
-        let generics = ast::Generics {
-            params: ThinVec::new(),
-            where_clause: ast::WhereClause {
-                has_where_token: false,
-                predicates: ThinVec::new(),
-                span: DUMMY_SP,
-            },
-            span: DUMMY_SP,
-        };
+        let generics = ast::Generics::default();
         let header = ast::FnHeader { safety, ext, ..ast::FnHeader::default() };
         self.print_fn(decl, header, name, &generics);
         self.end();
diff --git a/compiler/rustc_ast_pretty/src/pprust/state/item.rs b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
index ced0cbd2fef..6236f8ecfb5 100644
--- a/compiler/rustc_ast_pretty/src/pprust/state/item.rs
+++ b/compiler/rustc_ast_pretty/src/pprust/state/item.rs
@@ -650,7 +650,16 @@ impl<'a> State<'a> {
         attrs: &[ast::Attribute],
         func: &ast::Fn,
     ) {
-        let ast::Fn { defaultness, generics, sig, contract, body } = func;
+        let ast::Fn { defaultness, generics, sig, contract, body, define_opaque } = func;
+
+        if let Some(define_opaque) = define_opaque {
+            for (_, path) in define_opaque {
+                self.word("define opaques from ");
+                self.print_path(path, false, 0);
+                self.word(",");
+            }
+        }
+
         if body.is_some() {
             self.head("");
         }
@@ -698,7 +707,7 @@ impl<'a> State<'a> {
         }
         self.print_generic_params(&generics.params);
         self.print_fn_params_and_ret(decl, false);
-        self.print_where_clause(&generics.where_clause)
+        self.print_where_clause(&generics.where_clause);
     }
 
     pub(crate) fn print_fn_params_and_ret(&mut self, decl: &ast::FnDecl, is_closure: bool) {
diff --git a/compiler/rustc_attr_data_structures/src/lib.rs b/compiler/rustc_attr_data_structures/src/lib.rs
index be00d1c10e0..bbd3308809c 100644
--- a/compiler/rustc_attr_data_structures/src/lib.rs
+++ b/compiler/rustc_attr_data_structures/src/lib.rs
@@ -34,13 +34,17 @@ pub trait HashStableContext: rustc_ast::HashStableContext + rustc_abi::HashStabl
 /// like [`Span`]s and empty tuples, are gracefully skipped so they don't clutter the
 /// representation much.
 pub trait PrintAttribute {
-    fn print_something(&self) -> bool;
+    /// Whether or not this will render as something meaningful, or if it's skipped
+    /// (which will force the containing struct to also skip printing a comma
+    /// and the field name).
+    fn should_render(&self) -> bool;
+
     fn print_attribute(&self, p: &mut Printer);
 }
 
 impl<T: PrintAttribute> PrintAttribute for &T {
-    fn print_something(&self) -> bool {
-        T::print_something(self)
+    fn should_render(&self) -> bool {
+        T::should_render(self)
     }
 
     fn print_attribute(&self, p: &mut Printer) {
@@ -48,9 +52,10 @@ impl<T: PrintAttribute> PrintAttribute for &T {
     }
 }
 impl<T: PrintAttribute> PrintAttribute for Option<T> {
-    fn print_something(&self) -> bool {
-        self.as_ref().is_some_and(|x| x.print_something())
+    fn should_render(&self) -> bool {
+        self.as_ref().is_some_and(|x| x.should_render())
     }
+
     fn print_attribute(&self, p: &mut Printer) {
         if let Some(i) = self {
             T::print_attribute(i, p)
@@ -58,9 +63,10 @@ impl<T: PrintAttribute> PrintAttribute for Option<T> {
     }
 }
 impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
-    fn print_something(&self) -> bool {
-        self.is_empty() || self[0].print_something()
+    fn should_render(&self) -> bool {
+        self.is_empty() || self[0].should_render()
     }
+
     fn print_attribute(&self, p: &mut Printer) {
         let mut last_printed = false;
         p.word("[");
@@ -69,7 +75,7 @@ impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
                 p.word_space(",");
             }
             i.print_attribute(p);
-            last_printed = i.print_something();
+            last_printed = i.should_render();
         }
         p.word("]");
     }
@@ -77,7 +83,7 @@ impl<T: PrintAttribute> PrintAttribute for ThinVec<T> {
 macro_rules! print_skip {
     ($($t: ty),* $(,)?) => {$(
         impl PrintAttribute for $t {
-            fn print_something(&self) -> bool { false }
+            fn should_render(&self) -> bool { false }
             fn print_attribute(&self, _: &mut Printer) { }
         })*
     };
@@ -86,7 +92,7 @@ macro_rules! print_skip {
 macro_rules! print_disp {
     ($($t: ty),* $(,)?) => {$(
         impl PrintAttribute for $t {
-            fn print_something(&self) -> bool { true }
+            fn should_render(&self) -> bool { true }
             fn print_attribute(&self, p: &mut Printer) {
                 p.word(format!("{}", self));
             }
@@ -96,7 +102,7 @@ macro_rules! print_disp {
 macro_rules! print_debug {
     ($($t: ty),* $(,)?) => {$(
         impl PrintAttribute for $t {
-            fn print_something(&self) -> bool { true }
+            fn should_render(&self) -> bool { true }
             fn print_attribute(&self, p: &mut Printer) {
                 p.word(format!("{:?}", self));
             }
@@ -105,37 +111,39 @@ macro_rules! print_debug {
 }
 
 macro_rules! print_tup {
-    (num_print_something $($ts: ident)*) => { 0 $(+ $ts.print_something() as usize)* };
+    (num_should_render $($ts: ident)*) => { 0 $(+ $ts.should_render() as usize)* };
     () => {};
     ($t: ident $($ts: ident)*) => {
         #[allow(non_snake_case, unused)]
         impl<$t: PrintAttribute, $($ts: PrintAttribute),*> PrintAttribute for ($t, $($ts),*) {
-            fn print_something(&self) -> bool {
+            fn should_render(&self) -> bool {
                 let ($t, $($ts),*) = self;
-                print_tup!(num_print_something $t $($ts)*) != 0
+                print_tup!(num_should_render $t $($ts)*) != 0
             }
 
             fn print_attribute(&self, p: &mut Printer) {
                 let ($t, $($ts),*) = self;
-                let parens = print_tup!(num_print_something $t $($ts)*) > 1;
+                let parens = print_tup!(num_should_render $t $($ts)*) > 1;
                 if parens {
-                    p.word("(");
+                    p.popen();
                 }
 
-                let mut printed_anything = $t.print_something();
+                let mut printed_anything = $t.should_render();
 
                 $t.print_attribute(p);
 
                 $(
-                    if printed_anything && $ts.print_something() {
-                        p.word_space(",");
+                    if $ts.should_render() {
+                        if printed_anything {
+                            p.word_space(",");
+                        }
                         printed_anything = true;
                     }
                     $ts.print_attribute(p);
                 )*
 
                 if parens {
-                    p.word(")");
+                    p.pclose();
                 }
             }
         }
@@ -146,8 +154,8 @@ macro_rules! print_tup {
 
 print_tup!(A B C D E F G H);
 print_skip!(Span, ());
-print_disp!(Symbol, u16, bool, NonZero<u32>);
-print_debug!(UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
+print_disp!(u16, bool, NonZero<u32>);
+print_debug!(Symbol, UintTy, IntTy, Align, AttrStyle, CommentKind, Transparency);
 
 /// Finds attributes in sequences of attributes by pattern matching.
 ///
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index 0e6b0bab082..35541bb04bd 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -9,7 +9,6 @@ use rustc_errors::{DiagCtxtHandle, Diagnostic};
 use rustc_feature::Features;
 use rustc_hir::{AttrArgs, AttrItem, AttrPath, Attribute, HashIgnoredAttrId};
 use rustc_session::Session;
-use rustc_span::symbol::kw;
 use rustc_span::{DUMMY_SP, ErrorGuaranteed, Span, Symbol, sym};
 
 use crate::attributes::allow_unstable::{AllowConstFnUnstableParser, AllowInternalUnstableParser};
@@ -338,7 +337,7 @@ impl<'sess> AttributeParser<'sess> {
                         "expr in place where literal is expected (builtin attr parsing)",
                     );
                     ast::MetaItemLit {
-                        symbol: kw::Empty,
+                        symbol: sym::dummy,
                         suffix: None,
                         kind: ast::LitKind::Err(guar),
                         span: DUMMY_SP,
diff --git a/compiler/rustc_attr_parsing/src/parser.rs b/compiler/rustc_attr_parsing/src/parser.rs
index f0cce26f4e2..a8a1460591c 100644
--- a/compiler/rustc_attr_parsing/src/parser.rs
+++ b/compiler/rustc_attr_parsing/src/parser.rs
@@ -12,7 +12,7 @@ use rustc_ast::{AttrArgs, DelimArgs, Expr, ExprKind, LitKind, MetaItemLit, Norma
 use rustc_ast_pretty::pprust;
 use rustc_errors::DiagCtxtHandle;
 use rustc_hir::{self as hir, AttrPath};
-use rustc_span::symbol::{Ident, kw};
+use rustc_span::symbol::{Ident, kw, sym};
 use rustc_span::{ErrorGuaranteed, Span, Symbol};
 
 pub struct SegmentIterator<'a> {
@@ -360,7 +360,7 @@ fn expr_to_lit(dcx: DiagCtxtHandle<'_>, expr: &Expr, span: Span) -> MetaItemLit
             span,
             "expr in place where literal is expected (builtin attr parsing)",
         );
-        MetaItemLit { symbol: kw::Empty, suffix: None, kind: LitKind::Err(guar), span }
+        MetaItemLit { symbol: sym::dummy, suffix: None, kind: LitKind::Err(guar), span }
     }
 }
 
diff --git a/compiler/rustc_borrowck/src/type_check/input_output.rs b/compiler/rustc_borrowck/src/type_check/input_output.rs
index f70b17e3362..c6b29fe36fd 100644
--- a/compiler/rustc_borrowck/src/type_check/input_output.rs
+++ b/compiler/rustc_borrowck/src/type_check/input_output.rs
@@ -24,9 +24,9 @@ use crate::universal_regions::DefiningTy;
 impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// Check explicit closure signature annotation,
     /// e.g., `|x: FxIndexMap<_, &'static u32>| ...`.
-    #[instrument(skip(self, body), level = "debug")]
-    pub(super) fn check_signature_annotation(&mut self, body: &Body<'tcx>) {
-        let mir_def_id = body.source.def_id().expect_local();
+    #[instrument(skip(self), level = "debug")]
+    pub(super) fn check_signature_annotation(&mut self) {
+        let mir_def_id = self.body.source.def_id().expect_local();
 
         if !self.tcx().is_closure_like(mir_def_id.to_def_id()) {
             return;
@@ -38,9 +38,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         // (e.g., the `_` in the code above) with fresh variables.
         // Then replace the bound items in the fn sig with fresh variables,
         // so that they represent the view from "inside" the closure.
-        let user_provided_sig = self.instantiate_canonical(body.span, &user_provided_poly_sig);
+        let user_provided_sig = self.instantiate_canonical(self.body.span, &user_provided_poly_sig);
         let mut user_provided_sig = self.infcx.instantiate_binder_with_fresh_vars(
-            body.span,
+            self.body.span,
             BoundRegionConversionTime::FnCall,
             user_provided_sig,
         );
@@ -66,12 +66,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 Ty::new_tup(self.tcx(), user_provided_sig.inputs()),
                 args.tupled_upvars_ty(),
                 args.coroutine_captures_by_ref_ty(),
-                self.infcx.next_region_var(RegionVariableOrigin::MiscVariable(body.span), || {
-                    RegionCtxt::Unknown
-                }),
+                self.infcx
+                    .next_region_var(RegionVariableOrigin::MiscVariable(self.body.span), || {
+                        RegionCtxt::Unknown
+                    }),
             );
 
-            let next_ty_var = || self.infcx.next_ty_var(body.span);
+            let next_ty_var = || self.infcx.next_ty_var(self.body.span);
             let output_ty = Ty::new_coroutine(
                 self.tcx(),
                 self.tcx().coroutine_for_closure(mir_def_id),
@@ -107,9 +108,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         for (&user_ty, arg_decl) in user_provided_sig.inputs().iter().zip_eq(
             // In MIR, closure args begin with an implicit `self`.
             // Also, coroutines have a resume type which may be implicitly `()`.
-            body.args_iter()
+            self.body
+                .args_iter()
                 .skip(1 + if is_coroutine_with_implicit_resume_ty { 1 } else { 0 })
-                .map(|local| &body.local_decls[local]),
+                .map(|local| &self.body.local_decls[local]),
         ) {
             self.ascribe_user_type_skip_wf(
                 arg_decl.ty,
@@ -119,7 +121,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
 
         // If the user explicitly annotated the output type, enforce it.
-        let output_decl = &body.local_decls[RETURN_PLACE];
+        let output_decl = &self.body.local_decls[RETURN_PLACE];
         self.ascribe_user_type_skip_wf(
             output_decl.ty,
             ty::UserType::new(ty::UserTypeKind::Ty(user_provided_sig.output())),
@@ -127,12 +129,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         );
     }
 
-    #[instrument(skip(self, body), level = "debug")]
-    pub(super) fn equate_inputs_and_outputs(
-        &mut self,
-        body: &Body<'tcx>,
-        normalized_inputs_and_output: &[Ty<'tcx>],
-    ) {
+    #[instrument(skip(self), level = "debug")]
+    pub(super) fn equate_inputs_and_outputs(&mut self, normalized_inputs_and_output: &[Ty<'tcx>]) {
         let (&normalized_output_ty, normalized_input_tys) =
             normalized_inputs_and_output.split_last().unwrap();
 
@@ -141,18 +139,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
         // Equate expected input tys with those in the MIR.
         for (argument_index, &normalized_input_ty) in normalized_input_tys.iter().enumerate() {
-            if argument_index + 1 >= body.local_decls.len() {
+            if argument_index + 1 >= self.body.local_decls.len() {
                 self.tcx()
                     .dcx()
-                    .span_bug(body.span, "found more normalized_input_ty than local_decls");
+                    .span_bug(self.body.span, "found more normalized_input_ty than local_decls");
             }
 
             // In MIR, argument N is stored in local N+1.
             let local = Local::from_usize(argument_index + 1);
 
-            let mir_input_ty = body.local_decls[local].ty;
+            let mir_input_ty = self.body.local_decls[local].ty;
 
-            let mir_input_span = body.local_decls[local].source_info.span;
+            let mir_input_span = self.body.local_decls[local].source_info.span;
             self.equate_normalized_input_or_output(
                 normalized_input_ty,
                 mir_input_ty,
@@ -160,8 +158,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             );
         }
 
-        if let Some(mir_yield_ty) = body.yield_ty() {
-            let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
+        if let Some(mir_yield_ty) = self.body.yield_ty() {
+            let yield_span = self.body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
                 self.universal_regions.yield_ty.unwrap(),
                 mir_yield_ty,
@@ -169,8 +167,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             );
         }
 
-        if let Some(mir_resume_ty) = body.resume_ty() {
-            let yield_span = body.local_decls[RETURN_PLACE].source_info.span;
+        if let Some(mir_resume_ty) = self.body.resume_ty() {
+            let yield_span = self.body.local_decls[RETURN_PLACE].source_info.span;
             self.equate_normalized_input_or_output(
                 self.universal_regions.resume_ty.unwrap(),
                 mir_resume_ty,
@@ -179,8 +177,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
 
         // Return types are a bit more complex. They may contain opaque `impl Trait` types.
-        let mir_output_ty = body.local_decls[RETURN_PLACE].ty;
-        let output_span = body.local_decls[RETURN_PLACE].source_info.span;
+        let mir_output_ty = self.body.local_decls[RETURN_PLACE].ty;
+        let output_span = self.body.local_decls[RETURN_PLACE].source_info.span;
         self.equate_normalized_input_or_output(normalized_output_ty, mir_output_ty, output_span);
     }
 
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
index dcc17903002..f17ad23f4bf 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/mod.rs
@@ -31,7 +31,6 @@ mod trace;
 /// performed before
 pub(super) fn generate<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    body: &Body<'tcx>,
     location_map: &DenseLocationMap,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
@@ -51,23 +50,16 @@ pub(super) fn generate<'a, 'tcx>(
     // We do record these regions in the polonius context, since they're used to differentiate
     // relevant and boring locals, which is a key distinction used later in diagnostics.
     if typeck.tcx().sess.opts.unstable_opts.polonius.is_next_enabled() {
-        let (_, boring_locals) = compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
+        let (_, boring_locals) =
+            compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
         typeck.polonius_liveness.as_mut().unwrap().boring_nll_locals =
             boring_locals.into_iter().collect();
         free_regions = typeck.universal_regions.universal_regions_iter().collect();
     }
     let (relevant_live_locals, boring_locals) =
-        compute_relevant_live_locals(typeck.tcx(), &free_regions, body);
-
-    trace::trace(
-        typeck,
-        body,
-        location_map,
-        flow_inits,
-        move_data,
-        relevant_live_locals,
-        boring_locals,
-    );
+        compute_relevant_live_locals(typeck.tcx(), &free_regions, typeck.body);
+
+    trace::trace(typeck, location_map, flow_inits, move_data, relevant_live_locals, boring_locals);
 
     // Mark regions that should be live where they appear within rvalues or within a call: like
     // args, regions, and types.
@@ -76,7 +68,7 @@ pub(super) fn generate<'a, 'tcx>(
         &mut typeck.constraints.liveness_constraints,
         &typeck.universal_regions,
         &mut typeck.polonius_liveness,
-        body,
+        typeck.body,
     );
 }
 
diff --git a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
index dc35d5eb89c..7718644b9a9 100644
--- a/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
+++ b/compiler/rustc_borrowck/src/type_check/liveness/trace.rs
@@ -39,17 +39,15 @@ use crate::type_check::{NormalizeLocation, TypeChecker};
 /// this respects `#[may_dangle]` annotations).
 pub(super) fn trace<'a, 'tcx>(
     typeck: &mut TypeChecker<'_, 'tcx>,
-    body: &Body<'tcx>,
     location_map: &DenseLocationMap,
     flow_inits: ResultsCursor<'a, 'tcx, MaybeInitializedPlaces<'a, 'tcx>>,
     move_data: &MoveData<'tcx>,
     relevant_live_locals: Vec<Local>,
     boring_locals: Vec<Local>,
 ) {
-    let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, body);
+    let local_use_map = &LocalUseMap::build(&relevant_live_locals, location_map, typeck.body);
     let cx = LivenessContext {
         typeck,
-        body,
         flow_inits,
         location_map,
         local_use_map,
@@ -69,14 +67,13 @@ pub(super) fn trace<'a, 'tcx>(
 /// Contextual state for the type-liveness coroutine.
 struct LivenessContext<'a, 'typeck, 'b, 'tcx> {
     /// Current type-checker, giving us our inference context etc.
+    ///
+    /// This also stores the body we're currently analyzing.
     typeck: &'a mut TypeChecker<'typeck, 'tcx>,
 
     /// Defines the `PointIndex` mapping
     location_map: &'a DenseLocationMap,
 
-    /// MIR we are analyzing.
-    body: &'a Body<'tcx>,
-
     /// Mapping to/from the various indices used for initialization tracking.
     move_data: &'a MoveData<'tcx>,
 
@@ -139,7 +136,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
             self.compute_use_live_points_for(local);
             self.compute_drop_live_points_for(local);
 
-            let local_ty = self.cx.body.local_decls[local].ty;
+            let local_ty = self.cx.body().local_decls[local].ty;
 
             if !self.use_live_at.is_empty() {
                 self.cx.add_use_live_facts_for(local_ty, &self.use_live_at);
@@ -164,8 +161,8 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
     /// and can therefore safely be dropped.
     fn dropck_boring_locals(&mut self, boring_locals: Vec<Local>) {
         for local in boring_locals {
-            let local_ty = self.cx.body.local_decls[local].ty;
-            let local_span = self.cx.body.local_decls[local].source_info.span;
+            let local_ty = self.cx.body().local_decls[local].ty;
+            let local_span = self.cx.body().local_decls[local].source_info.span;
             let drop_data = self.cx.drop_data.entry(local_ty).or_insert_with({
                 let typeck = &self.cx.typeck;
                 move || LivenessContext::compute_drop_data(typeck, local_ty, local_span)
@@ -173,7 +170,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
 
             drop_data.dropck_result.report_overflows(
                 self.cx.typeck.infcx.tcx,
-                self.cx.body.local_decls[local].source_info.span,
+                self.cx.typeck.body.local_decls[local].source_info.span,
                 local_ty,
             );
         }
@@ -202,7 +199,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                 .var_dropped_at
                 .iter()
                 .filter_map(|&(local, location_index)| {
-                    let local_ty = self.cx.body.local_decls[local].ty;
+                    let local_ty = self.cx.body().local_decls[local].ty;
                     if relevant_live_locals.contains(&local) || !local_ty.has_free_regions() {
                         return None;
                     }
@@ -278,9 +275,9 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
 
                 let block = self.cx.location_map.to_location(block_start).block;
                 self.stack.extend(
-                    self.cx.body.basic_blocks.predecessors()[block]
+                    self.cx.body().basic_blocks.predecessors()[block]
                         .iter()
-                        .map(|&pred_bb| self.cx.body.terminator_loc(pred_bb))
+                        .map(|&pred_bb| self.cx.body().terminator_loc(pred_bb))
                         .map(|pred_loc| self.cx.location_map.point_from_location(pred_loc)),
                 );
             }
@@ -305,7 +302,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
         // Find the drops where `local` is initialized.
         for drop_point in self.cx.local_use_map.drops(local) {
             let location = self.cx.location_map.to_location(drop_point);
-            debug_assert_eq!(self.cx.body.terminator_loc(location.block), location,);
+            debug_assert_eq!(self.cx.body().terminator_loc(location.block), location,);
 
             if self.cx.initialized_at_terminator(location.block, mpi)
                 && self.drop_live_at.insert(drop_point)
@@ -351,7 +348,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
         // block. One of them may be either a definition or use
         // live point.
         let term_location = self.cx.location_map.to_location(term_point);
-        debug_assert_eq!(self.cx.body.terminator_loc(term_location.block), term_location,);
+        debug_assert_eq!(self.cx.body().terminator_loc(term_location.block), term_location,);
         let block = term_location.block;
         let entry_point = self.cx.location_map.entry_point(term_location.block);
         for p in (entry_point..term_point).rev() {
@@ -376,7 +373,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
             }
         }
 
-        let body = self.cx.body;
+        let body = self.cx.typeck.body;
         for &pred_block in body.basic_blocks.predecessors()[block].iter() {
             debug!("compute_drop_live_points_for_block: pred_block = {:?}", pred_block,);
 
@@ -403,7 +400,7 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
                 continue;
             }
 
-            let pred_term_loc = self.cx.body.terminator_loc(pred_block);
+            let pred_term_loc = self.cx.body().terminator_loc(pred_block);
             let pred_term_point = self.cx.location_map.point_from_location(pred_term_loc);
 
             // If the terminator of this predecessor either *assigns*
@@ -463,6 +460,9 @@ impl<'a, 'typeck, 'b, 'tcx> LivenessResults<'a, 'typeck, 'b, 'tcx> {
 }
 
 impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
+    fn body(&self) -> &Body<'tcx> {
+        self.typeck.body
+    }
     /// Returns `true` if the local variable (or some part of it) is initialized at the current
     /// cursor position. Callers should call one of the `seek` methods immediately before to point
     /// the cursor to the desired location.
@@ -481,7 +481,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// DROP of some local variable will have an effect -- note that
     /// drops, as they may unwind, are always terminators.
     fn initialized_at_terminator(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
-        self.flow_inits.seek_before_primary_effect(self.body.terminator_loc(block));
+        self.flow_inits.seek_before_primary_effect(self.body().terminator_loc(block));
         self.initialized_at_curr_loc(mpi)
     }
 
@@ -491,7 +491,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
     /// **Warning:** Does not account for the result of `Call`
     /// instructions.
     fn initialized_at_exit(&mut self, block: BasicBlock, mpi: MovePathIndex) -> bool {
-        self.flow_inits.seek_after_primary_effect(self.body.terminator_loc(block));
+        self.flow_inits.seek_after_primary_effect(self.body().terminator_loc(block));
         self.initialized_at_curr_loc(mpi)
     }
 
@@ -526,7 +526,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             values::pretty_print_points(self.location_map, live_at.iter()),
         );
 
-        let local_span = self.body.local_decls()[dropped_local].source_info.span;
+        let local_span = self.body().local_decls()[dropped_local].source_info.span;
         let drop_data = self.drop_data.entry(dropped_ty).or_insert_with({
             let typeck = &self.typeck;
             move || Self::compute_drop_data(typeck, dropped_ty, local_span)
@@ -544,7 +544,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
 
         drop_data.dropck_result.report_overflows(
             self.typeck.infcx.tcx,
-            self.body.source_info(*drop_locations.first().unwrap()).span,
+            self.typeck.body.source_info(*drop_locations.first().unwrap()).span,
             dropped_ty,
         );
 
@@ -610,7 +610,7 @@ impl<'tcx> LivenessContext<'_, '_, '_, 'tcx> {
             Err(ErrorGuaranteed { .. }) => {
                 // We don't run dropck on HIR, and dropck looks inside fields of
                 // types, so there's no guarantee that it succeeds. We also
-                // can't rely on the the `ErrorGuaranteed` from `fully_perform` here
+                // can't rely on the `ErrorGuaranteed` from `fully_perform` here
                 // because it comes from delay_span_bug.
                 //
                 // Do this inside of a probe because we don't particularly care (or want)
diff --git a/compiler/rustc_borrowck/src/type_check/mod.rs b/compiler/rustc_borrowck/src/type_check/mod.rs
index c1e23cb5411..9d5022f2bef 100644
--- a/compiler/rustc_borrowck/src/type_check/mod.rs
+++ b/compiler/rustc_borrowck/src/type_check/mod.rs
@@ -174,11 +174,11 @@ pub(crate) fn type_check<'a, 'tcx>(
     let mut verifier = TypeVerifier { typeck: &mut typeck, promoted, last_span: body.span };
     verifier.visit_body(body);
 
-    typeck.typeck_mir(body);
-    typeck.equate_inputs_and_outputs(body, &normalized_inputs_and_output);
-    typeck.check_signature_annotation(body);
+    typeck.typeck_mir();
+    typeck.equate_inputs_and_outputs(&normalized_inputs_and_output);
+    typeck.check_signature_annotation();
 
-    liveness::generate(&mut typeck, body, &location_map, flow_inits, move_data);
+    liveness::generate(&mut typeck, &location_map, flow_inits, move_data);
 
     let opaque_type_values =
         opaque_types::take_opaques_and_register_member_constraints(&mut typeck);
@@ -485,6 +485,7 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
 
     #[instrument(level = "debug", skip(self))]
     fn visit_body(&mut self, body: &Body<'tcx>) {
+        debug_assert!(std::ptr::eq(self.typeck.body, body));
         // We intentionally do not recurse into `body.required_consts` or
         // `body.mentioned_items` here as the MIR at this phase should still
         // refer to all items and we don't want to check them multiple times.
@@ -542,7 +543,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
 
         self.visit_body(promoted_body);
 
-        self.typeck.typeck_mir(promoted_body);
+        self.typeck.typeck_mir();
 
         self.typeck.body = parent_body;
         // Merge the outlives constraints back in, at the given location.
@@ -892,8 +893,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         self.infcx.tcx
     }
 
-    #[instrument(skip(self, body), level = "debug")]
-    fn check_stmt(&mut self, body: &Body<'tcx>, stmt: &Statement<'tcx>, location: Location) {
+    #[instrument(skip(self), level = "debug")]
+    fn check_stmt(&mut self, stmt: &Statement<'tcx>, location: Location) {
         let tcx = self.tcx();
         debug!("stmt kind: {:?}", stmt.kind);
         match &stmt.kind {
@@ -916,11 +917,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     Some(l)
-                        if matches!(body.local_decls[l].local_info(), LocalInfo::AggregateTemp) =>
+                        if matches!(
+                            self.body.local_decls[l].local_info(),
+                            LocalInfo::AggregateTemp
+                        ) =>
                     {
                         ConstraintCategory::Usage
                     }
-                    Some(l) if !body.local_decls[l].is_user_variable() => {
+                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
                     _ => ConstraintCategory::Assignment,
@@ -928,14 +932,14 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 debug!(
                     "assignment category: {:?} {:?}",
                     category,
-                    place.as_local().map(|l| &body.local_decls[l])
+                    place.as_local().map(|l| &self.body.local_decls[l])
                 );
 
-                let place_ty = place.ty(body, tcx).ty;
+                let place_ty = place.ty(self.body, tcx).ty;
                 debug!(?place_ty);
                 let place_ty = self.normalize(place_ty, location);
                 debug!("place_ty normalized: {:?}", place_ty);
-                let rv_ty = rv.ty(body, tcx);
+                let rv_ty = rv.ty(self.body, tcx);
                 debug!(?rv_ty);
                 let rv_ty = self.normalize(rv_ty, location);
                 debug!("normalized rv_ty: {:?}", rv_ty);
@@ -972,7 +976,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
                 }
 
-                self.check_rvalue(body, rv, location);
+                self.check_rvalue(rv, location);
                 if !self.unsized_feature_enabled() {
                     let trait_ref = ty::TraitRef::new(
                         tcx,
@@ -987,7 +991,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
             }
             StatementKind::AscribeUserType(box (place, projection), variance) => {
-                let place_ty = place.ty(body, tcx).ty;
+                let place_ty = place.ty(self.body, tcx).ty;
                 if let Err(terr) = self.relate_type_and_user_type(
                     place_ty,
                     *variance,
@@ -1029,13 +1033,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    #[instrument(skip(self, body, term_location), level = "debug")]
-    fn check_terminator(
-        &mut self,
-        body: &Body<'tcx>,
-        term: &Terminator<'tcx>,
-        term_location: Location,
-    ) {
+    #[instrument(skip(self, term_location), level = "debug")]
+    fn check_terminator(&mut self, term: &Terminator<'tcx>, term_location: Location) {
         let tcx = self.tcx();
         debug!("terminator kind: {:?}", term.kind);
         match &term.kind {
@@ -1055,7 +1054,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             TerminatorKind::SwitchInt { discr, .. } => {
                 self.check_operand(discr, term_location);
 
-                let switch_ty = discr.ty(body, tcx);
+                let switch_ty = discr.ty(self.body, tcx);
                 if !switch_ty.is_integral() && !switch_ty.is_char() && !switch_ty.is_bool() {
                     span_mirbug!(self, term, "bad SwitchInt discr ty {:?}", switch_ty);
                 }
@@ -1074,7 +1073,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.check_operand(&arg.node, term_location);
                 }
 
-                let func_ty = func.ty(body, tcx);
+                let func_ty = func.ty(self.body, tcx);
                 debug!("func_ty.kind: {:?}", func_ty.kind());
 
                 let sig = match func_ty.kind() {
@@ -1142,7 +1141,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 }
 
                 if let TerminatorKind::Call { destination, target, .. } = term.kind {
-                    self.check_call_dest(body, term, &sig, destination, target, term_location);
+                    self.check_call_dest(term, &sig, destination, target, term_location);
                 }
 
                 // The ordinary liveness rules will ensure that all
@@ -1157,21 +1156,21 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     self.constraints.liveness_constraints.add_location(region_vid, term_location);
                 }
 
-                self.check_call_inputs(body, term, func, &sig, args, term_location, call_source);
+                self.check_call_inputs(term, func, &sig, args, term_location, call_source);
             }
             TerminatorKind::Assert { cond, msg, .. } => {
                 self.check_operand(cond, term_location);
 
-                let cond_ty = cond.ty(body, tcx);
+                let cond_ty = cond.ty(self.body, tcx);
                 if cond_ty != tcx.types.bool {
                     span_mirbug!(self, term, "bad Assert ({:?}, not bool", cond_ty);
                 }
 
                 if let AssertKind::BoundsCheck { len, index } = &**msg {
-                    if len.ty(body, tcx) != tcx.types.usize {
+                    if len.ty(self.body, tcx) != tcx.types.usize {
                         span_mirbug!(self, len, "bounds-check length non-usize {:?}", len)
                     }
-                    if index.ty(body, tcx) != tcx.types.usize {
+                    if index.ty(self.body, tcx) != tcx.types.usize {
                         span_mirbug!(self, index, "bounds-check index non-usize {:?}", index)
                     }
                 }
@@ -1179,10 +1178,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             TerminatorKind::Yield { value, resume_arg, .. } => {
                 self.check_operand(value, term_location);
 
-                match body.yield_ty() {
+                match self.body.yield_ty() {
                     None => span_mirbug!(self, term, "yield in non-coroutine"),
                     Some(ty) => {
-                        let value_ty = value.ty(body, tcx);
+                        let value_ty = value.ty(self.body, tcx);
                         if let Err(terr) = self.sub_types(
                             value_ty,
                             ty,
@@ -1201,10 +1200,10 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
                 }
 
-                match body.resume_ty() {
+                match self.body.resume_ty() {
                     None => span_mirbug!(self, term, "yield in non-coroutine"),
                     Some(ty) => {
-                        let resume_ty = resume_arg.ty(body, tcx);
+                        let resume_ty = resume_arg.ty(self.body, tcx);
                         if let Err(terr) = self.sub_types(
                             ty,
                             resume_ty.ty,
@@ -1228,7 +1227,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
     fn check_call_dest(
         &mut self,
-        body: &Body<'tcx>,
         term: &Terminator<'tcx>,
         sig: &ty::FnSig<'tcx>,
         destination: Place<'tcx>,
@@ -1238,7 +1236,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let tcx = self.tcx();
         match target {
             Some(_) => {
-                let dest_ty = destination.ty(body, tcx).ty;
+                let dest_ty = destination.ty(self.body, tcx).ty;
                 let dest_ty = self.normalize(dest_ty, term_location);
                 let category = match destination.as_local() {
                     Some(RETURN_PLACE) => {
@@ -1254,7 +1252,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             ConstraintCategory::Return(ReturnConstraint::Normal)
                         }
                     }
-                    Some(l) if !body.local_decls[l].is_user_variable() => {
+                    Some(l) if !self.body.local_decls[l].is_user_variable() => {
                         ConstraintCategory::Boring
                     }
                     // The return type of a call is interesting for diagnostics.
@@ -1295,10 +1293,9 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    #[instrument(level = "debug", skip(self, body, term, func, term_location, call_source))]
+    #[instrument(level = "debug", skip(self, term, func, term_location, call_source))]
     fn check_call_inputs(
         &mut self,
-        body: &Body<'tcx>,
         term: &Terminator<'tcx>,
         func: &Operand<'tcx>,
         sig: &ty::FnSig<'tcx>,
@@ -1310,7 +1307,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             span_mirbug!(self, term, "call to {:?} with wrong # of args", sig);
         }
 
-        let func_ty = func.ty(body, self.infcx.tcx);
+        let func_ty = func.ty(self.body, self.infcx.tcx);
         if let ty::FnDef(def_id, _) = *func_ty.kind() {
             // Some of the SIMD intrinsics are special: they need a particular argument to be a
             // constant. (Eventually this should use const-generics, but those are not up for the
@@ -1334,7 +1331,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         debug!(?func_ty);
 
         for (n, (fn_arg, op_arg)) in iter::zip(sig.inputs(), args).enumerate() {
-            let op_arg_ty = op_arg.node.ty(body, self.tcx());
+            let op_arg_ty = op_arg.node.ty(self.body, self.tcx());
 
             let op_arg_ty = self.normalize(op_arg_ty, term_location);
             let category = if call_source.from_hir_call() {
@@ -1358,16 +1355,16 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    fn check_iscleanup(&mut self, body: &Body<'tcx>, block_data: &BasicBlockData<'tcx>) {
+    fn check_iscleanup(&mut self, block_data: &BasicBlockData<'tcx>) {
         let is_cleanup = block_data.is_cleanup;
         self.last_span = block_data.terminator().source_info.span;
         match block_data.terminator().kind {
             TerminatorKind::Goto { target } => {
-                self.assert_iscleanup(body, block_data, target, is_cleanup)
+                self.assert_iscleanup(block_data, target, is_cleanup)
             }
             TerminatorKind::SwitchInt { ref targets, .. } => {
                 for target in targets.all_targets() {
-                    self.assert_iscleanup(body, block_data, *target, is_cleanup);
+                    self.assert_iscleanup(block_data, *target, is_cleanup);
                 }
             }
             TerminatorKind::UnwindResume => {
@@ -1399,55 +1396,48 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 if is_cleanup {
                     span_mirbug!(self, block_data, "yield in cleanup block")
                 }
-                self.assert_iscleanup(body, block_data, resume, is_cleanup);
+                self.assert_iscleanup(block_data, resume, is_cleanup);
                 if let Some(drop) = drop {
-                    self.assert_iscleanup(body, block_data, drop, is_cleanup);
+                    self.assert_iscleanup(block_data, drop, is_cleanup);
                 }
             }
             TerminatorKind::Unreachable => {}
             TerminatorKind::Drop { target, unwind, .. }
             | TerminatorKind::Assert { target, unwind, .. } => {
-                self.assert_iscleanup(body, block_data, target, is_cleanup);
-                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
+                self.assert_iscleanup(block_data, target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
             }
             TerminatorKind::Call { ref target, unwind, .. } => {
                 if let &Some(target) = target {
-                    self.assert_iscleanup(body, block_data, target, is_cleanup);
+                    self.assert_iscleanup(block_data, target, is_cleanup);
                 }
-                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
             }
             TerminatorKind::FalseEdge { real_target, imaginary_target } => {
-                self.assert_iscleanup(body, block_data, real_target, is_cleanup);
-                self.assert_iscleanup(body, block_data, imaginary_target, is_cleanup);
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup(block_data, imaginary_target, is_cleanup);
             }
             TerminatorKind::FalseUnwind { real_target, unwind } => {
-                self.assert_iscleanup(body, block_data, real_target, is_cleanup);
-                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
+                self.assert_iscleanup(block_data, real_target, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
             }
             TerminatorKind::InlineAsm { ref targets, unwind, .. } => {
                 for &target in targets {
-                    self.assert_iscleanup(body, block_data, target, is_cleanup);
+                    self.assert_iscleanup(block_data, target, is_cleanup);
                 }
-                self.assert_iscleanup_unwind(body, block_data, unwind, is_cleanup);
+                self.assert_iscleanup_unwind(block_data, unwind, is_cleanup);
             }
         }
     }
 
-    fn assert_iscleanup(
-        &mut self,
-        body: &Body<'tcx>,
-        ctxt: &dyn fmt::Debug,
-        bb: BasicBlock,
-        iscleanuppad: bool,
-    ) {
-        if body[bb].is_cleanup != iscleanuppad {
+    fn assert_iscleanup(&mut self, ctxt: &dyn fmt::Debug, bb: BasicBlock, iscleanuppad: bool) {
+        if self.body[bb].is_cleanup != iscleanuppad {
             span_mirbug!(self, ctxt, "cleanuppad mismatch: {:?} should be {:?}", bb, iscleanuppad);
         }
     }
 
     fn assert_iscleanup_unwind(
         &mut self,
-        body: &Body<'tcx>,
         ctxt: &dyn fmt::Debug,
         unwind: UnwindAction,
         is_cleanup: bool,
@@ -1457,7 +1447,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 if is_cleanup {
                     span_mirbug!(self, ctxt, "unwind on cleanup block")
                 }
-                self.assert_iscleanup(body, ctxt, unwind, true);
+                self.assert_iscleanup(ctxt, unwind, true);
             }
             UnwindAction::Continue => {
                 if is_cleanup {
@@ -1468,8 +1458,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    fn check_local(&mut self, body: &Body<'tcx>, local: Local, local_decl: &LocalDecl<'tcx>) {
-        match body.local_kind(local) {
+    fn check_local(&mut self, local: Local, local_decl: &LocalDecl<'tcx>) {
+        match self.body.local_kind(local) {
             LocalKind::ReturnPointer | LocalKind::Arg => {
                 // return values of normal functions are required to be
                 // sized by typeck, but return values of ADT constructors are
@@ -1598,23 +1588,23 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    #[instrument(skip(self, body), level = "debug")]
-    fn check_rvalue(&mut self, body: &Body<'tcx>, rvalue: &Rvalue<'tcx>, location: Location) {
+    #[instrument(skip(self), level = "debug")]
+    fn check_rvalue(&mut self, rvalue: &Rvalue<'tcx>, location: Location) {
         let tcx = self.tcx();
-        let span = body.source_info(location).span;
+        let span = self.body.source_info(location).span;
 
         match rvalue {
             Rvalue::Aggregate(ak, ops) => {
                 for op in ops {
                     self.check_operand(op, location);
                 }
-                self.check_aggregate_rvalue(body, rvalue, ak, ops, location)
+                self.check_aggregate_rvalue(rvalue, ak, ops, location)
             }
 
             Rvalue::Repeat(operand, len) => {
                 self.check_operand(operand, location);
 
-                let array_ty = rvalue.ty(body.local_decls(), tcx);
+                let array_ty = rvalue.ty(self.body.local_decls(), tcx);
                 self.prove_predicate(
                     ty::PredicateKind::Clause(ty::ClauseKind::WellFormed(array_ty.into())),
                     Locations::Single(location),
@@ -1633,7 +1623,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                         Operand::Move(place) => {
                             // Make sure that repeated elements implement `Copy`.
-                            let ty = place.ty(body, tcx).ty;
+                            let ty = place.ty(self.body, tcx).ty;
                             let trait_ref = ty::TraitRef::new(
                                 tcx,
                                 tcx.require_lang_item(LangItem::Copy, Some(span)),
@@ -1688,7 +1678,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 match *cast_kind {
                     CastKind::PointerCoercion(PointerCoercion::ReifyFnPointer, coercion_source) => {
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
-                        let src_ty = op.ty(body, tcx);
+                        let src_ty = op.ty(self.body, tcx);
                         let mut src_sig = src_ty.fn_sig(tcx);
                         if let ty::FnDef(def_id, _) = src_ty.kind()
                             && let ty::FnPtr(_, target_hdr) = *ty.kind()
@@ -1697,7 +1687,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             && let Some(safe_sig) = tcx.adjust_target_feature_sig(
                                 *def_id,
                                 src_sig,
-                                body.source.def_id(),
+                                self.body.source.def_id(),
                             )
                         {
                             src_sig = safe_sig;
@@ -1790,7 +1780,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         PointerCoercion::ClosureFnPointer(safety),
                         coercion_source,
                     ) => {
-                        let sig = match op.ty(body, tcx).kind() {
+                        let sig = match op.ty(self.body, tcx).kind() {
                             ty::Closure(_, args) => args.as_closure().sig(),
                             _ => bug!(),
                         };
@@ -1819,7 +1809,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         PointerCoercion::UnsafeFnPointer,
                         coercion_source,
                     ) => {
-                        let fn_sig = op.ty(body, tcx).fn_sig(tcx);
+                        let fn_sig = op.ty(self.body, tcx).fn_sig(tcx);
 
                         // The type that we see in the fcx is like
                         // `foo::<'a, 'b>`, where `foo` is the path to a
@@ -1853,7 +1843,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         let trait_ref = ty::TraitRef::new(
                             tcx,
                             tcx.require_lang_item(LangItem::CoerceUnsized, Some(span)),
-                            [op.ty(body, tcx), ty],
+                            [op.ty(self.body, tcx), ty],
                         );
 
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
@@ -1879,7 +1869,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                             _ => panic!("Invalid dyn* cast_ty"),
                         };
 
-                        let self_ty = op.ty(body, tcx);
+                        let self_ty = op.ty(self.body, tcx);
 
                         let is_implicit_coercion = coercion_source == CoercionSource::Implicit;
                         self.prove_predicates(
@@ -1906,7 +1896,8 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         PointerCoercion::MutToConstPointer,
                         coercion_source,
                     ) => {
-                        let ty::RawPtr(ty_from, hir::Mutability::Mut) = op.ty(body, tcx).kind()
+                        let ty::RawPtr(ty_from, hir::Mutability::Mut) =
+                            op.ty(self.body, tcx).kind()
                         else {
                             span_mirbug!(self, rvalue, "unexpected base type for cast {:?}", ty,);
                             return;
@@ -1934,7 +1925,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     CastKind::PointerCoercion(PointerCoercion::ArrayToPointer, coercion_source) => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
 
                         let opt_ty_elem_mut = match ty_from.kind() {
                             ty::RawPtr(array_ty, array_mut) => match array_ty.kind() {
@@ -1997,7 +1988,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     CastKind::PointerExposeProvenance => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2015,7 +2006,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     }
 
                     CastKind::PointerWithExposedProvenance => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2032,7 +2023,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::IntToInt => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2049,7 +2040,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::IntToFloat => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2066,7 +2057,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::FloatToInt => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2083,7 +2074,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::FloatToFloat => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2100,7 +2091,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::FnPtrToPtr => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2117,7 +2108,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         }
                     }
                     CastKind::PtrToPtr => {
-                        let ty_from = op.ty(body, tcx);
+                        let ty_from = op.ty(self.body, tcx);
                         let cast_ty_from = CastTy::from_ty(ty_from);
                         let cast_ty_to = CastTy::from_ty(*ty);
                         match (cast_ty_from, cast_ty_to) {
@@ -2193,7 +2184,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
 
             Rvalue::Ref(region, _borrow_kind, borrowed_place) => {
-                self.add_reborrow_constraint(body, location, *region, borrowed_place);
+                self.add_reborrow_constraint(location, *region, borrowed_place);
             }
 
             Rvalue::BinaryOp(
@@ -2203,12 +2194,13 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 self.check_operand(left, location);
                 self.check_operand(right, location);
 
-                let ty_left = left.ty(body, tcx);
+                let ty_left = left.ty(self.body, tcx);
                 match ty_left.kind() {
                     // Types with regions are comparable if they have a common super-type.
                     ty::RawPtr(_, _) | ty::FnPtr(..) => {
-                        let ty_right = right.ty(body, tcx);
-                        let common_ty = self.infcx.next_ty_var(body.source_info(location).span);
+                        let ty_right = right.ty(self.body, tcx);
+                        let common_ty =
+                            self.infcx.next_ty_var(self.body.source_info(location).span);
                         self.sub_types(
                             ty_left,
                             common_ty,
@@ -2237,7 +2229,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     // For types with no regions we can just check that the
                     // both operands have the same type.
                     ty::Int(_) | ty::Uint(_) | ty::Bool | ty::Char | ty::Float(_)
-                        if ty_left == right.ty(body, tcx) => {}
+                        if ty_left == right.ty(self.body, tcx) => {}
                     // Other types are compared by trait methods, not by
                     // `Rvalue::BinaryOp`.
                     _ => span_mirbug!(
@@ -2245,7 +2237,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                         rvalue,
                         "unexpected comparison types {:?} and {:?}",
                         ty_left,
-                        right.ty(body, tcx)
+                        right.ty(self.body, tcx)
                     ),
                 }
             }
@@ -2326,7 +2318,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
     fn check_aggregate_rvalue(
         &mut self,
-        body: &Body<'tcx>,
         rvalue: &Rvalue<'tcx>,
         aggregate_kind: &AggregateKind<'tcx>,
         operands: &IndexSlice<FieldIdx, Operand<'tcx>>,
@@ -2359,7 +2350,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                     continue;
                 }
             };
-            let operand_ty = operand.ty(body, tcx);
+            let operand_ty = operand.ty(self.body, tcx);
             let operand_ty = self.normalize(operand_ty, location);
 
             if let Err(terr) = self.sub_types(
@@ -2389,7 +2380,6 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
     /// - `borrowed_place`: the place `P` being borrowed
     fn add_reborrow_constraint(
         &mut self,
-        body: &Body<'tcx>,
         location: Location,
         borrow_region: ty::Region<'tcx>,
         borrowed_place: &Place<'tcx>,
@@ -2428,7 +2418,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         let def = self.body.source.def_id().expect_local();
         let upvars = tcx.closure_captures(def);
         let field =
-            path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), body);
+            path_utils::is_upvar_field_projection(tcx, upvars, borrowed_place.as_ref(), self.body);
         let category = if let Some(field) = field {
             ConstraintCategory::ClosureUpvar(field)
         } else {
@@ -2440,7 +2430,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
 
             match elem {
                 ProjectionElem::Deref => {
-                    let base_ty = base.ty(body, tcx).ty;
+                    let base_ty = base.ty(self.body, tcx).ty;
 
                     debug!("add_reborrow_constraint - base_ty = {:?}", base_ty);
                     match base_ty.kind() {
@@ -2449,7 +2439,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                                 sup: ref_region.as_var(),
                                 sub: borrow_region.as_var(),
                                 locations: location.to_locations(),
-                                span: location.to_locations().span(body),
+                                span: location.to_locations().span(self.body),
                                 category,
                                 variance_info: ty::VarianceDiagInfo::default(),
                                 from_closure: false,
@@ -2634,27 +2624,27 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         tcx.predicates_of(def_id).instantiate(tcx, args)
     }
 
-    #[instrument(skip(self, body), level = "debug")]
-    fn typeck_mir(&mut self, body: &Body<'tcx>) {
-        self.last_span = body.span;
-        debug!(?body.span);
+    #[instrument(skip(self), level = "debug")]
+    fn typeck_mir(&mut self) {
+        self.last_span = self.body.span;
+        debug!(?self.body.span);
 
-        for (local, local_decl) in body.local_decls.iter_enumerated() {
-            self.check_local(body, local, local_decl);
+        for (local, local_decl) in self.body.local_decls.iter_enumerated() {
+            self.check_local(local, local_decl);
         }
 
-        for (block, block_data) in body.basic_blocks.iter_enumerated() {
+        for (block, block_data) in self.body.basic_blocks.iter_enumerated() {
             let mut location = Location { block, statement_index: 0 };
             for stmt in &block_data.statements {
                 if !stmt.source_info.span.is_dummy() {
                     self.last_span = stmt.source_info.span;
                 }
-                self.check_stmt(body, stmt, location);
+                self.check_stmt(stmt, location);
                 location.statement_index += 1;
             }
 
-            self.check_terminator(body, block_data.terminator(), location);
-            self.check_iscleanup(body, block_data);
+            self.check_terminator(block_data.terminator(), location);
+            self.check_iscleanup(block_data);
         }
     }
 }
diff --git a/compiler/rustc_borrowck/src/type_check/opaque_types.rs b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
index 17482cc0cbd..94b3d0c2bbf 100644
--- a/compiler/rustc_borrowck/src/type_check/opaque_types.rs
+++ b/compiler/rustc_borrowck/src/type_check/opaque_types.rs
@@ -180,6 +180,7 @@ pub(super) fn take_opaques_and_register_member_constraints<'tcx>(
 /// // Equivalent to:
 /// # mod dummy { use super::*;
 /// type FooReturn<'a, T> = impl Foo<'a>;
+/// #[define_opaque(FooReturn)]
 /// fn foo<'a, T>(x: &'a u32, y: T) -> FooReturn<'a, T> {
 ///   (x, y)
 /// }
diff --git a/compiler/rustc_builtin_macros/Cargo.toml b/compiler/rustc_builtin_macros/Cargo.toml
index b5f4f2efd1f..1289d21308b 100644
--- a/compiler/rustc_builtin_macros/Cargo.toml
+++ b/compiler/rustc_builtin_macros/Cargo.toml
@@ -3,10 +3,6 @@ name = "rustc_builtin_macros"
 version = "0.0.0"
 edition = "2024"
 
-
-[lints.rust]
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(llvm_enzyme)'] }
-
 [lib]
 doctest = false
 
diff --git a/compiler/rustc_builtin_macros/messages.ftl b/compiler/rustc_builtin_macros/messages.ftl
index 4cac7cb93f5..3f03834f8d7 100644
--- a/compiler/rustc_builtin_macros/messages.ftl
+++ b/compiler/rustc_builtin_macros/messages.ftl
@@ -75,9 +75,10 @@ builtin_macros_autodiff_mode = unknown Mode: `{$mode}`. Use `Forward` or `Revers
 builtin_macros_autodiff_mode_activity = {$act} can not be used in {$mode} Mode
 builtin_macros_autodiff_not_build = this rustc version does not support autodiff
 builtin_macros_autodiff_number_activities = expected {$expected} activities, but found {$found}
+builtin_macros_autodiff_ret_activity = invalid return activity {$act} in {$mode} Mode
 builtin_macros_autodiff_ty_activity = {$act} can not be used for this type
-
 builtin_macros_autodiff_unknown_activity = did not recognize Activity: `{$act}`
+
 builtin_macros_bad_derive_target = `derive` may only be applied to `struct`s, `enum`s and `union`s
     .label = not applicable here
     .label2 = not a `struct`, `enum` or `union`
diff --git a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
index 78bf2195975..1c1b2c88f76 100644
--- a/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
+++ b/compiler/rustc_builtin_macros/src/alloc_error_handler.rs
@@ -88,6 +88,7 @@ fn generate_handler(cx: &ExtCtxt<'_>, handler: Ident, span: Span, sig_span: Span
         generics: Generics::default(),
         contract: None,
         body,
+        define_opaque: None,
     }));
 
     let attrs = thin_vec![cx.attr_word(sym::rustc_std_internal_symbol, span)];
diff --git a/compiler/rustc_builtin_macros/src/autodiff.rs b/compiler/rustc_builtin_macros/src/autodiff.rs
index 7b5c4a159b0..dcd3c1ce8d9 100644
--- a/compiler/rustc_builtin_macros/src/autodiff.rs
+++ b/compiler/rustc_builtin_macros/src/autodiff.rs
@@ -8,7 +8,8 @@ mod llvm_enzyme {
     use std::string::String;
 
     use rustc_ast::expand::autodiff_attrs::{
-        AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ty_for_activity,
+        AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
+        valid_ty_for_activity,
     };
     use rustc_ast::ptr::P;
     use rustc_ast::token::{Token, TokenKind};
@@ -247,6 +248,7 @@ mod llvm_enzyme {
             generics: Generics::default(),
             contract: None,
             body: Some(d_body),
+            define_opaque: None,
         });
         let mut rustc_ad_attr =
             P(ast::NormalAttr::from_ident(Ident::with_dummy_span(sym::rustc_autodiff)));
@@ -576,6 +578,8 @@ mod llvm_enzyme {
     //
     // Error handling: If the user provides an invalid configuration (incorrect numbers, types, or
     // both), we emit an error and return the original signature. This allows us to continue parsing.
+    // FIXME(Sa4dUs): make individual activities' span available so errors
+    // can point to only the activity instead of the entire attribute
     fn gen_enzyme_decl(
         ecx: &ExtCtxt<'_>,
         sig: &ast::FnSig,
@@ -623,10 +627,22 @@ mod llvm_enzyme {
                 errors = true;
             }
         }
+
+        if has_ret && !valid_ret_activity(x.mode, x.ret_activity) {
+            dcx.emit_err(errors::AutoDiffInvalidRetAct {
+                span,
+                mode: x.mode.to_string(),
+                act: x.ret_activity.to_string(),
+            });
+            // We don't set `errors = true` to avoid annoying type errors relative
+            // to the expanded macro type signature
+        }
+
         if errors {
             // This is not the right signature, but we can continue parsing.
             return (sig.clone(), new_inputs, idents, true);
         }
+
         let unsafe_activities = x
             .input_activity
             .iter()
diff --git a/compiler/rustc_builtin_macros/src/define_opaque.rs b/compiler/rustc_builtin_macros/src/define_opaque.rs
new file mode 100644
index 00000000000..9777e772cf2
--- /dev/null
+++ b/compiler/rustc_builtin_macros/src/define_opaque.rs
@@ -0,0 +1,54 @@
+use rustc_ast::{DUMMY_NODE_ID, ast};
+use rustc_expand::base::{Annotatable, ExtCtxt};
+use rustc_span::Span;
+
+pub(crate) fn expand(
+    ecx: &mut ExtCtxt<'_>,
+    _expand_span: Span,
+    meta_item: &ast::MetaItem,
+    mut item: Annotatable,
+) -> Vec<Annotatable> {
+    let define_opaque = match &mut item {
+        Annotatable::Item(p) => match &mut p.kind {
+            ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
+            _ => None,
+        },
+        Annotatable::AssocItem(i, _assoc_ctxt) => match &mut i.kind {
+            ast::AssocItemKind::Fn(func) => Some(&mut func.define_opaque),
+            _ => None,
+        },
+        Annotatable::Stmt(s) => match &mut s.kind {
+            ast::StmtKind::Item(p) => match &mut p.kind {
+                ast::ItemKind::Fn(f) => Some(&mut f.define_opaque),
+                _ => None,
+            },
+            _ => None,
+        },
+        _ => None,
+    };
+
+    let Some(list) = meta_item.meta_item_list() else {
+        ecx.dcx().span_err(meta_item.span, "expected list of type aliases");
+        return vec![item];
+    };
+
+    if let Some(define_opaque) = define_opaque {
+        *define_opaque = Some(
+            list.iter()
+                .filter_map(|entry| match entry {
+                    ast::MetaItemInner::MetaItem(meta_item) if meta_item.is_word() => {
+                        Some((DUMMY_NODE_ID, meta_item.path.clone()))
+                    }
+                    _ => {
+                        ecx.dcx().span_err(entry.span(), "expected path to type alias");
+                        None
+                    }
+                })
+                .collect(),
+        );
+    } else {
+        ecx.dcx().span_err(meta_item.span, "only functions and methods can define opaque types");
+    }
+
+    vec![item]
+}
diff --git a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
index 5402b5a1ae9..03ee59de70e 100644
--- a/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/generic/mod.rs
@@ -1040,6 +1040,7 @@ impl<'a> MethodDef<'a> {
                 generics: fn_generics,
                 contract: None,
                 body: Some(body_block),
+                define_opaque: None,
             })),
             tokens: None,
         })
diff --git a/compiler/rustc_builtin_macros/src/errors.rs b/compiler/rustc_builtin_macros/src/errors.rs
index ab1e0d8ee89..30597944124 100644
--- a/compiler/rustc_builtin_macros/src/errors.rs
+++ b/compiler/rustc_builtin_macros/src/errors.rs
@@ -186,6 +186,15 @@ mod autodiff {
     }
 
     #[derive(Diagnostic)]
+    #[diag(builtin_macros_autodiff_ret_activity)]
+    pub(crate) struct AutoDiffInvalidRetAct {
+        #[primary_span]
+        pub(crate) span: Span,
+        pub(crate) mode: String,
+        pub(crate) act: String,
+    }
+
+    #[derive(Diagnostic)]
     #[diag(builtin_macros_autodiff_mode)]
     pub(crate) struct AutoDiffInvalidMode {
         #[primary_span]
diff --git a/compiler/rustc_builtin_macros/src/global_allocator.rs b/compiler/rustc_builtin_macros/src/global_allocator.rs
index 8fdbbf8e704..90d79235820 100644
--- a/compiler/rustc_builtin_macros/src/global_allocator.rs
+++ b/compiler/rustc_builtin_macros/src/global_allocator.rs
@@ -83,6 +83,7 @@ impl AllocFnFactory<'_, '_> {
             generics: Generics::default(),
             contract: None,
             body,
+            define_opaque: None,
         }));
         let item = self.cx.item(
             self.span,
diff --git a/compiler/rustc_builtin_macros/src/lib.rs b/compiler/rustc_builtin_macros/src/lib.rs
index c23ce1e5e4a..1defd3867a0 100644
--- a/compiler/rustc_builtin_macros/src/lib.rs
+++ b/compiler/rustc_builtin_macros/src/lib.rs
@@ -38,6 +38,7 @@ mod compile_error;
 mod concat;
 mod concat_bytes;
 mod concat_idents;
+mod define_opaque;
 mod derive;
 mod deriving;
 mod edition_panic;
@@ -113,6 +114,7 @@ pub fn register_builtin_macros(resolver: &mut dyn ResolverExpand) {
         bench: test::expand_bench,
         cfg_accessible: cfg_accessible::Expander,
         cfg_eval: cfg_eval::expand,
+        define_opaque: define_opaque::expand,
         derive: derive::Expander { is_const: false },
         derive_const: derive::Expander { is_const: true },
         global_allocator: global_allocator::expand,
diff --git a/compiler/rustc_builtin_macros/src/test_harness.rs b/compiler/rustc_builtin_macros/src/test_harness.rs
index 472e16e62d5..768b459ec5e 100644
--- a/compiler/rustc_builtin_macros/src/test_harness.rs
+++ b/compiler/rustc_builtin_macros/src/test_harness.rs
@@ -346,6 +346,7 @@ fn mk_main(cx: &mut TestCtxt<'_>) -> P<ast::Item> {
         generics: ast::Generics::default(),
         contract: None,
         body: Some(main_body),
+        define_opaque: None,
     }));
 
     // Honor the reexport_test_harness_main attribute
diff --git a/compiler/rustc_codegen_cranelift/example/issue-72793.rs b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
index 2e08fbca8ef..95d58b90e79 100644
--- a/compiler/rustc_codegen_cranelift/example/issue-72793.rs
+++ b/compiler/rustc_codegen_cranelift/example/issue-72793.rs
@@ -2,23 +2,21 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod helper {
-    pub trait T {
-        type Item;
-    }
+pub trait T {
+    type Item;
+}
 
-    pub type Alias<'a> = impl T<Item = &'a ()>;
+pub type Alias<'a> = impl T<Item = &'a ()>;
 
-    struct S;
-    impl<'a> T for &'a S {
-        type Item = &'a ();
-    }
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
 
-    pub fn filter_positive<'a>() -> Alias<'a> {
-        &S
-    }
+#[define_opaque(Alias)]
+pub fn filter_positive<'a>() -> Alias<'a> {
+    &S
 }
-use helper::*;
 
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     fun(filter_positive());
diff --git a/compiler/rustc_codegen_cranelift/src/lib.rs b/compiler/rustc_codegen_cranelift/src/lib.rs
index a3f43744875..06939beb374 100644
--- a/compiler/rustc_codegen_cranelift/src/lib.rs
+++ b/compiler/rustc_codegen_cranelift/src/lib.rs
@@ -176,13 +176,9 @@ impl CodegenBackend for CraneliftCodegenBackend {
         }
     }
 
-    fn target_features_cfg(
-        &self,
-        sess: &Session,
-        _allow_unstable: bool,
-    ) -> Vec<rustc_span::Symbol> {
+    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
         // FIXME return the actually used target features. this is necessary for #[cfg(target_feature)]
-        if sess.target.arch == "x86_64" && sess.target.os != "none" {
+        let target_features = if sess.target.arch == "x86_64" && sess.target.os != "none" {
             // x86_64 mandates SSE2 support and rustc requires the x87 feature to be enabled
             vec![sym::fsxr, sym::sse, sym::sse2, Symbol::intern("x87")]
         } else if sess.target.arch == "aarch64" {
@@ -196,7 +192,10 @@ impl CodegenBackend for CraneliftCodegenBackend {
             }
         } else {
             vec![]
-        }
+        };
+        // FIXME do `unstable_target_features` properly
+        let unstable_target_features = target_features.clone();
+        (target_features, unstable_target_features)
     }
 
     fn print_version(&self) {
diff --git a/compiler/rustc_codegen_gcc/src/gcc_util.rs b/compiler/rustc_codegen_gcc/src/gcc_util.rs
index 4e8c8aaaf5c..6eae0c24f48 100644
--- a/compiler/rustc_codegen_gcc/src/gcc_util.rs
+++ b/compiler/rustc_codegen_gcc/src/gcc_util.rs
@@ -48,7 +48,7 @@ pub(crate) fn global_gcc_features(sess: &Session, diagnostics: bool) -> Vec<Stri
     for feature in sess.opts.cg.target_feature.split(',') {
         if let Some(feature) = feature.strip_prefix('+') {
             all_rust_features.extend(
-                UnordSet::from(sess.target.implied_target_features(std::iter::once(feature)))
+                UnordSet::from(sess.target.implied_target_features(feature))
                     .to_sorted_stable_ord()
                     .iter()
                     .map(|&&s| (true, s)),
diff --git a/compiler/rustc_codegen_gcc/src/lib.rs b/compiler/rustc_codegen_gcc/src/lib.rs
index f090597f953..d478b2af46c 100644
--- a/compiler/rustc_codegen_gcc/src/lib.rs
+++ b/compiler/rustc_codegen_gcc/src/lib.rs
@@ -259,8 +259,8 @@ impl CodegenBackend for GccCodegenBackend {
             .join(sess)
     }
 
-    fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-        target_features_cfg(sess, allow_unstable, &self.target_info)
+    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
+        target_features_cfg(sess, &self.target_info)
     }
 }
 
@@ -486,35 +486,41 @@ fn to_gcc_opt_level(optlevel: Option<OptLevel>) -> OptimizationLevel {
 /// Returns the features that should be set in `cfg(target_feature)`.
 fn target_features_cfg(
     sess: &Session,
-    allow_unstable: bool,
     target_info: &LockedTargetInfo,
-) -> Vec<Symbol> {
+) -> (Vec<Symbol>, Vec<Symbol>) {
     // TODO(antoyo): use global_gcc_features.
-    sess.target
-        .rust_target_features()
-        .iter()
-        .filter_map(|&(feature, gate, _)| {
-            if allow_unstable
-                || (gate.in_cfg() && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
-            {
-                Some(feature)
-            } else {
-                None
-            }
-        })
-        .filter(|feature| {
-            // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
-            if *feature == "neon" {
-                return false;
-            }
-            target_info.cpu_supports(feature)
-            /*
-              adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
-              avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
-              bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
-              sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
-            */
-        })
-        .map(Symbol::intern)
-        .collect()
+    let f = |allow_unstable| {
+        sess.target
+            .rust_target_features()
+            .iter()
+            .filter_map(|&(feature, gate, _)| {
+                if allow_unstable
+                    || (gate.in_cfg()
+                        && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
+                {
+                    Some(feature)
+                } else {
+                    None
+                }
+            })
+            .filter(|feature| {
+                // TODO: we disable Neon for now since we don't support the LLVM intrinsics for it.
+                if *feature == "neon" {
+                    return false;
+                }
+                target_info.cpu_supports(feature)
+                /*
+                  adx, aes, avx, avx2, avx512bf16, avx512bitalg, avx512bw, avx512cd, avx512dq, avx512er, avx512f, avx512fp16, avx512ifma,
+                  avx512pf, avx512vbmi, avx512vbmi2, avx512vl, avx512vnni, avx512vp2intersect, avx512vpopcntdq,
+                  bmi1, bmi2, cmpxchg16b, ermsb, f16c, fma, fxsr, gfni, lzcnt, movbe, pclmulqdq, popcnt, rdrand, rdseed, rtm,
+                  sha, sse, sse2, sse3, sse4.1, sse4.2, sse4a, ssse3, tbm, vaes, vpclmulqdq, xsave, xsavec, xsaveopt, xsaves
+                */
+            })
+            .map(Symbol::intern)
+            .collect()
+    };
+
+    let target_features = f(false);
+    let unstable_target_features = f(true);
+    (target_features, unstable_target_features)
 }
diff --git a/compiler/rustc_codegen_llvm/src/lib.rs b/compiler/rustc_codegen_llvm/src/lib.rs
index 2f3c8c75b0b..f622646a5d9 100644
--- a/compiler/rustc_codegen_llvm/src/lib.rs
+++ b/compiler/rustc_codegen_llvm/src/lib.rs
@@ -340,8 +340,8 @@ impl CodegenBackend for LlvmCodegenBackend {
         llvm_util::print_version();
     }
 
-    fn target_features_cfg(&self, sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-        target_features_cfg(sess, allow_unstable)
+    fn target_features_cfg(&self, sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
+        target_features_cfg(sess)
     }
 
     fn codegen_crate<'tcx>(
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 5cc4f4ab9e6..4a166b0872d 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -306,45 +306,44 @@ pub(crate) fn to_llvm_features<'a>(sess: &Session, s: &'a str) -> Option<LLVMFea
 /// Must express features in the way Rust understands them.
 ///
 /// We do not have to worry about RUSTC_SPECIFIC_FEATURES here, those are handled outside codegen.
-pub(crate) fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<Symbol> {
-    let mut features: FxHashSet<Symbol> = Default::default();
-
+pub(crate) fn target_features_cfg(sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
     // Add base features for the target.
     // We do *not* add the -Ctarget-features there, and instead duplicate the logic for that below.
     // The reason is that if LLVM considers a feature implied but we do not, we don't want that to
     // show up in `cfg`. That way, `cfg` is entirely under our control -- except for the handling of
-    // the target CPU, that is still expanded to target features (with all their implied features) by
-    // LLVM.
+    // the target CPU, that is still expanded to target features (with all their implied features)
+    // by LLVM.
     let target_machine = create_informational_target_machine(sess, true);
-    // Compute which of the known target features are enabled in the 'base' target machine.
-    // We only consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
-    features.extend(
-        sess.target
-            .rust_target_features()
-            .iter()
-            .filter(|(feature, _, _)| {
-                // skip checking special features, as LLVM may not understand them
-                if RUSTC_SPECIAL_FEATURES.contains(feature) {
-                    return true;
-                }
-                // check that all features in a given smallvec are enabled
-                if let Some(feat) = to_llvm_features(sess, feature) {
-                    for llvm_feature in feat {
-                        let cstr = SmallCStr::new(llvm_feature);
-                        if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) }
-                        {
-                            return false;
-                        }
+    // Compute which of the known target features are enabled in the 'base' target machine. We only
+    // consider "supported" features; "forbidden" features are not reflected in `cfg` as of now.
+    let mut features: FxHashSet<Symbol> = sess
+        .target
+        .rust_target_features()
+        .iter()
+        .filter(|(feature, _, _)| {
+            // skip checking special features, as LLVM may not understand them
+            if RUSTC_SPECIAL_FEATURES.contains(feature) {
+                return true;
+            }
+            if let Some(feat) = to_llvm_features(sess, feature) {
+                for llvm_feature in feat {
+                    let cstr = SmallCStr::new(llvm_feature);
+                    // `LLVMRustHasFeature` is moderately expensive. On targets with many
+                    // features (e.g. x86) these calls take a non-trivial fraction of runtime
+                    // when compiling very small programs.
+                    if !unsafe { llvm::LLVMRustHasFeature(target_machine.raw(), cstr.as_ptr()) } {
+                        return false;
                     }
-                    true
-                } else {
-                    false
                 }
-            })
-            .map(|(feature, _, _)| Symbol::intern(feature)),
-    );
+                true
+            } else {
+                false
+            }
+        })
+        .map(|(feature, _, _)| Symbol::intern(feature))
+        .collect();
 
-    // Add enabled features
+    // Add enabled and remove disabled features.
     for (enabled, feature) in
         sess.opts.cg.target_feature.split(',').filter_map(|s| match s.chars().next() {
             Some('+') => Some((true, Symbol::intern(&s[1..]))),
@@ -360,7 +359,7 @@ pub(crate) fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<S
             #[allow(rustc::potential_query_instability)]
             features.extend(
                 sess.target
-                    .implied_target_features(std::iter::once(feature.as_str()))
+                    .implied_target_features(feature.as_str())
                     .iter()
                     .map(|s| Symbol::intern(s)),
             );
@@ -371,11 +370,7 @@ pub(crate) fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<S
             // `features.contains` below.
             #[allow(rustc::potential_query_instability)]
             features.retain(|f| {
-                if sess
-                    .target
-                    .implied_target_features(std::iter::once(f.as_str()))
-                    .contains(&feature.as_str())
-                {
+                if sess.target.implied_target_features(f.as_str()).contains(&feature.as_str()) {
                     // If `f` if implies `feature`, then `!feature` implies `!f`, so we have to
                     // remove `f`. (This is the standard logical contraposition principle.)
                     false
@@ -387,25 +382,31 @@ pub(crate) fn target_features_cfg(sess: &Session, allow_unstable: bool) -> Vec<S
         }
     }
 
-    // Filter enabled features based on feature gates
-    sess.target
-        .rust_target_features()
-        .iter()
-        .filter_map(|(feature, gate, _)| {
-            // The `allow_unstable` set is used by rustc internally to determined which target
-            // features are truly available, so we want to return even perma-unstable "forbidden"
-            // features.
-            if allow_unstable
-                || (gate.in_cfg() && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
-            {
-                Some(*feature)
-            } else {
-                None
-            }
-        })
-        .filter(|feature| features.contains(&Symbol::intern(feature)))
-        .map(|feature| Symbol::intern(feature))
-        .collect()
+    // Filter enabled features based on feature gates.
+    let f = |allow_unstable| {
+        sess.target
+            .rust_target_features()
+            .iter()
+            .filter_map(|(feature, gate, _)| {
+                // The `allow_unstable` set is used by rustc internally to determined which target
+                // features are truly available, so we want to return even perma-unstable
+                // "forbidden" features.
+                if allow_unstable
+                    || (gate.in_cfg()
+                        && (sess.is_nightly_build() || gate.requires_nightly().is_none()))
+                {
+                    Some(Symbol::intern(feature))
+                } else {
+                    None
+                }
+            })
+            .filter(|feature| features.contains(&feature))
+            .collect()
+    };
+
+    let target_features = f(false);
+    let unstable_target_features = f(true);
+    (target_features, unstable_target_features)
 }
 
 pub(crate) fn print_version() {
@@ -682,7 +683,7 @@ pub(crate) fn global_llvm_features(
         for feature in sess.opts.cg.target_feature.split(',') {
             if let Some(feature) = feature.strip_prefix('+') {
                 all_rust_features.extend(
-                    UnordSet::from(sess.target.implied_target_features(std::iter::once(feature)))
+                    UnordSet::from(sess.target.implied_target_features(feature))
                         .to_sorted_stable_ord()
                         .iter()
                         .map(|&&s| (true, s)),
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index f15d6fba506..95912b01600 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -18,6 +18,8 @@ codegen_ssa_atomic_compare_exchange = Atomic compare-exchange intrinsic missing
 
 codegen_ssa_autodiff_without_lto = using the autodiff feature requires using fat-lto
 
+codegen_ssa_bare_instruction_set = `#[instruction_set]` requires an argument
+
 codegen_ssa_binary_output_to_tty = option `-o` or `--emit` is used to write binary output type `{$shorthand}` to stdout, but stdout is a tty
 
 codegen_ssa_cgu_not_recorded =
@@ -52,6 +54,10 @@ codegen_ssa_error_creating_remark_dir = failed to create remark directory: {$err
 codegen_ssa_error_writing_def_file =
     Error writing .DEF file: {$error}
 
+codegen_ssa_expected_name_value_pair = expected name value pair
+
+codegen_ssa_expected_one_argument = expected one argument
+
 codegen_ssa_expected_used_symbol = expected `used`, `used(compiler)` or `used(linker)`
 
 codegen_ssa_extern_funcs_not_found = some `extern` functions couldn't be found; some native libraries may need to be installed or have their path specified
@@ -88,9 +94,17 @@ codegen_ssa_incorrect_cgu_reuse_type =
 
 codegen_ssa_insufficient_vs_code_product = VS Code is a different product, and is not sufficient.
 
+codegen_ssa_invalid_argument = invalid argument
+    .help = valid inline arguments are `always` and `never`
+
+codegen_ssa_invalid_instruction_set = invalid instruction set specified
+
 codegen_ssa_invalid_link_ordinal_nargs = incorrect number of arguments to `#[link_ordinal]`
     .note = the attribute requires exactly one argument
 
+codegen_ssa_invalid_literal_value = invalid literal value
+    .label = value must be an integer between `0` and `255`
+
 codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization of `{$name}` intrinsic: expected basic float type, found `{$ty}`
 
 codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
@@ -217,6 +231,8 @@ codegen_ssa_msvc_missing_linker = the msvc targets depend on the msvc linker but
 
 codegen_ssa_multiple_external_func_decl = multiple declarations of external function `{$function}` from library `{$library_name}` have different calling conventions
 
+codegen_ssa_multiple_instruction_set = cannot specify more than one instruction set
+
 codegen_ssa_multiple_main_functions = entry symbol `main` declared multiple times
     .help = did you use `#[no_mangle]` on `fn main`? Use `#![no_main]` to suppress the usual Rust-generated entry point
 
@@ -229,6 +245,11 @@ codegen_ssa_no_natvis_directory = error enumerating natvis directory: {$error}
 
 codegen_ssa_no_saved_object_file = cached cgu {$cgu_name} should have an object file, but doesn't
 
+codegen_ssa_null_on_export = `export_name` may not contain null characters
+
+codegen_ssa_out_of_range_integer = integer value out of range
+    .label = value must be between `0` and `255`
+
 codegen_ssa_processing_dymutil_failed = processing debug info with `dsymutil` failed: {$status}
     .note = {$output}
 
@@ -236,6 +257,8 @@ codegen_ssa_read_file = failed to read file: {$message}
 
 codegen_ssa_repair_vs_build_tools = the Visual Studio build tools may need to be repaired using the Visual Studio installer
 
+codegen_ssa_requires_rust_abi = `#[track_caller]` requires Rust ABI
+
 codegen_ssa_rlib_archive_build_failure = failed to build archive from rlib at `{$path}`: {$error}
 
 codegen_ssa_rlib_incompatible_dependency_formats = `{$ty1}` and `{$ty2}` do not have equivalent dependency formats (`{$list1}` vs `{$list2}`)
@@ -356,6 +379,9 @@ codegen_ssa_unable_to_run_dsymutil = unable to run `dsymutil`: {$error}
 
 codegen_ssa_unable_to_write_debugger_visualizer = Unable to write debugger visualizer file `{$path}`: {$error}
 
+codegen_ssa_unexpected_parameter_name = unexpected parameter name
+    .label = expected `{$prefix_nops}` or `{$entry_nops}`
+
 codegen_ssa_unknown_archive_kind =
     Don't know how to build archive of type: {$kind}
 
@@ -367,6 +393,8 @@ codegen_ssa_unknown_reuse_kind = unknown cgu-reuse-kind `{$kind}` specified
 
 codegen_ssa_unsupported_arch = unsupported arch `{$arch}` for os `{$os}`
 
+codegen_ssa_unsupported_instruction_set = target does not support `#[instruction_set]`
+
 codegen_ssa_unsupported_link_self_contained = option `-C link-self-contained` is not supported on this target
 
 codegen_ssa_use_cargo_directive = use the `cargo:rustc-link-lib` directive to specify the native libraries to link with Cargo (see https://doc.rust-lang.org/cargo/reference/build-scripts.html#rustc-link-lib)
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 673740b4aab..27b8be1022e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,15 +1,11 @@
 use std::str::FromStr;
 
 use rustc_abi::ExternAbi;
-use rustc_ast::expand::autodiff_attrs::{
-    AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
-};
+use rustc_ast::expand::autodiff_attrs::{AutoDiffAttrs, DiffActivity, DiffMode};
 use rustc_ast::{MetaItem, MetaItemInner, attr};
 use rustc_attr_parsing::ReprAttr::ReprAlign;
 use rustc_attr_parsing::{AttributeKind, InlineAttr, InstructionSetAttr, OptimizeAttr};
 use rustc_data_structures::fx::FxHashMap;
-use rustc_errors::codes::*;
-use rustc_errors::{DiagMessage, SubdiagMessage, struct_span_code_err};
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::weak_lang_items::WEAK_LANG_ITEMS;
@@ -236,13 +232,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     && let Some(fn_sig) = fn_sig()
                     && fn_sig.skip_binder().abi() != ExternAbi::Rust
                 {
-                    struct_span_code_err!(
-                        tcx.dcx(),
-                        attr.span(),
-                        E0737,
-                        "`#[track_caller]` requires Rust ABI"
-                    )
-                    .emit();
+                    tcx.dcx().emit_err(errors::RequiresRustAbi { span: attr.span() });
                 }
                 if is_closure
                     && !tcx.features().closure_track_caller()
@@ -263,13 +253,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     if s.as_str().contains('\0') {
                         // `#[export_name = ...]` will be converted to a null-terminated string,
                         // so it may not contain any null characters.
-                        struct_span_code_err!(
-                            tcx.dcx(),
-                            attr.span(),
-                            E0648,
-                            "`export_name` may not contain null characters"
-                        )
-                        .emit();
+                        tcx.dcx().emit_err(errors::NullOnExport { span: attr.span() });
                     }
                     codegen_fn_attrs.export_name = Some(s);
                     mixed_export_name_no_mangle_lint_state.track_export_name(attr.span());
@@ -394,47 +378,28 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                                 [sym::arm, sym::a32 | sym::t32]
                                     if !tcx.sess.target.has_thumb_interworking =>
                                 {
-                                    struct_span_code_err!(
-                                        tcx.dcx(),
-                                        attr.span(),
-                                        E0779,
-                                        "target does not support `#[instruction_set]`"
-                                    )
-                                    .emit();
+                                    tcx.dcx().emit_err(errors::UnsuportedInstructionSet {
+                                        span: attr.span(),
+                                    });
                                     None
                                 }
                                 [sym::arm, sym::a32] => Some(InstructionSetAttr::ArmA32),
                                 [sym::arm, sym::t32] => Some(InstructionSetAttr::ArmT32),
                                 _ => {
-                                    struct_span_code_err!(
-                                        tcx.dcx(),
-                                        attr.span(),
-                                        E0779,
-                                        "invalid instruction set specified",
-                                    )
-                                    .emit();
+                                    tcx.dcx().emit_err(errors::InvalidInstructionSet {
+                                        span: attr.span(),
+                                    });
                                     None
                                 }
                             }
                         }
                         [] => {
-                            struct_span_code_err!(
-                                tcx.dcx(),
-                                attr.span(),
-                                E0778,
-                                "`#[instruction_set]` requires an argument"
-                            )
-                            .emit();
+                            tcx.dcx().emit_err(errors::BareInstructionSet { span: attr.span() });
                             None
                         }
                         _ => {
-                            struct_span_code_err!(
-                                tcx.dcx(),
-                                attr.span(),
-                                E0779,
-                                "cannot specify more than one instruction set"
-                            )
-                            .emit();
+                            tcx.dcx()
+                                .emit_err(errors::MultipleInstructionSet { span: attr.span() });
                             None
                         }
                     })
@@ -445,58 +410,38 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
                     let mut entry = None;
                     for item in l {
                         let Some(meta_item) = item.meta_item() else {
-                            tcx.dcx().span_err(item.span(), "expected name value pair");
+                            tcx.dcx().emit_err(errors::ExpectedNameValuePair { span: item.span() });
                             continue;
                         };
 
                         let Some(name_value_lit) = meta_item.name_value_literal() else {
-                            tcx.dcx().span_err(item.span(), "expected name value pair");
+                            tcx.dcx().emit_err(errors::ExpectedNameValuePair { span: item.span() });
                             continue;
                         };
 
-                        fn emit_error_with_label(
-                            tcx: TyCtxt<'_>,
-                            span: Span,
-                            error: impl Into<DiagMessage>,
-                            label: impl Into<SubdiagMessage>,
-                        ) {
-                            let mut err: rustc_errors::Diag<'_, _> =
-                                tcx.dcx().struct_span_err(span, error);
-                            err.span_label(span, label);
-                            err.emit();
-                        }
-
                         let attrib_to_write = match meta_item.name_or_empty() {
                             sym::prefix_nops => &mut prefix,
                             sym::entry_nops => &mut entry,
                             _ => {
-                                emit_error_with_label(
-                                    tcx,
-                                    item.span(),
-                                    "unexpected parameter name",
-                                    format!("expected {} or {}", sym::prefix_nops, sym::entry_nops),
-                                );
+                                tcx.dcx().emit_err(errors::UnexpectedParameterName {
+                                    span: item.span(),
+                                    prefix_nops: sym::prefix_nops,
+                                    entry_nops: sym::entry_nops,
+                                });
                                 continue;
                             }
                         };
 
                         let rustc_ast::LitKind::Int(val, _) = name_value_lit.kind else {
-                            emit_error_with_label(
-                                tcx,
-                                name_value_lit.span,
-                                "invalid literal value",
-                                "value must be an integer between `0` and `255`",
-                            );
+                            tcx.dcx().emit_err(errors::InvalidLiteralValue {
+                                span: name_value_lit.span,
+                            });
                             continue;
                         };
 
                         let Ok(val) = val.get().try_into() else {
-                            emit_error_with_label(
-                                tcx,
-                                name_value_lit.span,
-                                "integer value out of range",
-                                "value must be between `0` and `255`",
-                            );
+                            tcx.dcx()
+                                .emit_err(errors::OutOfRangeInteger { span: name_value_lit.span });
                             continue;
                         };
 
@@ -533,7 +478,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         inline_span = Some(attr.span());
 
         let [item] = &items[..] else {
-            struct_span_code_err!(tcx.dcx(), attr.span(), E0534, "expected one argument").emit();
+            tcx.dcx().emit_err(errors::ExpectedOneArgument { span: attr.span() });
             return InlineAttr::None;
         };
 
@@ -542,9 +487,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         } else if item.has_name(sym::never) {
             InlineAttr::Never
         } else {
-            struct_span_code_err!(tcx.dcx(), items[0].span(), E0535, "invalid argument")
-                .with_help("valid inline arguments are `always` and `never`")
-                .emit();
+            tcx.dcx().emit_err(errors::InvalidArgument { span: items[0].span() });
 
             InlineAttr::None
         }
@@ -575,9 +518,8 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         if !attr.has_name(sym::optimize) {
             return ia;
         }
-        let err = |sp, s| struct_span_code_err!(tcx.dcx(), sp, E0722, "{}", s).emit();
         if attr.is_word() {
-            err(attr.span(), "expected one argument");
+            tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() });
             return ia;
         }
         let Some(ref items) = attr.meta_item_list() else {
@@ -586,7 +528,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
 
         inline_span = Some(attr.span());
         let [item] = &items[..] else {
-            err(attr.span(), "expected one argument");
+            tcx.dcx().emit_err(errors::ExpectedOneArgumentOptimize { span: attr.span() });
             return OptimizeAttr::Default;
         };
         if item.has_name(sym::size) {
@@ -596,7 +538,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
         } else if item.has_name(sym::none) {
             OptimizeAttr::DoNotOptimize
         } else {
-            err(item.span(), "invalid argument");
+            tcx.dcx().emit_err(errors::InvalidArgumentOptimize { span: item.span() });
             OptimizeAttr::Default
         }
     });
@@ -930,15 +872,6 @@ fn autodiff_attrs(tcx: TyCtxt<'_>, id: DefId) -> Option<AutoDiffAttrs> {
         }
     }
 
-    for &input in &arg_activities {
-        if !valid_input_activity(mode, input) {
-            span_bug!(attr.span(), "Invalid input activity {} for {} mode", input, mode);
-        }
-    }
-    if !valid_ret_activity(mode, ret_activity) {
-        span_bug!(attr.span(), "Invalid return activity {} for {} mode", ret_activity, mode);
-    }
-
     Some(AutoDiffAttrs { mode, ret_activity, input_activity: arg_activities })
 }
 
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index ccf6d12977f..394c80fcfbd 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -136,6 +136,110 @@ pub(crate) struct NoSavedObjectFile<'a> {
 }
 
 #[derive(Diagnostic)]
+#[diag(codegen_ssa_requires_rust_abi, code = E0737)]
+pub(crate) struct RequiresRustAbi {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_null_on_export, code = E0648)]
+pub(crate) struct NullOnExport {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_unsupported_instruction_set, code = E0779)]
+pub(crate) struct UnsuportedInstructionSet {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_invalid_instruction_set, code = E0779)]
+pub(crate) struct InvalidInstructionSet {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_bare_instruction_set, code = E0778)]
+pub(crate) struct BareInstructionSet {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_multiple_instruction_set, code = E0779)]
+pub(crate) struct MultipleInstructionSet {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_name_value_pair)]
+pub(crate) struct ExpectedNameValuePair {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_unexpected_parameter_name)]
+pub(crate) struct UnexpectedParameterName {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+    pub prefix_nops: Symbol,
+    pub entry_nops: Symbol,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_invalid_literal_value)]
+pub(crate) struct InvalidLiteralValue {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_out_of_range_integer)]
+pub(crate) struct OutOfRangeInteger {
+    #[primary_span]
+    #[label]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_one_argument, code = E0534)]
+pub(crate) struct ExpectedOneArgument {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_expected_one_argument, code = E0722)]
+pub(crate) struct ExpectedOneArgumentOptimize {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_invalid_argument, code = E0535)]
+#[help]
+pub(crate) struct InvalidArgument {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(codegen_ssa_invalid_argument, code = E0722)]
+pub(crate) struct InvalidArgumentOptimize {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
 #[diag(codegen_ssa_copy_path_buf)]
 pub(crate) struct CopyPathBuf {
     pub source_file: PathBuf,
diff --git a/compiler/rustc_codegen_ssa/src/target_features.rs b/compiler/rustc_codegen_ssa/src/target_features.rs
index 95a5e96fe46..8058cd1b178 100644
--- a/compiler/rustc_codegen_ssa/src/target_features.rs
+++ b/compiler/rustc_codegen_ssa/src/target_features.rs
@@ -190,7 +190,7 @@ pub(crate) fn provide(providers: &mut Providers) {
         },
         implied_target_features: |tcx, feature: Symbol| {
             let feature = feature.as_str();
-            UnordSet::from(tcx.sess.target.implied_target_features(std::iter::once(feature)))
+            UnordSet::from(tcx.sess.target.implied_target_features(feature))
                 .into_sorted_stable_ord()
                 .into_iter()
                 .map(|s| Symbol::intern(s))
diff --git a/compiler/rustc_codegen_ssa/src/traits/backend.rs b/compiler/rustc_codegen_ssa/src/traits/backend.rs
index ebcf118b903..65fd843e7a5 100644
--- a/compiler/rustc_codegen_ssa/src/traits/backend.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/backend.rs
@@ -45,10 +45,13 @@ pub trait CodegenBackend {
 
     fn print(&self, _req: &PrintRequest, _out: &mut String, _sess: &Session) {}
 
-    /// Returns the features that should be set in `cfg(target_features)`.
+    /// Returns two feature sets:
+    /// - The first has the features that should be set in `cfg(target_features)`.
+    /// - The second is like the first, but also includes unstable features.
+    ///
     /// RUSTC_SPECIFIC_FEATURES should be skipped here, those are handled outside codegen.
-    fn target_features_cfg(&self, _sess: &Session, _allow_unstable: bool) -> Vec<Symbol> {
-        vec![]
+    fn target_features_cfg(&self, _sess: &Session) -> (Vec<Symbol>, Vec<Symbol>) {
+        (vec![], vec![])
     }
 
     fn print_passes(&self) {}
diff --git a/compiler/rustc_const_eval/src/interpret/memory.rs b/compiler/rustc_const_eval/src/interpret/memory.rs
index ce0b5a350e0..e5af0673629 100644
--- a/compiler/rustc_const_eval/src/interpret/memory.rs
+++ b/compiler/rustc_const_eval/src/interpret/memory.rs
@@ -982,6 +982,10 @@ impl<'tcx, M: Machine<'tcx>> InterpCx<'tcx, M> {
                     todo.push(id);
                 }
             }
+            // Also expose the provenance of the interpreter-level allocation, so it can
+            // be read by FFI. The `black_box` is defensive programming as LLVM likes
+            // to (incorrectly) optimize away ptr2int casts whose result is unused.
+            std::hint::black_box(alloc.get_bytes_unchecked_raw().expose_provenance());
 
             // Prepare for possible write from native code if mutable.
             if info.mutbl.is_mut() {
diff --git a/compiler/rustc_data_structures/Cargo.toml b/compiler/rustc_data_structures/Cargo.toml
index bdf5494f210..b9a5fc3a1fe 100644
--- a/compiler/rustc_data_structures/Cargo.toml
+++ b/compiler/rustc_data_structures/Cargo.toml
@@ -29,6 +29,11 @@ thin-vec = "0.2.12"
 tracing = "0.1"
 # tidy-alphabetical-end
 
+[dependencies.hashbrown]
+version = "0.15.2"
+default-features = false
+features = ["nightly"] # for may_dangle
+
 [dependencies.parking_lot]
 version = "0.12"
 
diff --git a/compiler/rustc_data_structures/src/lib.rs b/compiler/rustc_data_structures/src/lib.rs
index a3b62b46919..865424fd6bb 100644
--- a/compiler/rustc_data_structures/src/lib.rs
+++ b/compiler/rustc_data_structures/src/lib.rs
@@ -24,7 +24,6 @@
 #![feature(dropck_eyepatch)]
 #![feature(extend_one)]
 #![feature(file_buffered)]
-#![feature(hash_raw_entry)]
 #![feature(macro_metavar_expr)]
 #![feature(map_try_insert)]
 #![feature(min_specialization)]
diff --git a/compiler/rustc_data_structures/src/marker.rs b/compiler/rustc_data_structures/src/marker.rs
index 4cacc269709..64c64bfa3c2 100644
--- a/compiler/rustc_data_structures/src/marker.rs
+++ b/compiler/rustc_data_structures/src/marker.rs
@@ -76,6 +76,7 @@ impl_dyn_send!(
     [crate::sync::RwLock<T> where T: DynSend]
     [crate::tagged_ptr::TaggedRef<'a, P, T> where 'a, P: Sync, T: Send + crate::tagged_ptr::Tag]
     [rustc_arena::TypedArena<T> where T: DynSend]
+    [hashbrown::HashTable<T> where T: DynSend]
     [indexmap::IndexSet<V, S> where V: DynSend, S: DynSend]
     [indexmap::IndexMap<K, V, S> where K: DynSend, V: DynSend, S: DynSend]
     [thin_vec::ThinVec<T> where T: DynSend]
@@ -153,6 +154,7 @@ impl_dyn_sync!(
     [crate::tagged_ptr::TaggedRef<'a, P, T> where 'a, P: Sync, T: Sync + crate::tagged_ptr::Tag]
     [parking_lot::lock_api::Mutex<R, T> where R: DynSync, T: ?Sized + DynSend]
     [parking_lot::lock_api::RwLock<R, T> where R: DynSync, T: ?Sized + DynSend + DynSync]
+    [hashbrown::HashTable<T> where T: DynSync]
     [indexmap::IndexSet<V, S> where V: DynSync, S: DynSync]
     [indexmap::IndexMap<K, V, S> where K: DynSync, V: DynSync, S: DynSync]
     [smallvec::SmallVec<A> where A: smallvec::Array + DynSync]
diff --git a/compiler/rustc_data_structures/src/obligation_forest/mod.rs b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
index 8d19fc5f9cc..f63b201742d 100644
--- a/compiler/rustc_data_structures/src/obligation_forest/mod.rs
+++ b/compiler/rustc_data_structures/src/obligation_forest/mod.rs
@@ -315,6 +315,7 @@ mod helper {
     use super::*;
     pub(super) type ObligationTreeIdGenerator = impl Iterator<Item = ObligationTreeId>;
     impl<O: ForestObligation> ObligationForest<O> {
+        #[cfg_attr(not(bootstrap), define_opaque(ObligationTreeIdGenerator))]
         pub fn new() -> ObligationForest<O> {
             ObligationForest {
                 nodes: vec![],
diff --git a/compiler/rustc_data_structures/src/sharded.rs b/compiler/rustc_data_structures/src/sharded.rs
index 3016348f224..49cafcb17a0 100644
--- a/compiler/rustc_data_structures/src/sharded.rs
+++ b/compiler/rustc_data_structures/src/sharded.rs
@@ -1,11 +1,11 @@
 use std::borrow::Borrow;
-use std::collections::hash_map::RawEntryMut;
 use std::hash::{Hash, Hasher};
-use std::iter;
+use std::{iter, mem};
 
 use either::Either;
+use hashbrown::hash_table::{Entry, HashTable};
 
-use crate::fx::{FxHashMap, FxHasher};
+use crate::fx::FxHasher;
 use crate::sync::{CacheAligned, Lock, LockGuard, Mode, is_dyn_thread_safe};
 
 // 32 shards is sufficient to reduce contention on an 8-core Ryzen 7 1700,
@@ -140,17 +140,67 @@ pub fn shards() -> usize {
     1
 }
 
-pub type ShardedHashMap<K, V> = Sharded<FxHashMap<K, V>>;
+pub type ShardedHashMap<K, V> = Sharded<HashTable<(K, V)>>;
 
 impl<K: Eq, V> ShardedHashMap<K, V> {
     pub fn with_capacity(cap: usize) -> Self {
-        Self::new(|| FxHashMap::with_capacity_and_hasher(cap, rustc_hash::FxBuildHasher::default()))
+        Self::new(|| HashTable::with_capacity(cap))
     }
     pub fn len(&self) -> usize {
         self.lock_shards().map(|shard| shard.len()).sum()
     }
 }
 
+impl<K: Eq + Hash, V> ShardedHashMap<K, V> {
+    #[inline]
+    pub fn get<Q>(&self, key: &Q) -> Option<V>
+    where
+        K: Borrow<Q>,
+        Q: Hash + Eq,
+        V: Clone,
+    {
+        let hash = make_hash(key);
+        let shard = self.lock_shard_by_hash(hash);
+        let (_, value) = shard.find(hash, |(k, _)| k.borrow() == key)?;
+        Some(value.clone())
+    }
+
+    #[inline]
+    pub fn get_or_insert_with(&self, key: K, default: impl FnOnce() -> V) -> V
+    where
+        V: Copy,
+    {
+        let hash = make_hash(&key);
+        let mut shard = self.lock_shard_by_hash(hash);
+
+        match table_entry(&mut shard, hash, &key) {
+            Entry::Occupied(e) => e.get().1,
+            Entry::Vacant(e) => {
+                let value = default();
+                e.insert((key, value));
+                value
+            }
+        }
+    }
+
+    #[inline]
+    pub fn insert(&self, key: K, value: V) -> Option<V> {
+        let hash = make_hash(&key);
+        let mut shard = self.lock_shard_by_hash(hash);
+
+        match table_entry(&mut shard, hash, &key) {
+            Entry::Occupied(e) => {
+                let previous = mem::replace(&mut e.into_mut().1, value);
+                Some(previous)
+            }
+            Entry::Vacant(e) => {
+                e.insert((key, value));
+                None
+            }
+        }
+    }
+}
+
 impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     #[inline]
     pub fn intern_ref<Q: ?Sized>(&self, value: &Q, make: impl FnOnce() -> K) -> K
@@ -160,13 +210,12 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     {
         let hash = make_hash(value);
         let mut shard = self.lock_shard_by_hash(hash);
-        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, value);
 
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
+        match table_entry(&mut shard, hash, value) {
+            Entry::Occupied(e) => e.get().0,
+            Entry::Vacant(e) => {
                 let v = make();
-                e.insert_hashed_nocheck(hash, v, ());
+                e.insert((v, ()));
                 v
             }
         }
@@ -180,13 +229,12 @@ impl<K: Eq + Hash + Copy> ShardedHashMap<K, ()> {
     {
         let hash = make_hash(&value);
         let mut shard = self.lock_shard_by_hash(hash);
-        let entry = shard.raw_entry_mut().from_key_hashed_nocheck(hash, &value);
 
-        match entry {
-            RawEntryMut::Occupied(e) => *e.key(),
-            RawEntryMut::Vacant(e) => {
+        match table_entry(&mut shard, hash, &value) {
+            Entry::Occupied(e) => e.get().0,
+            Entry::Vacant(e) => {
                 let v = make(value);
-                e.insert_hashed_nocheck(hash, v, ());
+                e.insert((v, ()));
                 v
             }
         }
@@ -203,17 +251,30 @@ impl<K: Eq + Hash + Copy + IntoPointer> ShardedHashMap<K, ()> {
         let hash = make_hash(&value);
         let shard = self.lock_shard_by_hash(hash);
         let value = value.into_pointer();
-        shard.raw_entry().from_hash(hash, |entry| entry.into_pointer() == value).is_some()
+        shard.find(hash, |(k, ())| k.into_pointer() == value).is_some()
     }
 }
 
 #[inline]
-pub fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
+fn make_hash<K: Hash + ?Sized>(val: &K) -> u64 {
     let mut state = FxHasher::default();
     val.hash(&mut state);
     state.finish()
 }
 
+#[inline]
+fn table_entry<'a, K, V, Q>(
+    table: &'a mut HashTable<(K, V)>,
+    hash: u64,
+    key: &Q,
+) -> Entry<'a, (K, V)>
+where
+    K: Hash + Borrow<Q>,
+    Q: ?Sized + Eq,
+{
+    table.entry(hash, move |(k, _)| k.borrow() == key, |(k, _)| make_hash(k))
+}
+
 /// Get a shard with a pre-computed hash value. If `get_shard_by_value` is
 /// ever used in combination with `get_shard_by_hash` on a single `Sharded`
 /// instance, then `hash` must be computed with `FxHasher`. Otherwise,
diff --git a/compiler/rustc_error_codes/src/error_codes/E0792.md b/compiler/rustc_error_codes/src/error_codes/E0792.md
index 5e3dcc4aa72..033e1c65192 100644
--- a/compiler/rustc_error_codes/src/error_codes/E0792.md
+++ b/compiler/rustc_error_codes/src/error_codes/E0792.md
@@ -7,6 +7,7 @@ This means
 
 type Foo<T> = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo<u32> {
     5u32
 }
@@ -19,6 +20,7 @@ is not accepted. If it were accepted, one could create unsound situations like
 
 type Foo<T> = impl Default;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo<u32> {
     5u32
 }
@@ -36,6 +38,7 @@ Instead you need to make the function generic:
 
 type Foo<T> = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo<U>() -> Foo<U> {
     5u32
 }
@@ -56,6 +59,7 @@ use std::fmt::Debug;
 
 type Foo<T: Debug> = impl Debug;
 
+#[define_opaque(Foo)]
 fn foo<U: Debug>() -> Foo<U> {
     Vec::<U>::new()
 }
diff --git a/compiler/rustc_error_messages/src/lib.rs b/compiler/rustc_error_messages/src/lib.rs
index a6fbbb29ccd..066546ecf74 100644
--- a/compiler/rustc_error_messages/src/lib.rs
+++ b/compiler/rustc_error_messages/src/lib.rs
@@ -208,6 +208,7 @@ pub type LazyFallbackBundle = Arc<LazyLock<FluentBundle, impl FnOnce() -> Fluent
 
 /// Return the default `FluentBundle` with standard "en-US" diagnostic messages.
 #[instrument(level = "trace", skip(resources))]
+#[cfg_attr(not(bootstrap), define_opaque(LazyFallbackBundle))]
 pub fn fallback_fluent_bundle(
     resources: Vec<&'static str>,
     with_directionality_markers: bool,
diff --git a/compiler/rustc_expand/src/expand.rs b/compiler/rustc_expand/src/expand.rs
index c523bcece72..87f01be26c2 100644
--- a/compiler/rustc_expand/src/expand.rs
+++ b/compiler/rustc_expand/src/expand.rs
@@ -780,8 +780,8 @@ impl<'a, 'b> MacroExpander<'a, 'b> {
                             }
                         }
                         Err(err) => {
-                            let guar = err.emit();
-                            fragment_kind.dummy(span, guar)
+                            let _guar = err.emit();
+                            fragment_kind.expect_from_annotatables(iter::once(item))
                         }
                     }
                 }
diff --git a/compiler/rustc_expand/src/mbe/quoted.rs b/compiler/rustc_expand/src/mbe/quoted.rs
index 8cb001391c5..0ea53627fe7 100644
--- a/compiler/rustc_expand/src/mbe/quoted.rs
+++ b/compiler/rustc_expand/src/mbe/quoted.rs
@@ -274,7 +274,7 @@ fn parse_tree<'a>(
                     let msg =
                         format!("expected identifier, found `{}`", pprust::token_to_string(token),);
                     sess.dcx().span_err(token.span, msg);
-                    TokenTree::MetaVar(token.span, Ident::empty())
+                    TokenTree::MetaVar(token.span, Ident::dummy())
                 }
 
                 // There are no more tokens. Just return the `$` we already have.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 7741f6668c3..3c61bfd1c93 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -240,7 +240,7 @@ declare_features! (
     /// Added for testing unstable lints; perma-unstable.
     (internal, test_unstable_lint, "1.60.0", None),
     /// Helps with formatting for `group_imports = "StdExternalCrate"`.
-    (unstable, unqualified_local_imports, "1.83.0", None),
+    (unstable, unqualified_local_imports, "1.83.0", Some(138299)),
     /// Use for stable + negative coherence and strict coherence depending on trait's
     /// rustc_strict_coherence value.
     (unstable, with_negative_coherence, "1.60.0", None),
diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs
index 928455ace85..d4dfb9f2973 100644
--- a/compiler/rustc_hir/src/hir.rs
+++ b/compiler/rustc_hir/src/hir.rs
@@ -243,7 +243,7 @@ impl<'hir> PathSegment<'hir> {
     }
 
     pub fn invalid() -> Self {
-        Self::new(Ident::empty(), HirId::INVALID, Res::Err)
+        Self::new(Ident::dummy(), HirId::INVALID, Res::Err)
     }
 
     pub fn args(&self) -> &GenericArgs<'hir> {
@@ -1307,13 +1307,18 @@ impl Attribute {
 #[derive(Debug)]
 pub struct AttributeMap<'tcx> {
     pub map: SortedMap<ItemLocalId, &'tcx [Attribute]>,
+    /// Preprocessed `#[define_opaque]` attribute.
+    pub define_opaque: Option<&'tcx [(Span, LocalDefId)]>,
     // Only present when the crate hash is needed.
     pub opt_hash: Option<Fingerprint>,
 }
 
 impl<'tcx> AttributeMap<'tcx> {
-    pub const EMPTY: &'static AttributeMap<'static> =
-        &AttributeMap { map: SortedMap::new(), opt_hash: Some(Fingerprint::ZERO) };
+    pub const EMPTY: &'static AttributeMap<'static> = &AttributeMap {
+        map: SortedMap::new(),
+        opt_hash: Some(Fingerprint::ZERO),
+        define_opaque: None,
+    };
 
     #[inline]
     pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
@@ -4327,16 +4332,6 @@ pub enum OwnerNode<'hir> {
 }
 
 impl<'hir> OwnerNode<'hir> {
-    pub fn ident(&self) -> Option<Ident> {
-        match self {
-            OwnerNode::Item(Item { ident, .. })
-            | OwnerNode::ForeignItem(ForeignItem { ident, .. })
-            | OwnerNode::ImplItem(ImplItem { ident, .. })
-            | OwnerNode::TraitItem(TraitItem { ident, .. }) => Some(*ident),
-            OwnerNode::Crate(..) | OwnerNode::Synthetic => None,
-        }
-    }
-
     pub fn span(&self) -> Span {
         match self {
             OwnerNode::Item(Item { span, .. })
diff --git a/compiler/rustc_hir/src/intravisit.rs b/compiler/rustc_hir/src/intravisit.rs
index 25d2a825343..3ef645a5f61 100644
--- a/compiler/rustc_hir/src/intravisit.rs
+++ b/compiler/rustc_hir/src/intravisit.rs
@@ -363,7 +363,7 @@ pub trait Visitor<'v>: Sized {
     /// See the doc comments on [`Ty`] for an explanation of what it means for a type to be
     /// ambiguous.
     ///
-    /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
+    /// The [`Visitor::visit_infer`] method should be overridden in order to handle infer vars.
     fn visit_ty(&mut self, t: &'v Ty<'v, AmbigArg>) -> Self::Result {
         walk_ty(self, t)
     }
@@ -374,7 +374,7 @@ pub trait Visitor<'v>: Sized {
     /// See the doc comments on [`ConstArg`] for an explanation of what it means for a const to be
     /// ambiguous.
     ///
-    /// The [`Visitor::visit_infer`] method should be overriden in order to handle infer vars.
+    /// The [`Visitor::visit_infer`] method should be overridden in order to handle infer vars.
     fn visit_const_arg(&mut self, c: &'v ConstArg<'v, AmbigArg>) -> Self::Result {
         walk_ambig_const_arg(self, c)
     }
diff --git a/compiler/rustc_hir/src/stable_hash_impls.rs b/compiler/rustc_hir/src/stable_hash_impls.rs
index 2709a826549..91ea88cae47 100644
--- a/compiler/rustc_hir/src/stable_hash_impls.rs
+++ b/compiler/rustc_hir/src/stable_hash_impls.rs
@@ -106,7 +106,7 @@ impl<'tcx, HirCtx: crate::HashStableContext> HashStable<HirCtx> for AttributeMap
     fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
         // We ignore the `map` since it refers to information included in `opt_hash` which is
         // hashed in the collector and used for the crate hash.
-        let AttributeMap { opt_hash, map: _ } = *self;
+        let AttributeMap { opt_hash, define_opaque: _, map: _ } = *self;
         opt_hash.unwrap().hash_stable(hcx, hasher);
     }
 }
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index 935f4de6c58..194f2cd04e4 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -504,12 +504,9 @@ hir_analysis_supertrait_item_shadowee = item from `{$supertrait}` is shadowed by
 
 hir_analysis_supertrait_item_shadowing = trait item `{$item}` from `{$subtrait}` shadows identically named item from supertrait
 
-hir_analysis_tait_forward_compat = item constrains opaque type that is not in its signature
-    .note = this item must mention the opaque type in its signature in order to be able to register hidden types
-
-hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`, but has it in its signature
-    .note = consider moving the opaque type's declaration and defining uses into a separate module
-    .opaque = this opaque type is in the signature
+hir_analysis_tait_forward_compat2 = item does not constrain `{$opaque_type}`
+    .note = consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+    .opaque = this opaque type is supposed to be constrained
 
 hir_analysis_target_feature_on_main = `main` function is not allowed to have `#[target_feature]`
 
diff --git a/compiler/rustc_hir_analysis/src/check/check.rs b/compiler/rustc_hir_analysis/src/check/check.rs
index 8f9997cb62c..8dc5d361750 100644
--- a/compiler/rustc_hir_analysis/src/check/check.rs
+++ b/compiler/rustc_hir_analysis/src/check/check.rs
@@ -392,6 +392,12 @@ fn best_definition_site_of_opaque<'tcx>(
                 return ControlFlow::Continue(());
             }
 
+            let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
+            // Don't try to check items that cannot possibly constrain the type.
+            if !opaque_types_defined_by.contains(&self.opaque_def_id) {
+                return ControlFlow::Continue(());
+            }
+
             if let Some(hidden_ty) =
                 self.tcx.mir_borrowck(item_def_id).concrete_opaque_types.get(&self.opaque_def_id)
             {
@@ -451,19 +457,7 @@ fn best_definition_site_of_opaque<'tcx>(
             None
         }
         hir::OpaqueTyOrigin::TyAlias { in_assoc_ty: false, .. } => {
-            let scope = tcx.hir_get_defining_scope(tcx.local_def_id_to_hir_id(opaque_def_id));
-            let found = if scope == hir::CRATE_HIR_ID {
-                tcx.hir_walk_toplevel_module(&mut locator)
-            } else {
-                match tcx.hir_node(scope) {
-                    Node::Item(it) => locator.visit_item(it),
-                    Node::ImplItem(it) => locator.visit_impl_item(it),
-                    Node::TraitItem(it) => locator.visit_trait_item(it),
-                    Node::ForeignItem(it) => locator.visit_foreign_item(it),
-                    other => bug!("{:?} is not a valid scope for an opaque type item", other),
-                }
-            };
-            found.break_value()
+            tcx.hir_walk_toplevel_module(&mut locator).break_value()
         }
     }
 }
diff --git a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
index 399c4fbe55a..142078900f0 100644
--- a/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
+++ b/compiler/rustc_hir_analysis/src/collect/type_of/opaque.rs
@@ -1,14 +1,13 @@
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def};
+use rustc_hir::{self as hir, Expr, ImplItem, Item, Node, TraitItem, def, intravisit};
 use rustc_middle::bug;
 use rustc_middle::hir::nested_filter;
 use rustc_middle::ty::{self, Ty, TyCtxt, TypeVisitableExt};
 use rustc_span::DUMMY_SP;
 use tracing::{debug, instrument, trace};
 
-use crate::errors::{TaitForwardCompat, TaitForwardCompat2, UnconstrainedOpaqueType};
+use crate::errors::{TaitForwardCompat2, UnconstrainedOpaqueType};
 
 /// Checks "defining uses" of opaque `impl Trait` in associated types.
 /// These can only be defined by associated items of the same trait.
@@ -82,38 +81,9 @@ pub(super) fn find_opaque_ty_constraints_for_impl_trait_in_assoc_type(
 /// ```
 #[instrument(skip(tcx), level = "debug")]
 pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: LocalDefId) -> Ty<'_> {
-    let hir_id = tcx.local_def_id_to_hir_id(def_id);
-    let scope = tcx.hir_get_defining_scope(hir_id);
     let mut locator = TaitConstraintLocator { def_id, tcx, found: None, typeck_types: vec![] };
 
-    debug!(?scope);
-
-    if scope == hir::CRATE_HIR_ID {
-        tcx.hir_walk_toplevel_module(&mut locator);
-    } else {
-        trace!("scope={:#?}", tcx.hir_node(scope));
-        match tcx.hir_node(scope) {
-            // We explicitly call `visit_*` methods, instead of using `intravisit::walk_*` methods
-            // This allows our visitor to process the defining item itself, causing
-            // it to pick up any 'sibling' defining uses.
-            //
-            // For example, this code:
-            // ```
-            // fn foo() {
-            //     type Blah = impl Debug;
-            //     let my_closure = || -> Blah { true };
-            // }
-            // ```
-            //
-            // requires us to explicitly process `foo()` in order
-            // to notice the defining usage of `Blah`.
-            Node::Item(it) => locator.visit_item(it),
-            Node::ImplItem(it) => locator.visit_impl_item(it),
-            Node::TraitItem(it) => locator.visit_trait_item(it),
-            Node::ForeignItem(it) => locator.visit_foreign_item(it),
-            other => bug!("{:?} is not a valid scope for an opaque type item", other),
-        }
-    }
+    tcx.hir_walk_toplevel_module(&mut locator);
 
     if let Some(hidden) = locator.found {
         // Only check against typeck if we didn't already error
@@ -137,12 +107,7 @@ pub(super) fn find_opaque_ty_constraints_for_tait(tcx: TyCtxt<'_>, def_id: Local
         let reported = tcx.dcx().emit_err(UnconstrainedOpaqueType {
             span: tcx.def_span(def_id),
             name: tcx.item_ident(parent_def_id.to_def_id()),
-            what: match tcx.hir_node(scope) {
-                _ if scope == hir::CRATE_HIR_ID => "module",
-                Node::Item(hir::Item { kind: hir::ItemKind::Mod(_), .. }) => "module",
-                Node::Item(hir::Item { kind: hir::ItemKind::Impl(_), .. }) => "impl",
-                _ => "item",
-            },
+            what: "crate",
         });
         Ty::new_error(tcx, reported)
     }
@@ -176,6 +141,13 @@ impl TaitConstraintLocator<'_> {
             return;
         }
 
+        let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
+        // Don't try to check items that cannot possibly constrain the type.
+        if !opaque_types_defined_by.contains(&self.def_id) {
+            debug!("no constraint: no opaque types defined");
+            return;
+        }
+
         // Function items with `_` in their return type already emit an error, skip any
         // "non-defining use" errors for them.
         // Note that we use `Node::fn_sig` instead of `Node::fn_decl` here, because the former
@@ -215,8 +187,6 @@ impl TaitConstraintLocator<'_> {
             return;
         }
 
-        let opaque_types_defined_by = self.tcx.opaque_types_defined_by(item_def_id);
-
         let mut constrained = false;
         for (&opaque_type_key, &hidden_type) in &tables.concrete_opaque_types {
             if opaque_type_key.def_id != self.def_id {
@@ -224,20 +194,6 @@ impl TaitConstraintLocator<'_> {
             }
             constrained = true;
 
-            if !opaque_types_defined_by.contains(&self.def_id) {
-                let guar = self.tcx.dcx().emit_err(TaitForwardCompat {
-                    span: hidden_type.span,
-                    item_span: self
-                        .tcx
-                        .def_ident_span(item_def_id)
-                        .unwrap_or_else(|| self.tcx.def_span(item_def_id)),
-                });
-                // Avoid "opaque type not constrained" errors on the opaque itself.
-                self.found = Some(ty::OpaqueHiddenType {
-                    span: DUMMY_SP,
-                    ty: Ty::new_error(self.tcx, guar),
-                });
-            }
             let concrete_type =
                 self.tcx.erase_regions(hidden_type.remap_generic_params_to_declaration_params(
                     opaque_type_key,
@@ -309,19 +265,13 @@ impl<'tcx> intravisit::Visitor<'tcx> for TaitConstraintLocator<'tcx> {
     }
     fn visit_item(&mut self, it: &'tcx Item<'tcx>) {
         trace!(?it.owner_id);
-        // The opaque type itself or its children are not within its reveal scope.
-        if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
-            intravisit::walk_item(self, it);
-        }
+        self.check(it.owner_id.def_id);
+        intravisit::walk_item(self, it);
     }
     fn visit_impl_item(&mut self, it: &'tcx ImplItem<'tcx>) {
         trace!(?it.owner_id);
-        // The opaque type itself or its children are not within its reveal scope.
-        if it.owner_id.def_id != self.def_id {
-            self.check(it.owner_id.def_id);
-            intravisit::walk_impl_item(self, it);
-        }
+        self.check(it.owner_id.def_id);
+        intravisit::walk_impl_item(self, it);
     }
     fn visit_trait_item(&mut self, it: &'tcx TraitItem<'tcx>) {
         trace!(?it.owner_id);
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 4c6c2504126..f2560f22874 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -425,16 +425,6 @@ pub(crate) struct UnconstrainedOpaqueType {
 }
 
 #[derive(Diagnostic)]
-#[diag(hir_analysis_tait_forward_compat)]
-#[note]
-pub(crate) struct TaitForwardCompat {
-    #[primary_span]
-    pub span: Span,
-    #[note]
-    pub item_span: Span,
-}
-
-#[derive(Diagnostic)]
 #[diag(hir_analysis_tait_forward_compat2)]
 #[note]
 pub(crate) struct TaitForwardCompat2 {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
index ace5e34b382..fa061c80618 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/errors.rs
@@ -1520,7 +1520,7 @@ fn generics_args_err_extend<'a>(
                 })
                 .collect();
             if args.len() > 1
-                && let Some(span) = args.into_iter().last()
+                && let Some(span) = args.into_iter().next_back()
             {
                 err.note(
                     "generic arguments are not allowed on both an enum and its variant's path \
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
index 3611db7c68f..e78801dd601 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/lint.rs
@@ -78,13 +78,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
 
         if self_ty.span.edition().at_least_rust_2021() {
-            let msg = "expected a type, found a trait";
-            let label = "you can add the `dyn` keyword if you want a trait object";
-            let mut diag =
-                rustc_errors::struct_span_code_err!(self.dcx(), self_ty.span, E0782, "{}", msg);
+            let mut diag = rustc_errors::struct_span_code_err!(
+                self.dcx(),
+                self_ty.span,
+                E0782,
+                "{}",
+                "expected a type, found a trait"
+            );
             if self_ty.span.can_be_used_for_suggestions()
                 && !self.maybe_suggest_impl_trait(self_ty, &mut diag)
-                && !self.maybe_suggest_dyn_trait(self_ty, label, sugg, &mut diag)
+                && !self.maybe_suggest_dyn_trait(self_ty, sugg, &mut diag)
             {
                 self.maybe_suggest_add_generic_impl_trait(self_ty, &mut diag);
             }
@@ -123,31 +126,62 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
+    /// For a struct or enum with an invalid bare trait object field, suggest turning
+    /// it into a generic type bound.
     fn maybe_suggest_add_generic_impl_trait(
         &self,
         self_ty: &hir::Ty<'_>,
         diag: &mut Diag<'_>,
     ) -> bool {
         let tcx = self.tcx();
-        let msg = "you might be missing a type parameter";
-        let mut sugg = vec![];
 
-        let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
-        let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
-        match parent_item.kind {
-            hir::ItemKind::Struct(_, generics) | hir::ItemKind::Enum(_, generics) => {
-                sugg.push((
-                    generics.where_clause_span,
-                    format!(
-                        "<T: {}>",
-                        self.tcx().sess.source_map().span_to_snippet(self_ty.span).unwrap()
-                    ),
-                ));
-                sugg.push((self_ty.span, "T".to_string()));
+        let parent_hir_id = tcx.parent_hir_id(self_ty.hir_id);
+        let parent_item = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
+
+        let generics = match tcx.hir_node_by_def_id(parent_item) {
+            hir::Node::Item(hir::Item {
+                kind: hir::ItemKind::Struct(variant, generics), ..
+            }) => {
+                if !variant.fields().iter().any(|field| field.hir_id == parent_hir_id) {
+                    return false;
+                }
+                generics
             }
-            _ => {}
+            hir::Node::Item(hir::Item { kind: hir::ItemKind::Enum(def, generics), .. }) => {
+                if !def
+                    .variants
+                    .iter()
+                    .flat_map(|variant| variant.data.fields().iter())
+                    .any(|field| field.hir_id == parent_hir_id)
+                {
+                    return false;
+                }
+                generics
+            }
+            _ => return false,
+        };
+
+        let Ok(rendered_ty) = tcx.sess.source_map().span_to_snippet(self_ty.span) else {
+            return false;
+        };
+
+        let param = "TUV"
+            .chars()
+            .map(|c| c.to_string())
+            .chain((0..).map(|i| format!("P{i}")))
+            .find(|s| !generics.params.iter().any(|param| param.name.ident().as_str() == s))
+            .expect("we definitely can find at least one param name to generate");
+        let mut sugg = vec![(self_ty.span, param.to_string())];
+        if let Some(insertion_span) = generics.span_for_param_suggestion() {
+            sugg.push((insertion_span, format!(", {param}: {}", rendered_ty)));
+        } else {
+            sugg.push((generics.where_clause_span, format!("<{param}: {}>", rendered_ty)));
         }
-        diag.multipart_suggestion_verbose(msg, sugg, Applicability::MachineApplicable);
+        diag.multipart_suggestion_verbose(
+            "you might be missing a type parameter",
+            sugg,
+            Applicability::MachineApplicable,
+        );
         true
     }
     /// Make sure that we are in the condition to suggest the blanket implementation.
@@ -198,32 +232,59 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         }
     }
 
+    /// Try our best to approximate when adding `dyn` would be helpful for a bare
+    /// trait object.
+    ///
+    /// Right now, this is if the type is either directly nested in another ty,
+    /// or if it's in the tail field within a struct. This approximates what the
+    /// user would've gotten on edition 2015, except for the case where we have
+    /// an *obvious* knock-on `Sized` error.
     fn maybe_suggest_dyn_trait(
         &self,
         self_ty: &hir::Ty<'_>,
-        label: &str,
         sugg: Vec<(Span, String)>,
         diag: &mut Diag<'_>,
     ) -> bool {
         let tcx = self.tcx();
-        let parent_id = tcx.hir_get_parent_item(self_ty.hir_id).def_id;
-        let parent_item = tcx.hir_node_by_def_id(parent_id).expect_item();
 
-        // If the parent item is an enum, don't suggest the dyn trait.
-        if let hir::ItemKind::Enum(..) = parent_item.kind {
-            return false;
-        }
+        // Look at the direct HIR parent, since we care about the relationship between
+        // the type and the thing that directly encloses it.
+        match tcx.parent_hir_node(self_ty.hir_id) {
+            // These are all generally ok. Namely, when a trait object is nested
+            // into another expression or ty, it's either very certain that they
+            // missed the ty (e.g. `&Trait`) or it's not really possible to tell
+            // what their intention is, so let's not give confusing suggestions and
+            // just mention `dyn`. The user can make up their mind what to do here.
+            hir::Node::Ty(_)
+            | hir::Node::Expr(_)
+            | hir::Node::PatExpr(_)
+            | hir::Node::PathSegment(_)
+            | hir::Node::AssocItemConstraint(_)
+            | hir::Node::TraitRef(_)
+            | hir::Node::Item(_)
+            | hir::Node::WherePredicate(_) => {}
 
-        // If the parent item is a struct, check if self_ty is the last field.
-        if let hir::ItemKind::Struct(variant_data, _) = parent_item.kind {
-            if variant_data.fields().last().unwrap().ty.span != self_ty.span {
-                return false;
+            hir::Node::Field(field) => {
+                // Enums can't have unsized fields, fields can only have an unsized tail field.
+                if let hir::Node::Item(hir::Item {
+                    kind: hir::ItemKind::Struct(variant, _), ..
+                }) = tcx.parent_hir_node(field.hir_id)
+                    && variant
+                        .fields()
+                        .last()
+                        .is_some_and(|tail_field| tail_field.hir_id == field.hir_id)
+                {
+                    // Ok
+                } else {
+                    return false;
+                }
             }
+            _ => return false,
         }
 
         // FIXME: Only emit this suggestion if the trait is dyn-compatible.
         diag.multipart_suggestion_verbose(
-            label.to_string(),
+            "you can add the `dyn` keyword if you want a trait object",
             sugg,
             Applicability::MachineApplicable,
         );
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index dd6c40bfbb8..5f91f1d7b3e 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -2294,18 +2294,14 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
         {
             let anon_const_type = tcx.type_of(param_def_id).instantiate(tcx, args);
 
-            // We must error if the instantiated type has any inference variables as we will
-            // use this type to feed the `type_of` and query results must not contain inference
-            // variables otherwise we will ICE.
-            //
+            // FIXME(generic_const_parameter_types): Ideally we remove these errors below when
+            // we have the ability to intermix typeck of anon const const args with the parent
+            // bodies typeck.
+
             // We also error if the type contains any regions as effectively any region will wind
             // up as a region variable in mir borrowck. It would also be somewhat concerning if
             // hir typeck was using equality but mir borrowck wound up using subtyping as that could
             // result in a non-infer in hir typeck but a region variable in borrowck.
-            //
-            // FIXME(generic_const_parameter_types): Ideally we remove these errors one day when
-            // we have the ability to intermix typeck of anon const const args with the parent
-            // bodies typeck.
             if tcx.features().generic_const_parameter_types()
                 && (anon_const_type.has_free_regions() || anon_const_type.has_erased_regions())
             {
@@ -2316,6 +2312,9 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
                 return ty::Const::new_error(tcx, e);
             }
+            // We must error if the instantiated type has any inference variables as we will
+            // use this type to feed the `type_of` and query results must not contain inference
+            // variables otherwise we will ICE.
             if anon_const_type.has_non_region_infer() {
                 let e = tcx.dcx().span_err(
                     const_arg.span(),
@@ -2324,6 +2323,16 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                 tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
                 return ty::Const::new_error(tcx, e);
             }
+            // We error when the type contains unsubstituted generics since we do not currently
+            // give the anon const any of the generics from the parent.
+            if anon_const_type.has_non_region_param() {
+                let e = tcx.dcx().span_err(
+                    const_arg.span(),
+                    "anonymous constants referencing generics are not yet supported",
+                );
+                tcx.feed_anon_const_type(anon.def_id, ty::EarlyBinder::bind(Ty::new_error(tcx, e)));
+                return ty::Const::new_error(tcx, e);
+            }
 
             tcx.feed_anon_const_type(
                 anon.def_id,
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 0e3721126fb..3067766fb4d 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -117,9 +117,9 @@ impl<'a> State<'a> {
                 self.hardbreak()
             }
             hir::Attribute::Parsed(pa) => {
-                self.word("#[attr=\"");
+                self.word("#[attr = ");
                 pa.print_attribute(self);
-                self.word("\")]");
+                self.word("]");
                 self.hardbreak()
             }
         }
@@ -552,24 +552,6 @@ impl<'a> State<'a> {
         self.word(";")
     }
 
-    fn print_item_type(
-        &mut self,
-        item: &hir::Item<'_>,
-        generics: &hir::Generics<'_>,
-        inner: impl Fn(&mut Self),
-    ) {
-        self.head("type");
-        self.print_ident(item.ident);
-        self.print_generic_params(generics.params);
-        self.end(); // end the inner ibox
-
-        self.print_where_clause(generics);
-        self.space();
-        inner(self);
-        self.word(";");
-        self.end(); // end the outer ibox
-    }
-
     fn print_item(&mut self, item: &hir::Item<'_>) {
         self.hardbreak_if_not_bol();
         self.maybe_print_comment(item.span.lo());
@@ -682,10 +664,17 @@ impl<'a> State<'a> {
                 self.end()
             }
             hir::ItemKind::TyAlias(ty, generics) => {
-                self.print_item_type(item, generics, |state| {
-                    state.word_space("=");
-                    state.print_type(ty);
-                });
+                self.head("type");
+                self.print_ident(item.ident);
+                self.print_generic_params(generics.params);
+                self.end(); // end the inner ibox
+
+                self.print_where_clause(generics);
+                self.space();
+                self.word_space("=");
+                self.print_type(ty);
+                self.word(";");
+                self.end(); // end the outer ibox
             }
             hir::ItemKind::Enum(ref enum_definition, params) => {
                 self.print_enum_def(enum_definition, params, item.ident.name, item.span);
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 786e8b876a6..7e4026db738 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2933,7 +2933,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         let guar = if field.name == kw::Empty {
-            self.dcx().span_delayed_bug(field.span, "field name with no name")
+            self.dcx().span_bug(field.span, "field name with no name")
         } else if self.method_exists_for_diagnostic(
             field,
             base_ty,
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
index c46a42c5de1..da2d6579423 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/_impl.rs
@@ -220,6 +220,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         debug!("fcx {}", self.tag());
 
+        // Don't write user type annotations for const param types, since we give them
+        // identity args just so that we can trivially substitute their `EarlyBinder`.
+        // We enforce that they match their type in MIR later on.
+        if matches!(self.tcx.def_kind(def_id), DefKind::ConstParam) {
+            return;
+        }
+
         if Self::can_contain_user_lifetime_bounds((args, user_self_ty)) {
             let canonicalized = self.canonicalize_user_type_annotation(ty::UserType::new(
                 ty::UserTypeKind::TypeOf(def_id, UserArgs { args, user_self_ty }),
@@ -825,15 +832,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
                 let trait_missing_method =
                     matches!(error, method::MethodError::NoMatch(_)) && ty.normalized.is_trait();
-                if item_name.name != kw::Empty {
-                    self.report_method_error(
-                        hir_id,
-                        ty.normalized,
-                        error,
-                        Expectation::NoExpectation,
-                        trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
-                    );
-                }
+                assert_ne!(item_name.name, kw::Empty);
+                self.report_method_error(
+                    hir_id,
+                    ty.normalized,
+                    error,
+                    Expectation::NoExpectation,
+                    trait_missing_method && span.edition().at_least_rust_2021(), // emits missing method for trait only after edition 2021
+                );
 
                 result
             });
diff --git a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
index ac911c20222..b8517701667 100644
--- a/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
+++ b/compiler/rustc_hir_typeck/src/fn_ctxt/checks.rs
@@ -1636,7 +1636,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             ast::LitKind::Char(_) => tcx.types.char,
             ast::LitKind::Int(_, ast::LitIntType::Signed(t)) => Ty::new_int(tcx, ty::int_ty(t)),
             ast::LitKind::Int(_, ast::LitIntType::Unsigned(t)) => Ty::new_uint(tcx, ty::uint_ty(t)),
-            ast::LitKind::Int(_, ast::LitIntType::Unsuffixed) => {
+            ast::LitKind::Int(i, ast::LitIntType::Unsuffixed) => {
                 let opt_ty = expected.to_option(self).and_then(|ty| match ty.kind() {
                     ty::Int(_) | ty::Uint(_) => Some(ty),
                     // These exist to direct casts like `0x61 as char` to use
@@ -1645,6 +1645,19 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     ty::Char => Some(tcx.types.u8),
                     ty::RawPtr(..) => Some(tcx.types.usize),
                     ty::FnDef(..) | ty::FnPtr(..) => Some(tcx.types.usize),
+                    &ty::Pat(base, _) if base.is_integral() => {
+                        let layout = tcx
+                            .layout_of(self.typing_env(self.param_env).as_query_input(ty))
+                            .ok()?;
+                        assert!(!layout.uninhabited);
+
+                        match layout.backend_repr {
+                            rustc_abi::BackendRepr::Scalar(scalar) => {
+                                scalar.valid_range(&tcx).contains(u128::from(i.get())).then_some(ty)
+                            }
+                            _ => unreachable!(),
+                        }
+                    }
                     _ => None,
                 });
                 opt_ty.unwrap_or_else(|| self.next_int_var())
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 19ae3e3899c..7e6973259fe 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -87,10 +87,10 @@ struct TopInfo<'tcx> {
 }
 
 #[derive(Copy, Clone)]
-struct PatInfo<'a, 'tcx> {
+struct PatInfo<'tcx> {
     binding_mode: ByRef,
     max_ref_mutbl: MutblCap,
-    top_info: &'a TopInfo<'tcx>,
+    top_info: TopInfo<'tcx>,
     decl_origin: Option<DeclOrigin<'tcx>>,
 
     /// The depth of current pattern
@@ -303,11 +303,11 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         origin_expr: Option<&'tcx hir::Expr<'tcx>>,
         decl_origin: Option<DeclOrigin<'tcx>>,
     ) {
-        let info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id };
+        let top_info = TopInfo { expected, origin_expr, span, hir_id: pat.hir_id };
         let pat_info = PatInfo {
             binding_mode: ByRef::No,
             max_ref_mutbl: MutblCap::Mut,
-            top_info: &info,
+            top_info,
             decl_origin,
             current_depth: 0,
         };
@@ -320,7 +320,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// Outside of this module, `check_pat_top` should always be used.
     /// Conversely, inside this module, `check_pat_top` should never be used.
     #[instrument(level = "debug", skip(self, pat_info))]
-    fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'_, 'tcx>) {
+    fn check_pat(&self, pat: &'tcx Pat<'tcx>, expected: Ty<'tcx>, pat_info: PatInfo<'tcx>) {
         let PatInfo { binding_mode, max_ref_mutbl, top_info: ti, current_depth, .. } = pat_info;
 
         let path_res = match pat.kind {
@@ -352,13 +352,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     qpath,
                     path_res.unwrap(),
                     expected,
-                    ti,
+                    &pat_info.top_info,
                 );
                 self.write_ty(*hir_id, ty);
                 ty
             }
-            PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, ti),
-            PatKind::Range(lhs, rhs, _) => self.check_pat_range(pat.span, lhs, rhs, expected, ti),
+            PatKind::Expr(lt) => self.check_pat_lit(pat.span, lt, expected, &pat_info.top_info),
+            PatKind::Range(lhs, rhs, _) => {
+                self.check_pat_range(pat.span, lhs, rhs, expected, &pat_info.top_info)
+            }
             PatKind::Binding(ba, var_id, ident, sub) => {
                 self.check_pat_ident(pat, ba, var_id, ident, sub, expected, pat_info)
             }
@@ -818,7 +820,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         ident: Ident,
         sub: Option<&'tcx Pat<'tcx>>,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let PatInfo { binding_mode: def_br, top_info: ti, .. } = pat_info;
 
@@ -914,12 +916,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // We have a concrete type for the local, so we do not need to taint it and hide follow up errors *using* the local.
-        let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, ti);
+        let _ = self.demand_eqtype_pat(pat.span, eq_ty, local_ty, &ti);
 
         // If there are multiple arms, make sure they all agree on
         // what the type of the binding `x` ought to be.
         if var_id != pat.hir_id {
-            self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, ti);
+            self.check_binding_alt_eq_ty(user_bind_annot, pat.span, var_id, local_ty, &ti);
         }
 
         if let Some(p) = sub {
@@ -1149,7 +1151,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         // Resolve the path and check the definition for errors.
         let (variant, pat_ty) = match self.check_struct_path(qpath, pat.hir_id) {
@@ -1164,7 +1166,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         };
 
         // Type-check the path.
-        let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, pat_info.top_info);
+        let _ = self.demand_eqtype_pat(pat.span, expected, pat_ty, &pat_info.top_info);
 
         // Type-check subpatterns.
         match self.check_struct_pat_fields(pat_ty, pat, variant, fields, has_rest_pat, pat_info) {
@@ -1353,7 +1355,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         subpats: &'tcx [Pat<'tcx>],
         ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let on_error = |e| {
@@ -1403,7 +1405,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let pat_ty = pat_ty.no_bound_vars().expect("expected fn type");
 
         // Type-check the tuple struct pattern against the expected type.
-        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, pat_info.top_info);
+        let diag = self.demand_eqtype_pat_diag(pat.span, expected, pat_ty, &pat_info.top_info);
         let had_err = diag.map_err(|diag| diag.emit());
 
         // Type-check subpatterns.
@@ -1610,7 +1612,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         elements: &'tcx [Pat<'tcx>],
         ddpos: hir::DotDotPos,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let mut expected_len = elements.len();
@@ -1625,7 +1627,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let element_tys_iter = (0..max_len).map(|_| self.next_ty_var(span));
         let element_tys = tcx.mk_type_list_from_iter(element_tys_iter);
         let pat_ty = Ty::new_tup(tcx, element_tys);
-        if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, pat_info.top_info) {
+        if let Err(reported) = self.demand_eqtype_pat(span, expected, pat_ty, &pat_info.top_info) {
             // Walk subpatterns with an expected type of `err` in this case to silence
             // further errors being emitted when using the bindings. #50333
             let element_tys_iter = (0..max_len).map(|_| Ty::new_error(tcx, reported));
@@ -1648,7 +1650,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         variant: &'tcx ty::VariantDef,
         fields: &'tcx [hir::PatField<'tcx>],
         has_rest_pat: bool,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Result<(), ErrorGuaranteed> {
         let tcx = self.tcx;
 
@@ -2257,7 +2259,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         inner: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         let (box_ty, inner_ty) = self
@@ -2267,7 +2269,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // think any errors can be introduced by using `demand::eqtype`.
                 let inner_ty = self.next_ty_var(inner.span);
                 let box_ty = Ty::new_box(tcx, inner_ty);
-                self.demand_eqtype_pat(span, expected, box_ty, pat_info.top_info)?;
+                self.demand_eqtype_pat(span, expected, box_ty, &pat_info.top_info)?;
                 Ok((box_ty, inner_ty))
             })
             .unwrap_or_else(|guar| {
@@ -2283,7 +2285,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         inner: &'tcx Pat<'tcx>,
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
         // Register a `DerefPure` bound, which is required by all `deref!()` pats.
@@ -2324,7 +2326,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         inner: &'tcx Pat<'tcx>,
         pat_mutbl: Mutability,
         mut expected: Ty<'tcx>,
-        mut pat_info: PatInfo<'_, 'tcx>,
+        mut pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let tcx = self.tcx;
 
@@ -2482,7 +2484,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             pat.span,
                             expected,
                             ref_ty,
-                            pat_info.top_info,
+                            &pat_info.top_info,
                         );
 
                         // Look for a case like `fn foo(&foo: u32)` and suggest
@@ -2605,7 +2607,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         slice: Option<&'tcx Pat<'tcx>>,
         after: &'tcx [Pat<'tcx>],
         expected: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> Ty<'tcx> {
         let expected = self.try_structurally_resolve_type(span, expected);
 
@@ -2767,7 +2769,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         span: Span,
         expected_ty: Ty<'tcx>,
-        pat_info: PatInfo<'_, 'tcx>,
+        pat_info: PatInfo<'tcx>,
     ) -> ErrorGuaranteed {
         let PatInfo { top_info: ti, current_depth, .. } = pat_info;
 
diff --git a/compiler/rustc_incremental/Cargo.toml b/compiler/rustc_incremental/Cargo.toml
index 4939bfb3a1c..db0a5841887 100644
--- a/compiler/rustc_incremental/Cargo.toml
+++ b/compiler/rustc_incremental/Cargo.toml
@@ -5,7 +5,7 @@ edition = "2024"
 
 [dependencies]
 # tidy-alphabetical-start
-rand = "0.8.4"
+rand = "0.9.0"
 rustc_ast = { path = "../rustc_ast" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
diff --git a/compiler/rustc_incremental/src/persist/fs.rs b/compiler/rustc_incremental/src/persist/fs.rs
index 19cca48af61..76a1ff3cf38 100644
--- a/compiler/rustc_incremental/src/persist/fs.rs
+++ b/compiler/rustc_incremental/src/persist/fs.rs
@@ -108,7 +108,7 @@ use std::io::{self, ErrorKind};
 use std::path::{Path, PathBuf};
 use std::time::{Duration, SystemTime, UNIX_EPOCH};
 
-use rand::{RngCore, thread_rng};
+use rand::{RngCore, rng};
 use rustc_data_structures::base_n::{BaseNString, CASE_INSENSITIVE, ToBaseN};
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_data_structures::svh::Svh;
@@ -445,7 +445,7 @@ fn copy_files(sess: &Session, target_dir: &Path, source_dir: &Path) -> Result<bo
 fn generate_session_dir_path(crate_dir: &Path) -> PathBuf {
     let timestamp = timestamp_to_string(SystemTime::now());
     debug!("generate_session_dir_path: timestamp = {}", timestamp);
-    let random_number = thread_rng().next_u32();
+    let random_number = rng().next_u32();
     debug!("generate_session_dir_path: random_number = {}", random_number);
 
     // Chop the first 3 characters off the timestamp. Those 3 bytes will be zero for a while.
diff --git a/compiler/rustc_index/src/slice.rs b/compiler/rustc_index/src/slice.rs
index f17ea9e4b59..67ac805c2bf 100644
--- a/compiler/rustc_index/src/slice.rs
+++ b/compiler/rustc_index/src/slice.rs
@@ -1,6 +1,7 @@
 use std::fmt;
 use std::marker::PhantomData;
 use std::ops::{Index, IndexMut};
+use std::slice::GetDisjointMutError::*;
 use std::slice::{self, SliceIndex};
 
 use crate::{Idx, IndexVec, IntoSliceIdx};
@@ -65,6 +66,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
 
     #[inline]
     pub fn iter_enumerated(&self) -> impl DoubleEndedIterator<Item = (I, &T)> + ExactSizeIterator {
+        // Allow the optimizer to elide the bounds checking when creating each index.
+        let _ = I::new(self.len());
         self.raw.iter().enumerate().map(|(n, t)| (I::new(n), t))
     }
 
@@ -72,6 +75,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
     pub fn indices(
         &self,
     ) -> impl DoubleEndedIterator<Item = I> + ExactSizeIterator + Clone + 'static {
+        // Allow the optimizer to elide the bounds checking when creating each index.
+        let _ = I::new(self.len());
         (0..self.len()).map(|n| I::new(n))
     }
 
@@ -84,6 +89,8 @@ impl<I: Idx, T> IndexSlice<I, T> {
     pub fn iter_enumerated_mut(
         &mut self,
     ) -> impl DoubleEndedIterator<Item = (I, &mut T)> + ExactSizeIterator {
+        // Allow the optimizer to elide the bounds checking when creating each index.
+        let _ = I::new(self.len());
         self.raw.iter_mut().enumerate().map(|(n, t)| (I::new(n), t))
     }
 
@@ -115,32 +122,36 @@ impl<I: Idx, T> IndexSlice<I, T> {
 
     /// Returns mutable references to two distinct elements, `a` and `b`.
     ///
-    /// Panics if `a == b`.
+    /// Panics if `a == b` or if some of them are out of bounds.
     #[inline]
     pub fn pick2_mut(&mut self, a: I, b: I) -> (&mut T, &mut T) {
         let (ai, bi) = (a.index(), b.index());
-        assert!(ai != bi);
-
-        if ai < bi {
-            let (c1, c2) = self.raw.split_at_mut(bi);
-            (&mut c1[ai], &mut c2[0])
-        } else {
-            let (c2, c1) = self.pick2_mut(b, a);
-            (c1, c2)
+
+        match self.raw.get_disjoint_mut([ai, bi]) {
+            Ok([a, b]) => (a, b),
+            Err(OverlappingIndices) => panic!("Indices {ai:?} and {bi:?} are not disjoint!"),
+            Err(IndexOutOfBounds) => {
+                panic!("Some indices among ({ai:?}, {bi:?}) are out of bounds")
+            }
         }
     }
 
     /// Returns mutable references to three distinct elements.
     ///
-    /// Panics if the elements are not distinct.
+    /// Panics if the elements are not distinct or if some of them are out of bounds.
     #[inline]
     pub fn pick3_mut(&mut self, a: I, b: I, c: I) -> (&mut T, &mut T, &mut T) {
         let (ai, bi, ci) = (a.index(), b.index(), c.index());
-        assert!(ai != bi && bi != ci && ci != ai);
-        let len = self.raw.len();
-        assert!(ai < len && bi < len && ci < len);
-        let ptr = self.raw.as_mut_ptr();
-        unsafe { (&mut *ptr.add(ai), &mut *ptr.add(bi), &mut *ptr.add(ci)) }
+
+        match self.raw.get_disjoint_mut([ai, bi, ci]) {
+            Ok([a, b, c]) => (a, b, c),
+            Err(OverlappingIndices) => {
+                panic!("Indices {ai:?}, {bi:?} and {ci:?} are not disjoint!")
+            }
+            Err(IndexOutOfBounds) => {
+                panic!("Some indices among ({ai:?}, {bi:?}, {ci:?}) are out of bounds")
+            }
+        }
     }
 
     #[inline]
diff --git a/compiler/rustc_index/src/vec.rs b/compiler/rustc_index/src/vec.rs
index 7f3f3ead5f2..13f0dda180b 100644
--- a/compiler/rustc_index/src/vec.rs
+++ b/compiler/rustc_index/src/vec.rs
@@ -93,6 +93,8 @@ impl<I: Idx, T> IndexVec<I, T> {
     /// be allocated only once, with a capacity of at least `n`.)
     #[inline]
     pub fn from_fn_n(func: impl FnMut(I) -> T, n: usize) -> Self {
+        // Allow the optimizer to elide the bounds checking when creating each index.
+        let _ = I::new(n);
         IndexVec::from_raw((0..n).map(I::new).map(func).collect())
     }
 
@@ -128,6 +130,8 @@ impl<I: Idx, T> IndexVec<I, T> {
     pub fn into_iter_enumerated(
         self,
     ) -> impl DoubleEndedIterator<Item = (I, T)> + ExactSizeIterator {
+        // Allow the optimizer to elide the bounds checking when creating each index.
+        let _ = I::new(self.len());
         self.raw.into_iter().enumerate().map(|(n, t)| (I::new(n), t))
     }
 
diff --git a/compiler/rustc_interface/src/util.rs b/compiler/rustc_interface/src/util.rs
index bc2aae7cd87..5cccab893bb 100644
--- a/compiler/rustc_interface/src/util.rs
+++ b/compiler/rustc_interface/src/util.rs
@@ -39,11 +39,11 @@ pub(crate) fn add_configuration(
 ) {
     let tf = sym::target_feature;
 
-    let unstable_target_features = codegen_backend.target_features_cfg(sess, true);
-    sess.unstable_target_features.extend(unstable_target_features.iter().cloned());
+    let (target_features, unstable_target_features) = codegen_backend.target_features_cfg(sess);
 
-    let target_features = codegen_backend.target_features_cfg(sess, false);
-    sess.target_features.extend(target_features.iter().cloned());
+    sess.unstable_target_features.extend(unstable_target_features.iter().copied());
+
+    sess.target_features.extend(target_features.iter().copied());
 
     cfg.extend(target_features.into_iter().map(|feat| (tf, Some(feat))));
 
diff --git a/compiler/rustc_lint/src/context.rs b/compiler/rustc_lint/src/context.rs
index cd4106ebf83..017ae943e91 100644
--- a/compiler/rustc_lint/src/context.rs
+++ b/compiler/rustc_lint/src/context.rs
@@ -6,6 +6,7 @@
 use std::cell::Cell;
 use std::slice;
 
+use rustc_ast::BindingMode;
 use rustc_data_structures::fx::FxIndexMap;
 use rustc_data_structures::sync;
 use rustc_data_structures::unord::UnordMap;
@@ -14,6 +15,7 @@ use rustc_feature::Features;
 use rustc_hir::def::Res;
 use rustc_hir::def_id::{CrateNum, DefId};
 use rustc_hir::definitions::{DefPathData, DisambiguatedDefPathData};
+use rustc_hir::{Pat, PatKind};
 use rustc_middle::bug;
 use rustc_middle::middle::privacy::EffectiveVisibilities;
 use rustc_middle::ty::layout::{LayoutError, LayoutOfHelpers, TyAndLayout};
@@ -890,7 +892,12 @@ impl<'tcx> LateContext<'tcx> {
             }
             && let Some(init) = match parent_node {
                 hir::Node::Expr(expr) => Some(expr),
-                hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
+                hir::Node::LetStmt(hir::LetStmt {
+                    init,
+                    // Binding is immutable, init cannot be re-assigned
+                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
+                    ..
+                }) => *init,
                 _ => None,
             }
         {
@@ -935,7 +942,12 @@ impl<'tcx> LateContext<'tcx> {
             }
             && let Some(init) = match parent_node {
                 hir::Node::Expr(expr) => Some(expr),
-                hir::Node::LetStmt(hir::LetStmt { init, .. }) => *init,
+                hir::Node::LetStmt(hir::LetStmt {
+                    init,
+                    // Binding is immutable, init cannot be re-assigned
+                    pat: Pat { kind: PatKind::Binding(BindingMode::NONE, ..), .. },
+                    ..
+                }) => *init,
                 hir::Node::Item(item) => match item.kind {
                     hir::ItemKind::Const(.., body_id) | hir::ItemKind::Static(.., body_id) => {
                         Some(self.tcx.hir_body(body_id).value)
diff --git a/compiler/rustc_lint/src/default_could_be_derived.rs b/compiler/rustc_lint/src/default_could_be_derived.rs
index 59e38a882dd..58efca5e994 100644
--- a/compiler/rustc_lint/src/default_could_be_derived.rs
+++ b/compiler/rustc_lint/src/default_could_be_derived.rs
@@ -133,7 +133,7 @@ impl<'tcx> LateLintPass<'tcx> for DefaultCouldBeDerived {
             return;
         }
 
-        // At least one of the fields with a default value have been overriden in
+        // At least one of the fields with a default value have been overridden in
         // the `Default` implementation. We suggest removing it and relying on `..`
         // instead.
         let any_default_field_given =
diff --git a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
index 7eaf83f5acf..659f6d98f03 100644
--- a/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
+++ b/compiler/rustc_lint/src/opaque_hidden_inferred_bound.rs
@@ -43,6 +43,7 @@ declare_lint! {
     ///
     /// type Tait = impl Sized;
     ///
+    /// #[define_opaque(Tait)]
     /// fn test() -> impl Trait<Assoc = Tait> {
     ///     42
     /// }
diff --git a/compiler/rustc_macros/src/print_attribute.rs b/compiler/rustc_macros/src/print_attribute.rs
index 3c6e30b851b..42d94e72ee9 100644
--- a/compiler/rustc_macros/src/print_attribute.rs
+++ b/compiler/rustc_macros/src/print_attribute.rs
@@ -16,12 +16,14 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 let name = field.ident.as_ref().unwrap();
                 let string_name = name.to_string();
                 disps.push(quote! {
-                    if __printed_anything && #name.print_something() {
-                        __p.word_space(",");
+                    if #name.should_render() {
+                        if __printed_anything {
+                            __p.word_space(",");
+                        }
+                        __p.word(#string_name);
+                        __p.word_space(":");
                         __printed_anything = true;
                     }
-                    __p.word(#string_name);
-                    __p.word_space(":");
                     #name.print_attribute(__p);
                 });
                 field_names.push(name);
@@ -31,10 +33,11 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 quote! { {#(#field_names),*} },
                 quote! {
                     __p.word(#string_name);
-                    if true #(&& !#field_names.print_something())* {
+                    if true #(&& !#field_names.should_render())* {
                         return;
                     }
 
+                    __p.nbsp();
                     __p.word("{");
                     #(#disps)*
                     __p.word("}");
@@ -48,8 +51,10 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
             for idx in 0..fields_unnamed.unnamed.len() {
                 let name = format_ident!("f{idx}");
                 disps.push(quote! {
-                    if __printed_anything && #name.print_something() {
-                        __p.word_space(",");
+                    if #name.should_render() {
+                        if __printed_anything {
+                            __p.word_space(",");
+                        }
                         __printed_anything = true;
                     }
                     #name.print_attribute(__p);
@@ -62,13 +67,13 @@ fn print_fields(name: &Ident, fields: &Fields) -> (TokenStream, TokenStream, Tok
                 quote! {
                     __p.word(#string_name);
 
-                    if true #(&& !#field_names.print_something())* {
+                    if true #(&& !#field_names.should_render())* {
                         return;
                     }
 
-                    __p.word("(");
+                    __p.popen();
                     #(#disps)*
-                    __p.word(")");
+                    __p.pclose();
                 },
                 quote! { true },
             )
@@ -138,7 +143,7 @@ pub(crate) fn print_attribute(input: Structure<'_>) -> TokenStream {
     input.gen_impl(quote! {
         #[allow(unused)]
         gen impl PrintAttribute for @Self {
-            fn print_something(&self) -> bool { #printed }
+            fn should_render(&self) -> bool { #printed }
             fn print_attribute(&self, __p: &mut rustc_ast_pretty::pp::Printer) { #code }
         }
     })
diff --git a/compiler/rustc_middle/src/mir/interpret/allocation.rs b/compiler/rustc_middle/src/mir/interpret/allocation.rs
index ba65a711815..b24f6bc7770 100644
--- a/compiler/rustc_middle/src/mir/interpret/allocation.rs
+++ b/compiler/rustc_middle/src/mir/interpret/allocation.rs
@@ -679,6 +679,11 @@ impl<Prov: Provenance, Extra, Bytes: AllocBytes> Allocation<Prov, Extra, Bytes>
         // Set provenance of all bytes to wildcard.
         self.provenance.write_wildcards(self.len());
 
+        // Also expose the provenance of the interpreter-level allocation, so it can
+        // be written by FFI. The `black_box` is defensive programming as LLVM likes
+        // to (incorrectly) optimize away ptr2int casts whose result is unused.
+        std::hint::black_box(self.get_bytes_unchecked_raw_mut().expose_provenance());
+
         Ok(())
     }
 
diff --git a/compiler/rustc_middle/src/mir/interpret/mod.rs b/compiler/rustc_middle/src/mir/interpret/mod.rs
index 2675b7e0fc5..effedf854e4 100644
--- a/compiler/rustc_middle/src/mir/interpret/mod.rs
+++ b/compiler/rustc_middle/src/mir/interpret/mod.rs
@@ -452,12 +452,7 @@ impl<'tcx> TyCtxt<'tcx> {
         }
         let id = self.alloc_map.reserve();
         debug!("creating alloc {:?} with id {id:?}", alloc_salt.0);
-        let had_previous = self
-            .alloc_map
-            .to_alloc
-            .lock_shard_by_value(&id)
-            .insert(id, alloc_salt.0.clone())
-            .is_some();
+        let had_previous = self.alloc_map.to_alloc.insert(id, alloc_salt.0.clone()).is_some();
         // We just reserved, so should always be unique.
         assert!(!had_previous);
         dedup.insert(alloc_salt, id);
@@ -510,7 +505,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// local dangling pointers and allocations in constants/statics.
     #[inline]
     pub fn try_get_global_alloc(self, id: AllocId) -> Option<GlobalAlloc<'tcx>> {
-        self.alloc_map.to_alloc.lock_shard_by_value(&id).get(&id).cloned()
+        self.alloc_map.to_alloc.get(&id)
     }
 
     #[inline]
@@ -529,9 +524,7 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Freezes an `AllocId` created with `reserve` by pointing it at an `Allocation`. Trying to
     /// call this function twice, even with the same `Allocation` will ICE the compiler.
     pub fn set_alloc_id_memory(self, id: AllocId, mem: ConstAllocation<'tcx>) {
-        if let Some(old) =
-            self.alloc_map.to_alloc.lock_shard_by_value(&id).insert(id, GlobalAlloc::Memory(mem))
-        {
+        if let Some(old) = self.alloc_map.to_alloc.insert(id, GlobalAlloc::Memory(mem)) {
             bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
         }
     }
@@ -539,11 +532,8 @@ impl<'tcx> TyCtxt<'tcx> {
     /// Freezes an `AllocId` created with `reserve` by pointing it at a static item. Trying to
     /// call this function twice, even with the same `DefId` will ICE the compiler.
     pub fn set_nested_alloc_id_static(self, id: AllocId, def_id: LocalDefId) {
-        if let Some(old) = self
-            .alloc_map
-            .to_alloc
-            .lock_shard_by_value(&id)
-            .insert(id, GlobalAlloc::Static(def_id.to_def_id()))
+        if let Some(old) =
+            self.alloc_map.to_alloc.insert(id, GlobalAlloc::Static(def_id.to_def_id()))
         {
             bug!("tried to set allocation ID {id:?}, but it was already existing as {old:#?}");
         }
diff --git a/compiler/rustc_middle/src/mir/terminator.rs b/compiler/rustc_middle/src/mir/terminator.rs
index bc77f22af67..b2c51ad8864 100644
--- a/compiler/rustc_middle/src/mir/terminator.rs
+++ b/compiler/rustc_middle/src/mir/terminator.rs
@@ -454,6 +454,7 @@ mod helper {
         /// Like [`SwitchTargets::target_for_value`], but returning the same type as
         /// [`Terminator::successors`].
         #[inline]
+        #[cfg_attr(not(bootstrap), define_opaque(Successors))]
         pub fn successors_for_value(&self, value: u128) -> Successors<'_> {
             let target = self.target_for_value(value);
             (&[]).into_iter().copied().chain(Some(target))
@@ -462,6 +463,7 @@ mod helper {
 
     impl<'tcx> TerminatorKind<'tcx> {
         #[inline]
+        #[cfg_attr(not(bootstrap), define_opaque(Successors))]
         pub fn successors(&self) -> Successors<'_> {
             use self::TerminatorKind::*;
             match *self {
@@ -500,6 +502,7 @@ mod helper {
         }
 
         #[inline]
+        #[cfg_attr(not(bootstrap), define_opaque(SuccessorsMut))]
         pub fn successors_mut(&mut self) -> SuccessorsMut<'_> {
             use self::TerminatorKind::*;
             match *self {
diff --git a/compiler/rustc_middle/src/query/erase.rs b/compiler/rustc_middle/src/query/erase.rs
index 907618e428f..7bbaa0496d5 100644
--- a/compiler/rustc_middle/src/query/erase.rs
+++ b/compiler/rustc_middle/src/query/erase.rs
@@ -24,6 +24,7 @@ pub trait EraseType: Copy {
 pub type Erase<T: EraseType> = Erased<impl Copy>;
 
 #[inline(always)]
+#[cfg_attr(not(bootstrap), define_opaque(Erase))]
 pub fn erase<T: EraseType>(src: T) -> Erase<T> {
     // Ensure the sizes match
     const {
@@ -47,6 +48,7 @@ pub fn erase<T: EraseType>(src: T) -> Erase<T> {
 
 /// Restores an erased value.
 #[inline(always)]
+#[cfg_attr(not(bootstrap), define_opaque(Erase))]
 pub fn restore<T: EraseType>(value: Erase<T>) -> T {
     let value: Erased<<T as EraseType>::Result> = value;
     // See comment in `erase` for why we use `transmute_unchecked`.
diff --git a/compiler/rustc_middle/src/ty/adt.rs b/compiler/rustc_middle/src/ty/adt.rs
index 3585f28b4a5..c1dc6a894ca 100644
--- a/compiler/rustc_middle/src/ty/adt.rs
+++ b/compiler/rustc_middle/src/ty/adt.rs
@@ -53,8 +53,6 @@ bitflags::bitflags! {
         const IS_VARIANT_LIST_NON_EXHAUSTIVE = 1 << 8;
         /// Indicates whether the type is `UnsafeCell`.
         const IS_UNSAFE_CELL              = 1 << 9;
-        /// Indicates whether the type is anonymous.
-        const IS_ANONYMOUS                = 1 << 10;
     }
 }
 rustc_data_structures::external_bitflags_debug! { AdtFlags }
@@ -402,12 +400,6 @@ impl<'tcx> AdtDef<'tcx> {
         self.flags().contains(AdtFlags::IS_MANUALLY_DROP)
     }
 
-    /// Returns `true` if this is an anonymous adt
-    #[inline]
-    pub fn is_anonymous(self) -> bool {
-        self.flags().contains(AdtFlags::IS_ANONYMOUS)
-    }
-
     /// Returns `true` if this type has a destructor.
     pub fn has_dtor(self, tcx: TyCtxt<'tcx>) -> bool {
         self.destructor(tcx).is_some()
diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs
index edba2a2530f..70bb902d1ae 100644
--- a/compiler/rustc_middle/src/ty/context.rs
+++ b/compiler/rustc_middle/src/ty/context.rs
@@ -2336,8 +2336,8 @@ macro_rules! sty_debug_print {
                 $(let mut $variant = total;)*
 
                 for shard in tcx.interners.type_.lock_shards() {
-                    let types = shard.keys();
-                    for &InternedInSet(t) in types {
+                    let types = shard.iter();
+                    for &(InternedInSet(t), ()) in types {
                         let variant = match t.internee {
                             ty::Bool | ty::Char | ty::Int(..) | ty::Uint(..) |
                                 ty::Float(..) | ty::Str | ty::Never => continue,
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index c5509c0a608..97cfe5946af 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1151,7 +1151,7 @@ pub struct VariantDef {
     /// `DefId` that identifies the variant's constructor.
     /// If this variant is a struct variant, then this is `None`.
     pub ctor: Option<(CtorKind, DefId)>,
-    /// Variant or struct name, maybe empty for anonymous adt (struct or union).
+    /// Variant or struct name.
     pub name: Symbol,
     /// Discriminant of this variant.
     pub discr: VariantDiscr,
diff --git a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
index 84c9297e658..f743ea60a45 100644
--- a/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
+++ b/compiler/rustc_mir_build/src/builder/expr/as_constant.rs
@@ -117,7 +117,12 @@ fn lit_to_mir_constant<'tcx>(tcx: TyCtxt<'tcx>, lit_input: LitToConstInput<'tcx>
         ConstValue::Scalar(Scalar::from_uint(result, width))
     };
 
-    let value = match (lit, ty.kind()) {
+    let lit_ty = match *ty.kind() {
+        ty::Pat(base, _) => base,
+        _ => ty,
+    };
+
+    let value = match (lit, lit_ty.kind()) {
         (ast::LitKind::Str(s, _), ty::Ref(_, inner_ty, _)) if inner_ty.is_str() => {
             let s = s.as_str();
             let allocation = Allocation::from_bytes_byte_aligned_immutable(s.as_bytes());
diff --git a/compiler/rustc_mir_build/src/thir/cx/mod.rs b/compiler/rustc_mir_build/src/thir/cx/mod.rs
index 2e069cae426..3d55c1401b6 100644
--- a/compiler/rustc_mir_build/src/thir/cx/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/mod.rs
@@ -207,7 +207,7 @@ impl<'tcx> ThirBuildCx<'tcx> {
         &self,
         hir_id: HirId,
     ) -> Option<ty::CanonicalUserType<'tcx>> {
-        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
     }
 }
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 8dc3f998e09..4bfeab44bf4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -539,7 +539,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         &self,
         hir_id: hir::HirId,
     ) -> Option<ty::CanonicalUserType<'tcx>> {
-        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.typeck_results, hir_id)
+        crate::thir::util::user_args_applied_to_ty_of_hir_id(self.tcx, self.typeck_results, hir_id)
     }
 
     /// Takes a HIR Path. If the path is a constant, evaluates it and feeds
diff --git a/compiler/rustc_mir_build/src/thir/util.rs b/compiler/rustc_mir_build/src/thir/util.rs
index 60a47a94e3a..457957f5fce 100644
--- a/compiler/rustc_mir_build/src/thir/util.rs
+++ b/compiler/rustc_mir_build/src/thir/util.rs
@@ -1,12 +1,16 @@
+use std::assert_matches::assert_matches;
+
 use rustc_hir as hir;
+use rustc_hir::def::DefKind;
 use rustc_middle::bug;
-use rustc_middle::ty::{self, CanonicalUserType};
+use rustc_middle::ty::{self, CanonicalUserType, TyCtxt};
 use tracing::debug;
 
 /// Looks up the type associated with this hir-id and applies the
 /// user-given generic parameters; the hir-id must map to a suitable
 /// type.
 pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
+    tcx: TyCtxt<'tcx>,
     typeck_results: &ty::TypeckResults<'tcx>,
     hir_id: hir::HirId,
 ) -> Option<CanonicalUserType<'tcx>> {
@@ -16,7 +20,23 @@ pub(crate) fn user_args_applied_to_ty_of_hir_id<'tcx>(
     let ty = typeck_results.node_type(hir_id);
     match ty.kind() {
         ty::Adt(adt_def, ..) => {
+            // This "fixes" user type annotations for tupled ctor patterns for ADTs.
+            // That's because `type_of(ctor_did)` returns a FnDef, but we actually
+            // want to be annotating the type of the ADT itself. It's a bit goofy,
+            // but it's easier to adjust this here rather than in the path lowering
+            // code for patterns in HIR.
             if let ty::UserTypeKind::TypeOf(did, _) = &mut user_ty.value.kind {
+                // This is either already set up correctly (struct, union, enum, or variant),
+                // or needs adjusting (ctor). Make sure we don't start adjusting other
+                // user annotations like consts or fn calls.
+                assert_matches!(
+                    tcx.def_kind(*did),
+                    DefKind::Ctor(..)
+                        | DefKind::Struct
+                        | DefKind::Enum
+                        | DefKind::Union
+                        | DefKind::Variant
+                );
                 *did = adt_def.did();
             }
             Some(user_ty)
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
index b0bbec48947..e48ee71c858 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/mod.rs
@@ -271,12 +271,39 @@ where
     /// and will need to clearly document it in the rustc-dev-guide before
     /// stabilization.
     pub(super) fn step_kind_for_source(&self, source: GoalSource) -> PathKind {
-        match (self.current_goal_kind, source) {
-            (_, GoalSource::NormalizeGoal(step_kind)) => step_kind,
-            (CurrentGoalKind::CoinductiveTrait, GoalSource::ImplWhereBound) => {
-                PathKind::Coinductive
+        match source {
+            // We treat these goals as unknown for now. It is likely that most miscellaneous
+            // nested goals will be converted to an inductive variant in the future.
+            //
+            // Having unknown cycles is always the safer option, as changing that to either
+            // succeed or hard error is backwards compatible. If we incorrectly treat a cycle
+            // as inductive even though it should not be, it may be unsound during coherence and
+            // fixing it may cause inference breakage or introduce ambiguity.
+            GoalSource::Misc => PathKind::Unknown,
+            GoalSource::NormalizeGoal(path_kind) => path_kind,
+            GoalSource::ImplWhereBound => {
+                // We currently only consider a cycle coinductive if it steps
+                // into a where-clause of a coinductive trait.
+                //
+                // We probably want to make all traits coinductive in the future,
+                // so we treat cycles involving their where-clauses as ambiguous.
+                if let CurrentGoalKind::CoinductiveTrait = self.current_goal_kind {
+                    PathKind::Coinductive
+                } else {
+                    PathKind::Unknown
+                }
             }
-            _ => PathKind::Inductive,
+            // Relating types is always unproductive. If we were to map proof trees to
+            // corecursive functions as explained in #136824, relating types never
+            // introduces a constructor which could cause the recursion to be guarded.
+            GoalSource::TypeRelating => PathKind::Inductive,
+            // Instantiating a higher ranked goal can never cause the recursion to be
+            // guarded and is therefore unproductive.
+            GoalSource::InstantiateHigherRanked => PathKind::Inductive,
+            // These goal sources are likely unproductive and can be changed to
+            // `PathKind::Inductive`. Keeping them as unknown until we're confident
+            // about this and have an example where it is necessary.
+            GoalSource::AliasBoundConstCondition | GoalSource::AliasWellFormed => PathKind::Unknown,
         }
     }
 
@@ -606,7 +633,7 @@ where
 
             let (NestedNormalizationGoals(nested_goals), _, certainty) = self.evaluate_goal_raw(
                 GoalEvaluationKind::Nested,
-                GoalSource::Misc,
+                GoalSource::TypeRelating,
                 unconstrained_goal,
             )?;
             // Add the nested goals from normalization to our own nested goals.
@@ -683,7 +710,7 @@ where
     pub(super) fn add_normalizes_to_goal(&mut self, mut goal: Goal<I, ty::NormalizesTo<I>>) {
         goal.predicate = goal.predicate.fold_with(&mut ReplaceAliasWithInfer::new(
             self,
-            GoalSource::Misc,
+            GoalSource::TypeRelating,
             goal.param_env,
         ));
         self.inspect.add_normalizes_to_goal(self.delegate, self.max_input_universe, goal);
@@ -939,7 +966,15 @@ where
         rhs: T,
     ) -> Result<(), NoSolution> {
         let goals = self.delegate.relate(param_env, lhs, variance, rhs, self.origin_span)?;
-        self.add_goals(GoalSource::Misc, goals);
+        if cfg!(debug_assertions) {
+            for g in goals.iter() {
+                match g.predicate.kind().skip_binder() {
+                    ty::PredicateKind::Subtype { .. } | ty::PredicateKind::AliasRelate(..) => {}
+                    p => unreachable!("unexpected nested goal in `relate`: {p:?}"),
+                }
+            }
+        }
+        self.add_goals(GoalSource::TypeRelating, goals);
         Ok(())
     }
 
diff --git a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
index 1607fbb1b6a..6a8e0790f7c 100644
--- a/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/inspect/build.rs
@@ -421,7 +421,7 @@ impl<D: SolverDelegate<Interner = I>, I: Interner> ProofTreeBuilder<D> {
         self.add_goal(
             delegate,
             max_input_universe,
-            GoalSource::Misc,
+            GoalSource::TypeRelating,
             goal.with(delegate.cx(), goal.predicate),
         );
     }
diff --git a/compiler/rustc_next_trait_solver/src/solve/mod.rs b/compiler/rustc_next_trait_solver/src/solve/mod.rs
index 1fa35b60304..199f0c7512e 100644
--- a/compiler/rustc_next_trait_solver/src/solve/mod.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/mod.rs
@@ -313,7 +313,9 @@ where
                     ty::AliasRelationDirection::Equate,
                 ),
             );
-            self.add_goal(GoalSource::Misc, alias_relate_goal);
+            // We normalize the self type to be able to relate it with
+            // types from candidates.
+            self.add_goal(GoalSource::TypeRelating, alias_relate_goal);
             self.try_evaluate_added_goals()?;
             Ok(self.resolve_vars_if_possible(normalized_term))
         } else {
diff --git a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
index d9452880071..944d5f0e042 100644
--- a/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/project_goals.rs
@@ -24,7 +24,8 @@ where
                 ty::AliasRelationDirection::Equate,
             ),
         );
-        self.add_goal(GoalSource::Misc, goal);
+        // A projection goal holds if the alias is equal to the expected term.
+        self.add_goal(GoalSource::TypeRelating, goal);
         self.evaluate_added_goals_and_make_canonical_response(Certainty::Yes)
     }
 }
diff --git a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
index 67eb442d2cc..eba496fa226 100644
--- a/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/search_graph.rs
@@ -1,9 +1,9 @@
 use std::convert::Infallible;
 use std::marker::PhantomData;
 
-use rustc_type_ir::Interner;
 use rustc_type_ir::search_graph::{self, PathKind};
-use rustc_type_ir::solve::{CanonicalInput, Certainty, QueryResult};
+use rustc_type_ir::solve::{CanonicalInput, Certainty, NoSolution, QueryResult};
+use rustc_type_ir::{Interner, TypingMode};
 
 use super::inspect::ProofTreeBuilder;
 use super::{FIXPOINT_STEP_LIMIT, has_no_inference_or_external_constraints};
@@ -47,7 +47,24 @@ where
     ) -> QueryResult<I> {
         match kind {
             PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes),
-            PathKind::Inductive => response_no_constraints(cx, input, Certainty::overflow(false)),
+            PathKind::Unknown => response_no_constraints(cx, input, Certainty::overflow(false)),
+            // Even though we know these cycles to be unproductive, we still return
+            // overflow during coherence. This is both as we are not 100% confident in
+            // the implementation yet and any incorrect errors would be unsound there.
+            // The affected cases are also fairly artificial and not necessarily desirable
+            // so keeping this as ambiguity is fine for now.
+            //
+            // See `tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs` for an
+            // example where this would matter. We likely should change these cycles to `NoSolution`
+            // even in coherence once this is a bit more settled.
+            PathKind::Inductive => match input.typing_mode {
+                TypingMode::Coherence => {
+                    response_no_constraints(cx, input, Certainty::overflow(false))
+                }
+                TypingMode::Analysis { .. }
+                | TypingMode::PostBorrowckAnalysis { .. }
+                | TypingMode::PostAnalysis => Err(NoSolution),
+            },
         }
     }
 
@@ -57,12 +74,7 @@ where
         input: CanonicalInput<I>,
         result: QueryResult<I>,
     ) -> bool {
-        match kind {
-            PathKind::Coinductive => response_no_constraints(cx, input, Certainty::Yes) == result,
-            PathKind::Inductive => {
-                response_no_constraints(cx, input, Certainty::overflow(false)) == result
-            }
-        }
+        Self::initial_provisional_result(cx, kind, input) == result
     }
 
     fn on_stack_overflow(
diff --git a/compiler/rustc_parse/src/parser/diagnostics.rs b/compiler/rustc_parse/src/parser/diagnostics.rs
index bb227a58cf1..716ababb008 100644
--- a/compiler/rustc_parse/src/parser/diagnostics.rs
+++ b/compiler/rustc_parse/src/parser/diagnostics.rs
@@ -2107,7 +2107,7 @@ impl<'a> Parser<'a> {
                     ast::GenericBound::Trait(poly) => Some(poly),
                     _ => None,
                 })
-                .last()
+                .next_back()
         {
             err.span_suggestion_verbose(
                 poly.span.shrink_to_hi(),
diff --git a/compiler/rustc_parse/src/parser/item.rs b/compiler/rustc_parse/src/parser/item.rs
index 0b9350c7199..9e6cdfe59bb 100644
--- a/compiler/rustc_parse/src/parser/item.rs
+++ b/compiler/rustc_parse/src/parser/item.rs
@@ -217,7 +217,14 @@ impl<'a> Parser<'a> {
                 self.parse_fn(attrs, fn_parse_mode, lo, vis, case)?;
             (
                 ident,
-                ItemKind::Fn(Box::new(Fn { defaultness: def_(), sig, generics, contract, body })),
+                ItemKind::Fn(Box::new(Fn {
+                    defaultness: def_(),
+                    sig,
+                    generics,
+                    contract,
+                    body,
+                    define_opaque: None,
+                })),
             )
         } else if self.eat_keyword(exp!(Extern)) {
             if self.eat_keyword(exp!(Crate)) {
@@ -639,7 +646,7 @@ impl<'a> Parser<'a> {
 
         let impl_items = self.parse_item_list(attrs, |p| p.parse_impl_item(ForceCollect::No))?;
 
-        let item_kind = match ty_second {
+        let (of_trait, self_ty) = match ty_second {
             Some(ty_second) => {
                 // impl Trait for Type
                 if !has_for {
@@ -672,31 +679,20 @@ impl<'a> Parser<'a> {
                 };
                 let trait_ref = TraitRef { path, ref_id: ty_first.id };
 
-                ItemKind::Impl(Box::new(Impl {
-                    safety,
-                    polarity,
-                    defaultness,
-                    constness,
-                    generics,
-                    of_trait: Some(trait_ref),
-                    self_ty: ty_second,
-                    items: impl_items,
-                }))
-            }
-            None => {
-                // impl Type
-                ItemKind::Impl(Box::new(Impl {
-                    safety,
-                    polarity,
-                    defaultness,
-                    constness,
-                    generics,
-                    of_trait: None,
-                    self_ty: ty_first,
-                    items: impl_items,
-                }))
+                (Some(trait_ref), ty_second)
             }
+            None => (None, ty_first), // impl Type
         };
+        let item_kind = ItemKind::Impl(Box::new(Impl {
+            safety,
+            polarity,
+            defaultness,
+            constness,
+            generics,
+            of_trait,
+            self_ty,
+            items: impl_items,
+        }));
 
         Ok((Ident::empty(), item_kind))
     }
diff --git a/compiler/rustc_parse_format/src/lib.rs b/compiler/rustc_parse_format/src/lib.rs
index 287bd8678da..5b8a2fe52d3 100644
--- a/compiler/rustc_parse_format/src/lib.rs
+++ b/compiler/rustc_parse_format/src/lib.rs
@@ -189,7 +189,7 @@ pub enum DebugHex {
 #[derive(Copy, Clone, Debug, PartialEq)]
 pub enum Count<'a> {
     /// The count is specified explicitly.
-    CountIs(usize),
+    CountIs(u16),
     /// The count is specified by the argument with the given name.
     CountIsName(&'a str, InnerSpan),
     /// The count is specified by the argument at the given index.
@@ -564,7 +564,7 @@ impl<'a> Parser<'a> {
     /// consuming a macro argument, `None` if it's the case.
     fn position(&mut self) -> Option<Position<'a>> {
         if let Some(i) = self.integer() {
-            Some(ArgumentIs(i))
+            Some(ArgumentIs(i.into()))
         } else {
             match self.cur.peek() {
                 Some(&(lo, c)) if rustc_lexer::is_id_start(c) => {
@@ -770,7 +770,7 @@ impl<'a> Parser<'a> {
     /// width.
     fn count(&mut self, start: usize) -> Count<'a> {
         if let Some(i) = self.integer() {
-            if self.consume('$') { CountIsParam(i) } else { CountIs(i) }
+            if self.consume('$') { CountIsParam(i.into()) } else { CountIs(i) }
         } else {
             let tmp = self.cur.clone();
             let word = self.word();
@@ -821,15 +821,15 @@ impl<'a> Parser<'a> {
         word
     }
 
-    fn integer(&mut self) -> Option<usize> {
-        let mut cur: usize = 0;
+    fn integer(&mut self) -> Option<u16> {
+        let mut cur: u16 = 0;
         let mut found = false;
         let mut overflow = false;
         let start = self.current_pos();
         while let Some(&(_, c)) = self.cur.peek() {
             if let Some(i) = c.to_digit(10) {
                 let (tmp, mul_overflow) = cur.overflowing_mul(10);
-                let (tmp, add_overflow) = tmp.overflowing_add(i as usize);
+                let (tmp, add_overflow) = tmp.overflowing_add(i as u16);
                 if mul_overflow || add_overflow {
                     overflow = true;
                 }
@@ -846,11 +846,11 @@ impl<'a> Parser<'a> {
             let overflowed_int = &self.input[start..end];
             self.err(
                 format!(
-                    "integer `{}` does not fit into the type `usize` whose range is `0..={}`",
+                    "integer `{}` does not fit into the type `u16` whose range is `0..={}`",
                     overflowed_int,
-                    usize::MAX
+                    u16::MAX
                 ),
-                "integer out of range for `usize`",
+                "integer out of range for `u16`",
                 self.span(start, end),
             );
         }
diff --git a/compiler/rustc_privacy/src/lib.rs b/compiler/rustc_privacy/src/lib.rs
index 5e3e8d69b60..6b4acc1e7a8 100644
--- a/compiler/rustc_privacy/src/lib.rs
+++ b/compiler/rustc_privacy/src/lib.rs
@@ -39,7 +39,7 @@ use rustc_middle::ty::{
 use rustc_middle::{bug, span_bug};
 use rustc_session::lint;
 use rustc_span::hygiene::Transparency;
-use rustc_span::{Ident, Span, Symbol, kw, sym};
+use rustc_span::{Ident, Span, Symbol, sym};
 use tracing::debug;
 use {rustc_attr_parsing as attr, rustc_hir as hir};
 
@@ -934,8 +934,8 @@ impl<'tcx> NamePrivacyVisitor<'tcx> {
         }
 
         // definition of the field
-        let ident = Ident::new(kw::Empty, use_ctxt);
-        let def_id = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id).1;
+        let ident = Ident::new(sym::dummy, use_ctxt);
+        let (_, def_id) = self.tcx.adjust_ident_and_get_scope(ident, def.did(), hir_id);
         !field.vis.is_accessible_from(def_id, self.tcx)
     }
 
diff --git a/compiler/rustc_query_system/src/dep_graph/graph.rs b/compiler/rustc_query_system/src/dep_graph/graph.rs
index 6ece01c211b..3109d53cd2c 100644
--- a/compiler/rustc_query_system/src/dep_graph/graph.rs
+++ b/compiler/rustc_query_system/src/dep_graph/graph.rs
@@ -1,5 +1,4 @@
 use std::assert_matches::assert_matches;
-use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -9,7 +8,7 @@ use std::sync::atomic::{AtomicU32, Ordering};
 use rustc_data_structures::fingerprint::Fingerprint;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::profiling::{QueryInvocationId, SelfProfilerRef};
-use rustc_data_structures::sharded::{self, Sharded};
+use rustc_data_structures::sharded::{self, ShardedHashMap};
 use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
 use rustc_data_structures::sync::{AtomicU64, Lock};
 use rustc_data_structures::unord::UnordMap;
@@ -619,7 +618,7 @@ impl<D: Deps> DepGraphData<D> {
         if let Some(prev_index) = self.previous.node_to_index_opt(dep_node) {
             self.current.prev_index_to_index.lock()[prev_index]
         } else {
-            self.current.new_node_to_index.lock_shard_by_value(dep_node).get(dep_node).copied()
+            self.current.new_node_to_index.get(dep_node)
         }
     }
 
@@ -1048,7 +1047,7 @@ rustc_index::newtype_index! {
 /// first, and `data` second.
 pub(super) struct CurrentDepGraph<D: Deps> {
     encoder: GraphEncoder<D>,
-    new_node_to_index: Sharded<FxHashMap<DepNode, DepNodeIndex>>,
+    new_node_to_index: ShardedHashMap<DepNode, DepNodeIndex>,
     prev_index_to_index: Lock<IndexVec<SerializedDepNodeIndex, Option<DepNodeIndex>>>,
 
     /// This is used to verify that fingerprints do not change between the creation of a node
@@ -1117,12 +1116,9 @@ impl<D: Deps> CurrentDepGraph<D> {
                 profiler,
                 previous,
             ),
-            new_node_to_index: Sharded::new(|| {
-                FxHashMap::with_capacity_and_hasher(
-                    new_node_count_estimate / sharded::shards(),
-                    Default::default(),
-                )
-            }),
+            new_node_to_index: ShardedHashMap::with_capacity(
+                new_node_count_estimate / sharded::shards(),
+            ),
             prev_index_to_index: Lock::new(IndexVec::from_elem_n(None, prev_graph_node_count)),
             anon_id_seed,
             #[cfg(debug_assertions)]
@@ -1152,14 +1148,9 @@ impl<D: Deps> CurrentDepGraph<D> {
         edges: EdgesVec,
         current_fingerprint: Fingerprint,
     ) -> DepNodeIndex {
-        let dep_node_index = match self.new_node_to_index.lock_shard_by_value(&key).entry(key) {
-            Entry::Occupied(entry) => *entry.get(),
-            Entry::Vacant(entry) => {
-                let dep_node_index = self.encoder.send(key, current_fingerprint, edges);
-                entry.insert(dep_node_index);
-                dep_node_index
-            }
-        };
+        let dep_node_index = self
+            .new_node_to_index
+            .get_or_insert_with(key, || self.encoder.send(key, current_fingerprint, edges));
 
         #[cfg(debug_assertions)]
         self.record_edge(dep_node_index, key, current_fingerprint);
@@ -1257,7 +1248,7 @@ impl<D: Deps> CurrentDepGraph<D> {
     ) {
         let node = &prev_graph.index_to_node(prev_index);
         debug_assert!(
-            !self.new_node_to_index.lock_shard_by_value(node).contains_key(node),
+            !self.new_node_to_index.get(node).is_some(),
             "node from previous graph present in new node collection"
         );
     }
@@ -1382,7 +1373,7 @@ fn panic_on_forbidden_read<D: Deps>(data: &DepGraphData<D>, dep_node_index: DepN
     if dep_node.is_none() {
         // Try to find it among the new nodes
         for shard in data.current.new_node_to_index.lock_shards() {
-            if let Some((node, _)) = shard.iter().find(|(_, index)| **index == dep_node_index) {
+            if let Some((node, _)) = shard.iter().find(|(_, index)| *index == dep_node_index) {
                 dep_node = Some(*node);
                 break;
             }
diff --git a/compiler/rustc_query_system/src/lib.rs b/compiler/rustc_query_system/src/lib.rs
index a546362414c..2aedd365adc 100644
--- a/compiler/rustc_query_system/src/lib.rs
+++ b/compiler/rustc_query_system/src/lib.rs
@@ -3,7 +3,6 @@
 #![feature(assert_matches)]
 #![feature(core_intrinsics)]
 #![feature(dropck_eyepatch)]
-#![feature(hash_raw_entry)]
 #![feature(let_chains)]
 #![feature(min_specialization)]
 // tidy-alphabetical-end
diff --git a/compiler/rustc_query_system/src/query/caches.rs b/compiler/rustc_query_system/src/query/caches.rs
index 3b47e7eba0f..30b5d7e5954 100644
--- a/compiler/rustc_query_system/src/query/caches.rs
+++ b/compiler/rustc_query_system/src/query/caches.rs
@@ -2,8 +2,7 @@ use std::fmt::Debug;
 use std::hash::Hash;
 use std::sync::OnceLock;
 
-use rustc_data_structures::fx::FxHashMap;
-use rustc_data_structures::sharded::{self, Sharded};
+use rustc_data_structures::sharded::ShardedHashMap;
 pub use rustc_data_structures::vec_cache::VecCache;
 use rustc_hir::def_id::LOCAL_CRATE;
 use rustc_index::Idx;
@@ -36,7 +35,7 @@ pub trait QueryCache: Sized {
 /// In-memory cache for queries whose keys aren't suitable for any of the
 /// more specialized kinds of cache. Backed by a sharded hashmap.
 pub struct DefaultCache<K, V> {
-    cache: Sharded<FxHashMap<K, (V, DepNodeIndex)>>,
+    cache: ShardedHashMap<K, (V, DepNodeIndex)>,
 }
 
 impl<K, V> Default for DefaultCache<K, V> {
@@ -55,19 +54,14 @@ where
 
     #[inline(always)]
     fn lookup(&self, key: &K) -> Option<(V, DepNodeIndex)> {
-        let key_hash = sharded::make_hash(key);
-        let lock = self.cache.lock_shard_by_hash(key_hash);
-        let result = lock.raw_entry().from_key_hashed_nocheck(key_hash, key);
-
-        if let Some((_, value)) = result { Some(*value) } else { None }
+        self.cache.get(key)
     }
 
     #[inline]
     fn complete(&self, key: K, value: V, index: DepNodeIndex) {
-        let mut lock = self.cache.lock_shard_by_value(&key);
         // We may be overwriting another value. This is all right, since the dep-graph
         // will check that the fingerprint matches.
-        lock.insert(key, (value, index));
+        self.cache.insert(key, (value, index));
     }
 
     fn iter(&self, f: &mut dyn FnMut(&Self::Key, &Self::Value, DepNodeIndex)) {
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index e3405c89b79..88d1126de1a 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -2266,7 +2266,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     && !first.ident.is_path_segment_keyword() =>
             {
                 // Insert a placeholder that's later replaced by `self`/`super`/etc.
-                path.insert(0, Segment::from_ident(Ident::empty()));
+                path.insert(0, Segment::from_ident(Ident::dummy()));
             }
             _ => return None,
         }
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 79479986d07..2c3e4bb505c 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -397,32 +397,37 @@ pub(crate) enum AliasPossibility {
 
 #[derive(Copy, Clone, Debug)]
 pub(crate) enum PathSource<'a> {
-    // Type paths `Path`.
+    /// Type paths `Path`.
     Type,
-    // Trait paths in bounds or impls.
+    /// Trait paths in bounds or impls.
     Trait(AliasPossibility),
-    // Expression paths `path`, with optional parent context.
+    /// Expression paths `path`, with optional parent context.
     Expr(Option<&'a Expr>),
-    // Paths in path patterns `Path`.
+    /// Paths in path patterns `Path`.
     Pat,
-    // Paths in struct expressions and patterns `Path { .. }`.
+    /// Paths in struct expressions and patterns `Path { .. }`.
     Struct,
-    // Paths in tuple struct patterns `Path(..)`.
+    /// Paths in tuple struct patterns `Path(..)`.
     TupleStruct(Span, &'a [Span]),
-    // `m::A::B` in `<T as m::A>::B::C`.
+    /// `m::A::B` in `<T as m::A>::B::C`.
     TraitItem(Namespace),
-    // Paths in delegation item
+    /// Paths in delegation item
     Delegation,
     /// An arg in a `use<'a, N>` precise-capturing bound.
     PreciseCapturingArg(Namespace),
-    // Paths that end with `(..)`, for return type notation.
+    /// Paths that end with `(..)`, for return type notation.
     ReturnTypeNotation,
+    /// Paths from `#[define_opaque]` attributes
+    DefineOpaques,
 }
 
 impl<'a> PathSource<'a> {
     fn namespace(self) -> Namespace {
         match self {
-            PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
+            PathSource::Type
+            | PathSource::Trait(_)
+            | PathSource::Struct
+            | PathSource::DefineOpaques => TypeNS,
             PathSource::Expr(..)
             | PathSource::Pat
             | PathSource::TupleStruct(..)
@@ -443,6 +448,7 @@ impl<'a> PathSource<'a> {
             | PathSource::ReturnTypeNotation => true,
             PathSource::Trait(_)
             | PathSource::TraitItem(..)
+            | PathSource::DefineOpaques
             | PathSource::Delegation
             | PathSource::PreciseCapturingArg(..) => false,
         }
@@ -450,6 +456,7 @@ impl<'a> PathSource<'a> {
 
     fn descr_expected(self) -> &'static str {
         match &self {
+            PathSource::DefineOpaques => "type alias or associated type with opaqaue types",
             PathSource::Type => "type",
             PathSource::Trait(_) => "trait",
             PathSource::Pat => "unit struct, unit variant or constant",
@@ -493,6 +500,19 @@ impl<'a> PathSource<'a> {
 
     pub(crate) fn is_expected(self, res: Res) -> bool {
         match self {
+            PathSource::DefineOpaques => {
+                matches!(
+                    res,
+                    Res::Def(
+                        DefKind::Struct
+                            | DefKind::Union
+                            | DefKind::Enum
+                            | DefKind::TyAlias
+                            | DefKind::AssocTy,
+                        _
+                    ) | Res::SelfTyAlias { .. }
+                )
+            }
             PathSource::Type => matches!(
                 res,
                 Res::Def(
@@ -572,16 +592,16 @@ impl<'a> PathSource<'a> {
         match (self, has_unexpected_resolution) {
             (PathSource::Trait(_), true) => E0404,
             (PathSource::Trait(_), false) => E0405,
-            (PathSource::Type, true) => E0573,
-            (PathSource::Type, false) => E0412,
+            (PathSource::Type | PathSource::DefineOpaques, true) => E0573,
+            (PathSource::Type | PathSource::DefineOpaques, false) => E0412,
             (PathSource::Struct, true) => E0574,
             (PathSource::Struct, false) => E0422,
             (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
             (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
             (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
             (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
-            (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
-            (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
+            (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, true) => E0575,
+            (PathSource::TraitItem(..) | PathSource::ReturnTypeNotation, false) => E0576,
             (PathSource::PreciseCapturingArg(..), true) => E0799,
             (PathSource::PreciseCapturingArg(..), false) => E0800,
         }
@@ -2006,6 +2026,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 | PathSource::Pat
                 | PathSource::Struct
                 | PathSource::TupleStruct(..)
+                | PathSource::DefineOpaques
                 | PathSource::Delegation => true,
             };
             if inferred {
@@ -2619,7 +2640,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 );
             }
 
-            ItemKind::Fn(box Fn { ref generics, .. }) => {
+            ItemKind::Fn(box Fn { ref generics, ref define_opaque, .. }) => {
                 self.with_generic_param_rib(
                     &generics.params,
                     RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
@@ -2630,6 +2651,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     },
                     |this| visit::walk_item(this, item),
                 );
+
+                for (id, path) in define_opaque.iter().flatten() {
+                    self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
+                }
             }
 
             ItemKind::Enum(_, ref generics)
@@ -3100,8 +3125,12 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         },
                     );
                 }
-                AssocItemKind::Fn(box Fn { generics, .. }) => {
+                AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
                     walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
+
+                    for (id, path) in define_opaque.iter().flatten() {
+                        self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
+                    }
                 }
                 AssocItemKind::Delegation(delegation) => {
                     self.with_generic_param_rib(
@@ -3311,7 +3340,7 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     },
                 );
             }
-            AssocItemKind::Fn(box Fn { generics, .. }) => {
+            AssocItemKind::Fn(box Fn { generics, define_opaque, .. }) => {
                 debug!("resolve_implementation AssocItemKind::Fn");
                 // We also need a new scope for the impl item type parameters.
                 self.with_generic_param_rib(
@@ -3338,6 +3367,10 @@ impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                         visit::walk_assoc_item(this, item, AssocCtxt::Impl)
                     },
                 );
+
+                for (id, path) in define_opaque.iter().flatten() {
+                    self.smart_resolve_path(*id, &None, path, PathSource::DefineOpaques);
+                }
             }
             AssocItemKind::Type(box TyAlias { generics, .. }) => {
                 self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 9e7f5047eb3..8a8bec35d81 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -33,6 +33,15 @@ symbols! {
         // Special reserved identifiers used internally for elided lifetimes,
         // unnamed method parameters, crate root module, error recovery etc.
         // Matching predicates: `is_any_keyword`, `is_special`/`is_reserved`
+        //
+        // Notes about `kw::Empty`:
+        // - Its use can blur the lines between "empty symbol" and "no symbol".
+        //   Using `Option<Symbol>` is preferable, where possible, because that
+        //   is unambiguous.
+        // - For dummy symbols that are never used and absolutely must be
+        //   present, it's better to use `sym::dummy` than `kw::Empty`, because
+        //   it's clearer that it's intended as a dummy value, and more likely
+        //   to be detected if it accidentally does get used.
         Empty:              "",
         PathRoot:           "{{root}}",
         DollarCrate:        "$crate",
@@ -779,6 +788,7 @@ symbols! {
         default_method_body_is_const,
         default_type_parameter_fallback,
         default_type_params,
+        define_opaque,
         delayed_bug_from_inside_query,
         deny,
         deprecated,
@@ -833,6 +843,7 @@ symbols! {
         drop_types_in_const,
         dropck_eyepatch,
         dropck_parametricity,
+        dummy: "<!dummy!>", // use this instead of `kw::Empty` for symbols that won't be used
         dummy_cgu_name,
         dylib,
         dyn_compatible_for_dispatch,
@@ -1016,6 +1027,7 @@ symbols! {
         from_residual,
         from_size_align_unchecked,
         from_str_method,
+        from_u16,
         from_usize,
         from_yeet,
         fs_create_dir,
@@ -2303,11 +2315,23 @@ impl Ident {
         Ident::new(name, DUMMY_SP)
     }
 
+    /// This is best avoided, because it blurs the lines between "empty
+    /// identifier" and "no identifier". Using `Option<Ident>` is preferable,
+    /// where possible, because that is unambiguous.
     #[inline]
     pub fn empty() -> Ident {
         Ident::with_dummy_span(kw::Empty)
     }
 
+    // For dummy identifiers that are never used and absolutely must be
+    // present, it's better to use `Ident::dummy` than `Ident::Empty`, because
+    // it's clearer that it's intended as a dummy value, and more likely to be
+    // detected if it accidentally does get used.
+    #[inline]
+    pub fn dummy() -> Ident {
+        Ident::with_dummy_span(sym::dummy)
+    }
+
     /// Maps a string to an identifier with a dummy span.
     pub fn from_str(string: &str) -> Ident {
         Ident::with_dummy_span(Symbol::intern(string))
diff --git a/compiler/rustc_target/src/spec/base/linux_wasm.rs b/compiler/rustc_target/src/spec/base/linux_wasm.rs
new file mode 100644
index 00000000000..a8c137c22a9
--- /dev/null
+++ b/compiler/rustc_target/src/spec/base/linux_wasm.rs
@@ -0,0 +1,159 @@
+//! This target is a confluence of Linux and Wasm models, inheriting most
+//! aspects from their respective base targets
+
+use crate::spec::{
+    Cc, LinkSelfContainedDefault, LinkerFlavor, PanicStrategy, RelocModel, TargetOptions, TlsModel,
+    add_link_args, crt_objects, cvs,
+};
+
+pub(crate) fn opts() -> TargetOptions {
+    macro_rules! args {
+        ($prefix:literal) => {
+            &[
+                // By default LLD only gives us one page of stack (64k) which is a
+                // little small. Default to a larger stack closer to other PC platforms
+                // (1MB) and users can always inject their own link-args to override this.
+                concat!($prefix, "-z"),
+                concat!($prefix, "stack-size=1048576"),
+                // By default LLD's memory layout is:
+                //
+                // 1. First, a blank page
+                // 2. Next, all static data
+                // 3. Finally, the main stack (which grows down)
+                //
+                // This has the unfortunate consequence that on stack overflows you
+                // corrupt static data and can cause some exceedingly weird bugs. To
+                // help detect this a little sooner we instead request that the stack is
+                // placed before static data.
+                //
+                // This means that we'll generate slightly larger binaries as references
+                // to static data will take more bytes in the ULEB128 encoding, but
+                // stack overflow will be guaranteed to trap as it underflows instead of
+                // corrupting static data.
+                concat!($prefix, "--stack-first"),
+                // FIXME we probably shouldn't pass this but instead pass an explicit list
+                // of symbols we'll allow to be undefined. We don't currently have a
+                // mechanism of knowing, however, which symbols are intended to be imported
+                // from the environment and which are intended to be imported from other
+                // objects linked elsewhere. This is a coarse approximation but is sure to
+                // hide some bugs and frustrate someone at some point, so we should ideally
+                // work towards a world where we can explicitly list symbols that are
+                // supposed to be imported and have all other symbols generate errors if
+                // they remain undefined.
+                concat!($prefix, "--allow-undefined"),
+                // LLD only implements C++-like demangling, which doesn't match our own
+                // mangling scheme. Tell LLD to not demangle anything and leave it up to
+                // us to demangle these symbols later. Currently rustc does not perform
+                // further demangling, but tools like twiggy and wasm-bindgen are intended
+                // to do so.
+                concat!($prefix, "--no-demangle"),
+            ]
+        };
+    }
+
+    let mut pre_link_args = TargetOptions::link_args(LinkerFlavor::WasmLld(Cc::No), args!(""));
+    add_link_args(&mut pre_link_args, LinkerFlavor::WasmLld(Cc::Yes), args!("-Wl,"));
+
+    TargetOptions {
+        is_like_wasm: true,
+        families: cvs!["wasm", "unix"],
+        os: "linux".into(),
+        env: "musl".into(),
+
+        // we allow dynamic linking, but only cdylibs. Basically we allow a
+        // final library artifact that exports some symbols (a wasm module) but
+        // we don't allow intermediate `dylib` crate types
+        dynamic_linking: true,
+        only_cdylib: true,
+
+        // relatively self-explanatory!
+        exe_suffix: ".wasm".into(),
+        dll_prefix: "".into(),
+        dll_suffix: ".wasm".into(),
+        eh_frame_header: false,
+
+        max_atomic_width: Some(64),
+
+        // Unwinding doesn't work right now, so the whole target unconditionally
+        // defaults to panic=abort. Note that this is guaranteed to change in
+        // the future once unwinding is implemented. Don't rely on this as we're
+        // basically guaranteed to change it once WebAssembly supports
+        // exceptions.
+        panic_strategy: PanicStrategy::Abort,
+
+        // Symbol visibility takes care of this for the WebAssembly.
+        // Additionally the only known linker, LLD, doesn't support the script
+        // arguments just yet
+        limit_rdylib_exports: false,
+
+        // we use the LLD shipped with the Rust toolchain by default
+        linker: Some("rust-lld".into()),
+        linker_flavor: LinkerFlavor::WasmLld(Cc::No),
+
+        pre_link_args,
+
+        // FIXME: Figure out cases in which WASM needs to link with a native toolchain.
+        //
+        // rust-lang/rust#104137: cannot blindly remove this without putting in
+        // some other way to compensate for lack of `-nostartfiles` in linker
+        // invocation.
+        link_self_contained: LinkSelfContainedDefault::True,
+        pre_link_objects_self_contained: crt_objects::pre_wasi_self_contained(),
+        post_link_objects_self_contained: crt_objects::post_wasi_self_contained(),
+
+        // This has no effect in LLVM 8 or prior, but in LLVM 9 and later when
+        // PIC code is implemented this has quite a drastic effect if it stays
+        // at the default, `pic`. In an effort to keep wasm binaries as minimal
+        // as possible we're defaulting to `static` for now, but the hope is
+        // that eventually we can ship a `pic`-compatible standard library which
+        // works with `static` as well (or works with some method of generating
+        // non-relative calls and such later on).
+        relocation_model: RelocModel::Static,
+
+        // When the atomics feature is activated then these two keys matter,
+        // otherwise they're basically ignored by the standard library. In this
+        // mode, however, the `#[thread_local]` attribute works (i.e.
+        // `has_thread_local`) and we need to get it to work by specifying
+        // `local-exec` as that's all that's implemented in LLVM today for wasm.
+        has_thread_local: true,
+        tls_model: TlsModel::LocalExec,
+
+        // Supporting Linux requires multithreading supported by Wasm's thread
+        // proposal
+        singlethread: false,
+
+        // gdb scripts don't work on wasm blobs
+        emit_debug_gdb_scripts: false,
+
+        // There's more discussion of this at
+        // https://bugs.llvm.org/show_bug.cgi?id=52442 but the general result is
+        // that this isn't useful for wasm and has tricky issues with
+        // representation, so this is disabled.
+        generate_arange_section: false,
+
+        // Right now this is a bit of a workaround but we're currently saying that
+        // the target by default has a static crt which we're taking as a signal
+        // for "use the bundled crt". If that's turned off then the system's crt
+        // will be used, but this means that default usage of this target doesn't
+        // need an external compiler but it's still interoperable with an external
+        // compiler if configured correctly.
+        crt_static_default: true,
+        crt_static_respected: true,
+
+        // Allow `+crt-static` to create a "cdylib" output which is just a wasm file
+        // without a main function.
+        crt_static_allows_dylibs: true,
+
+        // Wasm start ignores arguments -- relies on API call from interface.
+        main_needs_argc_argv: false,
+
+        // Wasm toolchains mangle the name of "main" to distinguish between different
+        // signatures.
+        entry_name: "__main_void".into(),
+
+        // Wasm Feature flags for supporting Linux
+        features: "+atomics,+bulk-memory,+mutable-globals,+sign-ext".into(),
+
+        ..Default::default()
+    }
+}
diff --git a/compiler/rustc_target/src/spec/base/mod.rs b/compiler/rustc_target/src/spec/base/mod.rs
index 6f88be5d37f..e8fdc871785 100644
--- a/compiler/rustc_target/src/spec/base/mod.rs
+++ b/compiler/rustc_target/src/spec/base/mod.rs
@@ -18,6 +18,7 @@ pub(crate) mod linux_gnu;
 pub(crate) mod linux_musl;
 pub(crate) mod linux_ohos;
 pub(crate) mod linux_uclibc;
+pub(crate) mod linux_wasm;
 pub(crate) mod msvc;
 pub(crate) mod netbsd;
 pub(crate) mod nto_qnx;
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 15936c731ea..1887134c575 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -1924,6 +1924,7 @@ supported_targets! {
     ("wasm32-wasip1", wasm32_wasip1),
     ("wasm32-wasip2", wasm32_wasip2),
     ("wasm32-wasip1-threads", wasm32_wasip1_threads),
+    ("wasm32-wali-linux-musl", wasm32_wali_linux_musl),
     ("wasm64-unknown-unknown", wasm64_unknown_unknown),
 
     ("thumbv6m-none-eabi", thumbv6m_none_eabi),
diff --git a/compiler/rustc_target/src/spec/targets/wasm32_wali_linux_musl.rs b/compiler/rustc_target/src/spec/targets/wasm32_wali_linux_musl.rs
new file mode 100644
index 00000000000..a0eb4a254fc
--- /dev/null
+++ b/compiler/rustc_target/src/spec/targets/wasm32_wali_linux_musl.rs
@@ -0,0 +1,29 @@
+//! The `wasm32-wali-linux-musl` target is a wasm32 target compliant with the
+//! [WebAssembly Linux Interface](https://github.com/arjunr2/WALI).
+
+use crate::spec::{Cc, LinkerFlavor, Target, TargetMetadata, base};
+
+pub(crate) fn target() -> Target {
+    let mut options = base::linux_wasm::opts();
+
+    options
+        .add_pre_link_args(LinkerFlavor::WasmLld(Cc::No), &["--export-memory", "--shared-memory"]);
+    options.add_pre_link_args(
+        LinkerFlavor::WasmLld(Cc::Yes),
+        &["--target=wasm32-wasi-threads", "-Wl,--export-memory,", "-Wl,--shared-memory"],
+    );
+
+    Target {
+        llvm_target: "wasm32-wasi".into(),
+        metadata: TargetMetadata {
+            description: Some("WebAssembly Linux Interface with musl-libc".into()),
+            tier: Some(3),
+            host_tools: Some(false),
+            std: None,
+        },
+        pointer_width: 32,
+        data_layout: "e-m:e-p:32:32-p10:8:8-p20:8:8-i64:64-i128:128-n32:64-S128-ni:1:10:20".into(),
+        arch: "wasm32".into(),
+        options,
+    }
+}
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index d05466bb484..6d3b6608ea2 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -768,17 +768,15 @@ impl Target {
         }
     }
 
-    pub fn implied_target_features<'a>(
-        &self,
-        base_features: impl Iterator<Item = &'a str>,
-    ) -> FxHashSet<&'a str> {
+    // Note: the returned set includes `base_feature`.
+    pub fn implied_target_features<'a>(&self, base_feature: &'a str) -> FxHashSet<&'a str> {
         let implied_features =
             self.rust_target_features().iter().map(|(f, _, i)| (f, i)).collect::<FxHashMap<_, _>>();
 
-        // implied target features have their own implied target features, so we traverse the
-        // map until there are no more features to add
+        // Implied target features have their own implied target features, so we traverse the
+        // map until there are no more features to add.
         let mut features = FxHashSet::default();
-        let mut new_features = base_features.collect::<Vec<&str>>();
+        let mut new_features = vec![base_feature];
         while let Some(new_feature) = new_features.pop() {
             if features.insert(new_feature) {
                 if let Some(implied_features) = implied_features.get(&new_feature) {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
index 514615735a5..51b2a0b36bb 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/note_and_explain.rs
@@ -395,11 +395,28 @@ impl<T> Trait<T> for X {
                             let sp = tcx
                                 .def_ident_span(body_owner_def_id)
                                 .unwrap_or_else(|| tcx.def_span(body_owner_def_id));
-                            diag.span_note(
-                                sp,
-                                "this item must have the opaque type in its signature in order to \
-                                 be able to register hidden types",
-                            );
+                            let mut alias_def_id = opaque_ty.def_id;
+                            while let DefKind::OpaqueTy = tcx.def_kind(alias_def_id) {
+                                alias_def_id = tcx.parent(alias_def_id);
+                            }
+                            let opaque_path = tcx.def_path_str(alias_def_id);
+                            // FIXME(type_alias_impl_trait): make this a structured suggestion
+                            match tcx.opaque_ty_origin(opaque_ty.def_id) {
+                                rustc_hir::OpaqueTyOrigin::FnReturn { .. } => {}
+                                rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {}
+                                rustc_hir::OpaqueTyOrigin::TyAlias {
+                                    in_assoc_ty: false, ..
+                                } => {
+                                    diag.span_note(
+                                        sp,
+                                        format!("this item must have a `#[define_opaque({opaque_path})]` \
+                                        attribute to be able to define hidden types"),
+                                    );
+                                }
+                                rustc_hir::OpaqueTyOrigin::TyAlias {
+                                    in_assoc_ty: true, ..
+                                } => {}
+                            }
                         }
                         // If two if arms can be coerced to a trait object, provide a structured
                         // suggestion.
diff --git a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
index 4f177df89e2..352ac7c1a4e 100644
--- a/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
+++ b/compiler/rustc_trait_selection/src/solve/fulfill/derive_errors.rs
@@ -440,7 +440,7 @@ impl<'tcx> ProofTreeVisitor<'tcx> for BestObligation<'tcx> {
             match (child_mode, nested_goal.source()) {
                 (
                     ChildMode::Trait(_) | ChildMode::Host(_),
-                    GoalSource::Misc | GoalSource::NormalizeGoal(_),
+                    GoalSource::Misc | GoalSource::TypeRelating | GoalSource::NormalizeGoal(_),
                 ) => {
                     continue;
                 }
diff --git a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
index d4502be6ccf..3fceada2510 100644
--- a/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
+++ b/compiler/rustc_trait_selection/src/traits/dyn_compatibility.rs
@@ -24,7 +24,9 @@ use super::elaborate;
 use crate::infer::TyCtxtInferExt;
 pub use crate::traits::DynCompatibilityViolation;
 use crate::traits::query::evaluate_obligation::InferCtxtExt;
-use crate::traits::{MethodViolationCode, Obligation, ObligationCause, util};
+use crate::traits::{
+    MethodViolationCode, Obligation, ObligationCause, normalize_param_env_or_error, util,
+};
 
 /// Returns the dyn-compatibility violations that affect HIR ty lowering.
 ///
@@ -579,8 +581,8 @@ fn receiver_is_dispatchable<'tcx>(
     let unsized_receiver_ty =
         receiver_for_self_ty(tcx, receiver_ty, unsized_self_ty, method.def_id);
 
-    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` added to caller bounds
-    // `U: ?Sized` is already implied here
+    // create a modified param env, with `Self: Unsize<U>` and `U: Trait` (and all of
+    // its supertraits) added to caller bounds. `U: ?Sized` is already implied here.
     let param_env = {
         let param_env = tcx.param_env(method.def_id);
 
@@ -598,10 +600,13 @@ fn receiver_is_dispatchable<'tcx>(
             ty::TraitRef::new_from_args(tcx, trait_def_id, args).upcast(tcx)
         };
 
-        let caller_bounds =
-            param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]);
-
-        ty::ParamEnv::new(tcx.mk_clauses_from_iter(caller_bounds))
+        normalize_param_env_or_error(
+            tcx,
+            ty::ParamEnv::new(tcx.mk_clauses_from_iter(
+                param_env.caller_bounds().iter().chain([unsize_predicate, trait_predicate]),
+            )),
+            ObligationCause::dummy_with_span(tcx.def_span(method.def_id)),
+        )
     };
 
     // Receiver: DispatchFromDyn<Receiver[Self => U]>
diff --git a/compiler/rustc_trait_selection/src/traits/select/mod.rs b/compiler/rustc_trait_selection/src/traits/select/mod.rs
index 0a54b8468fe..e1adabbeaa6 100644
--- a/compiler/rustc_trait_selection/src/traits/select/mod.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/mod.rs
@@ -2231,15 +2231,6 @@ impl<'tcx> SelectionContext<'_, 'tcx> {
                 }
             }
 
-            // `Copy` and `Clone` are automatically implemented for an anonymous adt
-            // if all of its fields are `Copy` and `Clone`
-            ty::Adt(adt, args) if adt.is_anonymous() => {
-                // (*) binder moved here
-                Where(obligation.predicate.rebind(
-                    adt.non_enum_variant().fields.iter().map(|f| f.ty(self.tcx(), args)).collect(),
-                ))
-            }
-
             ty::Adt(..) | ty::Alias(..) | ty::Param(..) | ty::Placeholder(..) => {
                 // Fallback to whatever user-defined impls exist in this case.
                 None
diff --git a/compiler/rustc_ty_utils/Cargo.toml b/compiler/rustc_ty_utils/Cargo.toml
index 4c7a57f2931..7e96b64408c 100644
--- a/compiler/rustc_ty_utils/Cargo.toml
+++ b/compiler/rustc_ty_utils/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2024"
 # tidy-alphabetical-start
 itertools = "0.12"
 rustc_abi = { path = "../rustc_abi" }
+rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
diff --git a/compiler/rustc_ty_utils/src/layout.rs b/compiler/rustc_ty_utils/src/layout.rs
index 5a4bb2c95da..7334beb52c9 100644
--- a/compiler/rustc_ty_utils/src/layout.rs
+++ b/compiler/rustc_ty_utils/src/layout.rs
@@ -220,6 +220,34 @@ fn layout_of_uncached<'tcx>(
                             .try_to_bits(tcx, cx.typing_env)
                             .ok_or_else(|| error(cx, LayoutError::Unknown(ty)))?;
 
+                        // FIXME(pattern_types): create implied bounds from pattern types in signatures
+                        // that require that the range end is >= the range start so that we can't hit
+                        // this error anymore without first having hit a trait solver error.
+                        // Very fuzzy on the details here, but pattern types are an internal impl detail,
+                        // so we can just go with this for now
+                        if scalar.is_signed() {
+                            let range = scalar.valid_range_mut();
+                            let start = layout.size.sign_extend(range.start);
+                            let end = layout.size.sign_extend(range.end);
+                            if end < start {
+                                let guar = tcx.dcx().err(format!(
+                                    "pattern type ranges cannot wrap: {start}..={end}"
+                                ));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+                        } else {
+                            let range = scalar.valid_range_mut();
+                            if range.end < range.start {
+                                let guar = tcx.dcx().err(format!(
+                                    "pattern type ranges cannot wrap: {}..={}",
+                                    range.start, range.end
+                                ));
+
+                                return Err(error(cx, LayoutError::ReferencesError(guar)));
+                            }
+                        };
+
                         let niche = Niche {
                             offset: Size::ZERO,
                             value: scalar.primitive(),
diff --git a/compiler/rustc_ty_utils/src/opaque_types.rs b/compiler/rustc_ty_utils/src/opaque_types.rs
index 98881905bcf..a107925fb18 100644
--- a/compiler/rustc_ty_utils/src/opaque_types.rs
+++ b/compiler/rustc_ty_utils/src/opaque_types.rs
@@ -1,8 +1,8 @@
 use rustc_data_structures::fx::FxHashSet;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::LocalDefId;
+use rustc_hir::intravisit;
 use rustc_hir::intravisit::Visitor;
-use rustc_hir::{CRATE_HIR_ID, intravisit};
 use rustc_middle::bug;
 use rustc_middle::query::Providers;
 use rustc_middle::ty::util::{CheckRegions, NotUniqueParam};
@@ -30,14 +30,21 @@ enum CollectionMode {
     /// For impl trait in assoc types we only permit collecting them from
     /// associated types of the same impl block.
     ImplTraitInAssocTypes,
-    TypeAliasImplTraitTransition,
+    /// When collecting for an explicit `#[define_opaque]` attribute, find all TAITs
+    Taits,
+    /// The default case, only collect RPITs and AsyncFn return types, as these are
+    /// always defined by the current item.
+    RpitAndAsyncFnOnly,
 }
 
 impl<'tcx> OpaqueTypeCollector<'tcx> {
     fn new(tcx: TyCtxt<'tcx>, item: LocalDefId) -> Self {
-        let mode = match tcx.def_kind(tcx.local_parent(item)) {
-            DefKind::Impl { of_trait: true } => CollectionMode::ImplTraitInAssocTypes,
-            _ => CollectionMode::TypeAliasImplTraitTransition,
+        let mode = match tcx.def_kind(item) {
+            DefKind::AssocConst | DefKind::AssocFn | DefKind::AssocTy => {
+                CollectionMode::ImplTraitInAssocTypes
+            }
+            DefKind::TyAlias => CollectionMode::Taits,
+            _ => CollectionMode::RpitAndAsyncFnOnly,
         };
         Self { tcx, opaques: Vec::new(), item, seen: Default::default(), span: None, mode }
     }
@@ -73,40 +80,6 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         }
     }
 
-    /// Returns `true` if `opaque_hir_id` is a sibling or a child of a sibling of `self.item`.
-    ///
-    /// Example:
-    /// ```ignore UNSOLVED (is this a bug?)
-    /// # #![feature(type_alias_impl_trait)]
-    /// pub mod foo {
-    ///     pub mod bar {
-    ///         pub trait Bar { /* ... */ }
-    ///         pub type Baz = impl Bar;
-    ///
-    ///         # impl Bar for () {}
-    ///         fn f1() -> Baz { /* ... */ }
-    ///     }
-    ///     fn f2() -> bar::Baz { /* ... */ }
-    /// }
-    /// ```
-    ///
-    /// and `opaque_def_id` is the `DefId` of the definition of the opaque type `Baz`.
-    /// For the above example, this function returns `true` for `f1` and `false` for `f2`.
-    #[instrument(level = "trace", skip(self), ret)]
-    fn check_tait_defining_scope(&self, opaque_def_id: LocalDefId) -> bool {
-        let mut hir_id = self.tcx.local_def_id_to_hir_id(self.item);
-        let opaque_hir_id = self.tcx.local_def_id_to_hir_id(opaque_def_id);
-
-        // Named opaque types can be defined by any siblings or children of siblings.
-        let scope = self.tcx.hir_get_defining_scope(opaque_hir_id);
-        // We walk up the node tree until we hit the root or the scope of the opaque type.
-        while hir_id != scope && hir_id != CRATE_HIR_ID {
-            hir_id = self.tcx.hir_get_parent_item(hir_id).into();
-        }
-        // Syntactically, we are allowed to define the concrete type if:
-        hir_id == scope
-    }
-
     #[instrument(level = "trace", skip(self))]
     fn collect_taits_declared_in_body(&mut self) {
         let body = self.tcx.hir_body_owned_by(self.item).value;
@@ -139,18 +112,31 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
         }
 
         // TAITs outside their defining scopes are ignored.
-        let origin = self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local());
-        trace!(?origin);
-        match origin {
+        match self.tcx.local_opaque_ty_origin(alias_ty.def_id.expect_local()) {
             rustc_hir::OpaqueTyOrigin::FnReturn { .. }
             | rustc_hir::OpaqueTyOrigin::AsyncFn { .. } => {}
-            rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => {
-                if !in_assoc_ty && !self.check_tait_defining_scope(alias_ty.def_id.expect_local()) {
-                    return;
+            rustc_hir::OpaqueTyOrigin::TyAlias { in_assoc_ty, .. } => match self.mode {
+                // If we are collecting opaques in an assoc method, we are only looking at assoc types
+                // mentioned in the assoc method and only at opaques defined in there. We do not
+                // want to collect TAITs
+                CollectionMode::ImplTraitInAssocTypes => {
+                    if !in_assoc_ty {
+                        return;
+                    }
                 }
-            }
+                // If we are collecting opaques referenced from a `define_opaque` attribute, we
+                // do not want to look at opaques defined in associated types. Those can only be
+                // defined by methods on the same impl.
+                CollectionMode::Taits => {
+                    if in_assoc_ty {
+                        return;
+                    }
+                }
+                CollectionMode::RpitAndAsyncFnOnly => return,
+            },
         }
 
+        trace!(?alias_ty, "adding");
         self.opaques.push(alias_ty.def_id.expect_local());
 
         let parent_count = self.tcx.generics_of(alias_ty.def_id).parent_count;
@@ -192,6 +178,32 @@ impl<'tcx> OpaqueTypeCollector<'tcx> {
             }
         }
     }
+
+    /// Checks the `#[define_opaque]` attributes on items and collectes opaques to define
+    /// from the referenced types.
+    #[instrument(level = "trace", skip(self))]
+    fn collect_taits_from_defines_attr(&mut self) {
+        let hir_id = self.tcx.local_def_id_to_hir_id(self.item);
+        if !hir_id.is_owner() {
+            return;
+        }
+        let Some(defines) = self.tcx.hir_attrs(hir_id.owner).define_opaque else {
+            return;
+        };
+        for &(span, define) in defines {
+            trace!(?define);
+            let mode = std::mem::replace(&mut self.mode, CollectionMode::Taits);
+            let n = self.opaques.len();
+            super::sig_types::walk_types(self.tcx, define, self);
+            if n == self.opaques.len() {
+                self.tcx.dcx().span_err(span, "item does not contain any opaque types");
+            }
+            self.mode = mode;
+        }
+        // Allow using `#[define_opaque]` on assoc methods and type aliases to override the default collection mode in
+        // case it was capturing too much.
+        self.mode = CollectionMode::RpitAndAsyncFnOnly;
+    }
 }
 
 impl<'tcx> super::sig_types::SpannedTypeVisitor<'tcx> for OpaqueTypeCollector<'tcx> {
@@ -210,6 +222,7 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                 self.visit_opaque_ty(alias_ty);
             }
             // Skips type aliases, as they are meant to be transparent.
+            // FIXME(type_alias_impl_trait): can we require mentioning nested type aliases explicitly?
             ty::Alias(ty::Weak, alias_ty) if alias_ty.def_id.is_local() => {
                 self.tcx
                     .type_of(alias_ty.def_id)
@@ -283,28 +296,6 @@ impl<'tcx> TypeVisitor<TyCtxt<'tcx>> for OpaqueTypeCollector<'tcx> {
                     self.visit_opaque_ty(alias_ty);
                 }
             }
-            ty::Adt(def, _) if def.did().is_local() => {
-                if let CollectionMode::ImplTraitInAssocTypes = self.mode {
-                    return;
-                }
-                if !self.seen.insert(def.did().expect_local()) {
-                    return;
-                }
-                for variant in def.variants().iter() {
-                    for field in variant.fields.iter() {
-                        // Don't use the `ty::Adt` args, we either
-                        // * found the opaque in the args
-                        // * will find the opaque in the uninstantiated fields
-                        // The only other situation that can occur is that after instantiating,
-                        // some projection resolves to an opaque that we would have otherwise
-                        // not found. While we could instantiate and walk those, that would mean we
-                        // would have to walk all generic parameters of an Adt, which can quickly
-                        // degenerate into looking at an exponential number of types.
-                        let ty = self.tcx.type_of(field.did).instantiate_identity();
-                        self.visit_spanned(self.tcx.def_span(field.did), ty);
-                    }
-                }
-            }
             _ => trace!(kind=?t.kind()),
         }
     }
@@ -317,7 +308,9 @@ fn opaque_types_defined_by<'tcx>(
     let kind = tcx.def_kind(item);
     trace!(?kind);
     let mut collector = OpaqueTypeCollector::new(tcx, item);
+    collector.collect_taits_from_defines_attr();
     super::sig_types::walk_types(tcx, item, &mut collector);
+
     match kind {
         DefKind::AssocFn
         | DefKind::Fn
@@ -350,8 +343,7 @@ fn opaque_types_defined_by<'tcx>(
         | DefKind::GlobalAsm
         | DefKind::Impl { .. }
         | DefKind::SyntheticCoroutineBody => {}
-        // Closures and coroutines are type checked with their parent, so we need to allow all
-        // opaques from the closure signature *and* from the parent body.
+        // Closures and coroutines are type checked with their parent
         DefKind::Closure | DefKind::InlineConst => {
             collector.opaques.extend(tcx.opaque_types_defined_by(tcx.local_parent(item)));
         }
diff --git a/compiler/rustc_type_ir/Cargo.toml b/compiler/rustc_type_ir/Cargo.toml
index 7b2593b96e3..4adf7157926 100644
--- a/compiler/rustc_type_ir/Cargo.toml
+++ b/compiler/rustc_type_ir/Cargo.toml
@@ -33,6 +33,3 @@ nightly = [
     "rustc_index/nightly",
     "rustc_ast_ir/nightly",
 ]
-
-[lints.rust]
-unexpected_cfgs = { level = "warn", check-cfg = ['cfg(bootstrap)'] }
diff --git a/compiler/rustc_type_ir/src/search_graph/mod.rs b/compiler/rustc_type_ir/src/search_graph/mod.rs
index 18e84db5d68..9ae83928057 100644
--- a/compiler/rustc_type_ir/src/search_graph/mod.rs
+++ b/compiler/rustc_type_ir/src/search_graph/mod.rs
@@ -13,6 +13,7 @@
 /// behavior as long as the resulting behavior is still correct.
 use std::cmp::Ordering;
 use std::collections::BTreeMap;
+use std::collections::hash_map::Entry;
 use std::fmt::Debug;
 use std::hash::Hash;
 use std::marker::PhantomData;
@@ -20,7 +21,7 @@ use std::marker::PhantomData;
 use derive_where::derive_where;
 use rustc_index::{Idx, IndexVec};
 #[cfg(feature = "nightly")]
-use rustc_macros::HashStable_NoContext;
+use rustc_macros::{HashStable_NoContext, TyDecodable, TyEncodable};
 use tracing::debug;
 
 use crate::data_structures::HashMap;
@@ -111,21 +112,35 @@ pub trait Delegate {
 /// In the initial iteration of a cycle, we do not yet have a provisional
 /// result. In the case we return an initial provisional result depending
 /// on the kind of cycle.
-#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
-#[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
+#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
+#[cfg_attr(feature = "nightly", derive(TyDecodable, TyEncodable, HashStable_NoContext))]
 pub enum PathKind {
-    Coinductive,
+    /// A path consisting of only inductive/unproductive steps. Their initial
+    /// provisional result is `Err(NoSolution)`. We currently treat them as
+    /// `PathKind::Unknown` during coherence until we're fully confident in
+    /// our approach.
     Inductive,
+    /// A path which is not be coinductive right now but we may want
+    /// to change of them to be so in the future. We return an ambiguous
+    /// result in this case to prevent people from relying on this.
+    Unknown,
+    /// A path with at least one coinductive step. Such cycles hold.
+    Coinductive,
 }
+
 impl PathKind {
     /// Returns the path kind when merging `self` with `rest`.
     ///
     /// Given an inductive path `self` and a coinductive path `rest`,
     /// the path `self -> rest` would be coinductive.
+    ///
+    /// This operation represents an ordering and would be equivalent
+    /// to `max(self, rest)`.
     fn extend(self, rest: PathKind) -> PathKind {
-        match self {
-            PathKind::Coinductive => PathKind::Coinductive,
-            PathKind::Inductive => rest,
+        match (self, rest) {
+            (PathKind::Coinductive, _) | (_, PathKind::Coinductive) => PathKind::Coinductive,
+            (PathKind::Unknown, _) | (_, PathKind::Unknown) => PathKind::Unknown,
+            (PathKind::Inductive, PathKind::Inductive) => PathKind::Inductive,
         }
     }
 }
@@ -159,9 +174,6 @@ impl UsageKind {
             }
         }
     }
-    fn and_merge(&mut self, other: impl Into<Self>) {
-        *self = self.merge(other);
-    }
 }
 
 /// For each goal we track whether the paths from this goal
@@ -297,7 +309,7 @@ impl CycleHeads {
 
             let path_from_entry = match step_kind {
                 PathKind::Coinductive => AllPathsToHeadCoinductive::Yes,
-                PathKind::Inductive => path_from_entry,
+                PathKind::Unknown | PathKind::Inductive => path_from_entry,
             };
 
             self.insert(head, path_from_entry);
@@ -305,6 +317,63 @@ impl CycleHeads {
     }
 }
 
+bitflags::bitflags! {
+    /// Tracks how nested goals have been accessed. This is necessary to disable
+    /// global cache entries if computing them would otherwise result in a cycle or
+    /// access a provisional cache entry.
+    #[derive(Debug, Clone, Copy)]
+    pub struct PathsToNested: u8 {
+        /// The initial value when adding a goal to its own nested goals.
+        const EMPTY                      = 1 << 0;
+        const INDUCTIVE                  = 1 << 1;
+        const UNKNOWN                    = 1 << 2;
+        const COINDUCTIVE                = 1 << 3;
+    }
+}
+impl From<PathKind> for PathsToNested {
+    fn from(path: PathKind) -> PathsToNested {
+        match path {
+            PathKind::Inductive => PathsToNested::INDUCTIVE,
+            PathKind::Unknown => PathsToNested::UNKNOWN,
+            PathKind::Coinductive => PathsToNested::COINDUCTIVE,
+        }
+    }
+}
+impl PathsToNested {
+    /// The implementation of this function is kind of ugly. We check whether
+    /// there currently exist 'weaker' paths in the set, if so we upgrade these
+    /// paths to at least `path`.
+    #[must_use]
+    fn extend_with(mut self, path: PathKind) -> Self {
+        match path {
+            PathKind::Inductive => {
+                if self.intersects(PathsToNested::EMPTY) {
+                    self.remove(PathsToNested::EMPTY);
+                    self.insert(PathsToNested::INDUCTIVE);
+                }
+            }
+            PathKind::Unknown => {
+                if self.intersects(PathsToNested::EMPTY | PathsToNested::INDUCTIVE) {
+                    self.remove(PathsToNested::EMPTY | PathsToNested::INDUCTIVE);
+                    self.insert(PathsToNested::UNKNOWN);
+                }
+            }
+            PathKind::Coinductive => {
+                if self.intersects(
+                    PathsToNested::EMPTY | PathsToNested::INDUCTIVE | PathsToNested::UNKNOWN,
+                ) {
+                    self.remove(
+                        PathsToNested::EMPTY | PathsToNested::INDUCTIVE | PathsToNested::UNKNOWN,
+                    );
+                    self.insert(PathsToNested::COINDUCTIVE);
+                }
+            }
+        }
+
+        self
+    }
+}
+
 /// The nested goals of each stack entry and the path from the
 /// stack entry to that nested goal.
 ///
@@ -322,15 +391,18 @@ impl CycleHeads {
 /// results from a the cycle BAB depending on the cycle root.
 #[derive_where(Debug, Default, Clone; X: Cx)]
 struct NestedGoals<X: Cx> {
-    nested_goals: HashMap<X::Input, UsageKind>,
+    nested_goals: HashMap<X::Input, PathsToNested>,
 }
 impl<X: Cx> NestedGoals<X> {
     fn is_empty(&self) -> bool {
         self.nested_goals.is_empty()
     }
 
-    fn insert(&mut self, input: X::Input, path_from_entry: UsageKind) {
-        self.nested_goals.entry(input).or_insert(path_from_entry).and_merge(path_from_entry);
+    fn insert(&mut self, input: X::Input, paths_to_nested: PathsToNested) {
+        match self.nested_goals.entry(input) {
+            Entry::Occupied(mut entry) => *entry.get_mut() |= paths_to_nested,
+            Entry::Vacant(entry) => drop(entry.insert(paths_to_nested)),
+        }
     }
 
     /// Adds the nested goals of a nested goal, given that the path `step_kind` from this goal
@@ -341,18 +413,15 @@ impl<X: Cx> NestedGoals<X> {
     /// the same as for the child.
     fn extend_from_child(&mut self, step_kind: PathKind, nested_goals: &NestedGoals<X>) {
         #[allow(rustc::potential_query_instability)]
-        for (input, path_from_entry) in nested_goals.iter() {
-            let path_from_entry = match step_kind {
-                PathKind::Coinductive => UsageKind::Single(PathKind::Coinductive),
-                PathKind::Inductive => path_from_entry,
-            };
-            self.insert(input, path_from_entry);
+        for (input, paths_to_nested) in nested_goals.iter() {
+            let paths_to_nested = paths_to_nested.extend_with(step_kind);
+            self.insert(input, paths_to_nested);
         }
     }
 
     #[cfg_attr(feature = "nightly", rustc_lint_query_instability)]
     #[allow(rustc::potential_query_instability)]
-    fn iter(&self) -> impl Iterator<Item = (X::Input, UsageKind)> {
+    fn iter(&self) -> impl Iterator<Item = (X::Input, PathsToNested)> + '_ {
         self.nested_goals.iter().map(|(i, p)| (*i, *p))
     }
 
@@ -490,7 +559,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             // goals as this change may cause them to now depend on additional
             // goals, resulting in new cycles. See the dev-guide for examples.
             if parent_depends_on_cycle {
-                parent.nested_goals.insert(parent.input, UsageKind::Single(PathKind::Inductive))
+                parent.nested_goals.insert(parent.input, PathsToNested::EMPTY);
             }
         }
     }
@@ -666,7 +735,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             //
             // We must therefore not use the global cache entry for `B` in that case.
             // See tests/ui/traits/next-solver/cycles/hidden-by-overflow.rs
-            last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Inductive));
+            last.nested_goals.insert(last.input, PathsToNested::EMPTY);
         }
 
         debug!("encountered stack overflow");
@@ -749,16 +818,11 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
 
                 // We now care about the path from the next highest cycle head to the
                 // provisional cache entry.
-                match path_from_head {
-                    PathKind::Coinductive => {}
-                    PathKind::Inductive => {
-                        *path_from_head = Self::cycle_path_kind(
-                            &self.stack,
-                            stack_entry.step_kind_from_parent,
-                            head,
-                        )
-                    }
-                }
+                *path_from_head = path_from_head.extend(Self::cycle_path_kind(
+                    &self.stack,
+                    stack_entry.step_kind_from_parent,
+                    head,
+                ));
                 // Mutate the result of the provisional cache entry in case we did
                 // not reach a fixpoint.
                 *result = mutate_result(input, *result);
@@ -858,7 +922,7 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
             for &ProvisionalCacheEntry {
                 encountered_overflow,
                 ref heads,
-                path_from_head,
+                path_from_head: head_to_provisional,
                 result: _,
             } in entries.iter()
             {
@@ -870,24 +934,19 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
 
                 // A provisional cache entry only applies if the path from its highest head
                 // matches the path when encountering the goal.
+                //
+                // We check if any of the paths taken while computing the global goal
+                // would end up with an applicable provisional cache entry.
                 let head = heads.highest_cycle_head();
-                let full_path = match Self::cycle_path_kind(stack, step_kind_from_parent, head) {
-                    PathKind::Coinductive => UsageKind::Single(PathKind::Coinductive),
-                    PathKind::Inductive => path_from_global_entry,
-                };
-
-                match (full_path, path_from_head) {
-                    (UsageKind::Mixed, _)
-                    | (UsageKind::Single(PathKind::Coinductive), PathKind::Coinductive)
-                    | (UsageKind::Single(PathKind::Inductive), PathKind::Inductive) => {
-                        debug!(
-                            ?full_path,
-                            ?path_from_head,
-                            "cache entry not applicable due to matching paths"
-                        );
-                        return false;
-                    }
-                    _ => debug!(?full_path, ?path_from_head, "paths don't match"),
+                let head_to_curr = Self::cycle_path_kind(stack, step_kind_from_parent, head);
+                let full_paths = path_from_global_entry.extend_with(head_to_curr);
+                if full_paths.contains(head_to_provisional.into()) {
+                    debug!(
+                        ?full_paths,
+                        ?head_to_provisional,
+                        "cache entry not applicable due to matching paths"
+                    );
+                    return false;
                 }
             }
         }
@@ -986,8 +1045,8 @@ impl<D: Delegate<Cx = X>, X: Cx> SearchGraph<D> {
         let last = &mut self.stack[last_index];
         last.reached_depth = last.reached_depth.max(next_index);
 
-        last.nested_goals.insert(input, UsageKind::Single(step_kind_from_parent));
-        last.nested_goals.insert(last.input, UsageKind::Single(PathKind::Inductive));
+        last.nested_goals.insert(input, step_kind_from_parent.into());
+        last.nested_goals.insert(last.input, PathsToNested::EMPTY);
         if last_index != head {
             last.heads.insert(head, step_kind_from_parent);
         }
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index 6f37db1cb85..de2e0f2c0ec 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -58,20 +58,24 @@ impl<I: Interner, P> Goal<I, P> {
 /// Why a specific goal has to be proven.
 ///
 /// This is necessary as we treat nested goals different depending on
-/// their source. This is currently mostly used by proof tree visitors
-/// but will be used by cycle handling in the future.
+/// their source. This is used to decide whether a cycle is coinductive.
+/// See the documentation of `EvalCtxt::step_kind_for_source` for more details
+/// about this.
+///
+/// It is also used by proof tree visitors, e.g. for diagnostics purposes.
 #[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
 #[cfg_attr(feature = "nightly", derive(HashStable_NoContext))]
 pub enum GoalSource {
     Misc,
-    /// We're proving a where-bound of an impl.
+    /// A nested goal required to prove that types are equal/subtypes.
+    /// This is always an unproductive step.
     ///
-    /// FIXME(-Znext-solver=coinductive): Explain how and why this
-    /// changes whether cycles are coinductive.
+    /// This is also used for all `NormalizesTo` goals as we they are used
+    /// to relate types in `AliasRelate`.
+    TypeRelating,
+    /// We're proving a where-bound of an impl.
     ImplWhereBound,
     /// Const conditions that need to hold for `~const` alias bounds to hold.
-    ///
-    /// FIXME(-Znext-solver=coinductive): Are these even coinductive?
     AliasBoundConstCondition,
     /// Instantiating a higher-ranked goal and re-proving it.
     InstantiateHigherRanked,
@@ -79,7 +83,6 @@ pub enum GoalSource {
     /// This is used in two places: projecting to an opaque whose hidden type
     /// is already registered in the opaque type storage, and for rigid projections.
     AliasWellFormed,
-
     /// In case normalizing aliases in nested goals cycles, eagerly normalizing these
     /// aliases in the context of the parent may incorrectly change the cycle kind.
     /// Normalizing aliases in goals therefore tracks the original path kind for this
diff --git a/config.example.toml b/config.example.toml
index ac5e491b4b5..c3d2ad094ce 100644
--- a/config.example.toml
+++ b/config.example.toml
@@ -164,6 +164,16 @@
 #build-config = {}
 
 # =============================================================================
+# Tweaking how GCC is compiled
+# =============================================================================
+[gcc]
+# Download GCC from CI instead of building it locally.
+# Note that this will attempt to download GCC even if there are local
+# modifications to the `src/gcc` submodule.
+# Currently, this is only supported for the `x86_64-unknown-linux-gnu` target.
+# download-ci-gcc = false
+
+# =============================================================================
 # General build configuration options
 # =============================================================================
 [build]
diff --git a/library/Cargo.lock b/library/Cargo.lock
index 405c69d9568..8f174f28472 100644
--- a/library/Cargo.lock
+++ b/library/Cargo.lock
@@ -146,9 +146,9 @@ dependencies = [
 
 [[package]]
 name = "hermit-abi"
-version = "0.4.0"
+version = "0.5.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "fbf6a919d6cf397374f7dfeeea91d974c7c0a7221d0d0f4f20d859d329e53fcc"
+checksum = "fbd780fe5cc30f81464441920d82ac8740e2e46b29a6fad543ddd075229ce37e"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-alloc",
diff --git a/library/alloc/src/collections/binary_heap/mod.rs b/library/alloc/src/collections/binary_heap/mod.rs
index b764b8fa5d9..63828b482b9 100644
--- a/library/alloc/src/collections/binary_heap/mod.rs
+++ b/library/alloc/src/collections/binary_heap/mod.rs
@@ -361,6 +361,74 @@ impl<T: Ord, A: Allocator> DerefMut for PeekMut<'_, T, A> {
 }
 
 impl<'a, T: Ord, A: Allocator> PeekMut<'a, T, A> {
+    /// Sifts the current element to its new position.
+    ///
+    /// Afterwards refers to the new element. Returns if the element changed.
+    ///
+    /// ## Examples
+    ///
+    /// The condition can be used to upper bound all elements in the heap. When only few elements
+    /// are affected, the heap's sort ensures this is faster than a reconstruction from the raw
+    /// element list and requires no additional allocation.
+    ///
+    /// ```
+    /// #![feature(binary_heap_peek_mut_refresh)]
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut heap: BinaryHeap<u32> = (0..128).collect();
+    /// let mut peek = heap.peek_mut().unwrap();
+    ///
+    /// loop {
+    ///     *peek = 99;
+    ///
+    ///     if !peek.refresh() {
+    ///         break;
+    ///     }
+    /// }
+    ///
+    /// // Post condition, this is now an upper bound.
+    /// assert!(*peek < 100);
+    /// ```
+    ///
+    /// When the element remains the maximum after modification, the peek remains unchanged:
+    ///
+    /// ```
+    /// #![feature(binary_heap_peek_mut_refresh)]
+    /// use std::collections::BinaryHeap;
+    ///
+    /// let mut heap: BinaryHeap<u32> = [1, 2, 3].into();
+    /// let mut peek = heap.peek_mut().unwrap();
+    ///
+    /// assert_eq!(*peek, 3);
+    /// *peek = 42;
+    ///
+    /// // When we refresh, the peek is updated to the new maximum.
+    /// assert!(!peek.refresh(), "42 is even larger than 3");
+    /// assert_eq!(*peek, 42);
+    /// ```
+    #[unstable(feature = "binary_heap_peek_mut_refresh", issue = "138355")]
+    #[must_use = "is equivalent to dropping and getting a new PeekMut except for return information"]
+    pub fn refresh(&mut self) -> bool {
+        // The length of the underlying heap is unchanged by sifting down. The value stored for leak
+        // amplification thus remains accurate. We erase the leak amplification firstly because the
+        // operation is then equivalent to constructing a new PeekMut and secondly this avoids any
+        // future complication where original_len being non-empty would be interpreted as the heap
+        // having been leak amplified instead of checking the heap itself.
+        if let Some(original_len) = self.original_len.take() {
+            // SAFETY: This is how many elements were in the Vec at the time of
+            // the BinaryHeap::peek_mut call.
+            unsafe { self.heap.data.set_len(original_len.get()) };
+
+            // The length of the heap did not change by sifting, upholding our own invariants.
+
+            // SAFETY: PeekMut is only instantiated for non-empty heaps.
+            (unsafe { self.heap.sift_down(0) }) != 0
+        } else {
+            // The element was not modified.
+            false
+        }
+    }
+
     /// Removes the peeked value from the heap and returns it.
     #[stable(feature = "binary_heap_peek_mut_pop", since = "1.18.0")]
     pub fn pop(mut this: PeekMut<'a, T, A>) -> T {
@@ -672,6 +740,8 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
     /// # Safety
     ///
     /// The caller must guarantee that `pos < self.len()`.
+    ///
+    /// Returns the new position of the element.
     unsafe fn sift_up(&mut self, start: usize, pos: usize) -> usize {
         // Take out the value at `pos` and create a hole.
         // SAFETY: The caller guarantees that pos < self.len()
@@ -698,10 +768,12 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
     /// Take an element at `pos` and move it down the heap,
     /// while its children are larger.
     ///
+    /// Returns the new position of the element.
+    ///
     /// # Safety
     ///
     /// The caller must guarantee that `pos < end <= self.len()`.
-    unsafe fn sift_down_range(&mut self, pos: usize, end: usize) {
+    unsafe fn sift_down_range(&mut self, pos: usize, end: usize) -> usize {
         // SAFETY: The caller guarantees that pos < end <= self.len().
         let mut hole = unsafe { Hole::new(&mut self.data, pos) };
         let mut child = 2 * hole.pos() + 1;
@@ -721,7 +793,7 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
             // SAFETY: child is now either the old child or the old child+1
             //  We already proven that both are < self.len() and != hole.pos()
             if hole.element() >= unsafe { hole.get(child) } {
-                return;
+                return hole.pos();
             }
 
             // SAFETY: same as above.
@@ -736,16 +808,18 @@ impl<T: Ord, A: Allocator> BinaryHeap<T, A> {
             //  child == 2 * hole.pos() + 1 != hole.pos().
             unsafe { hole.move_to(child) };
         }
+
+        hole.pos()
     }
 
     /// # Safety
     ///
     /// The caller must guarantee that `pos < self.len()`.
-    unsafe fn sift_down(&mut self, pos: usize) {
+    unsafe fn sift_down(&mut self, pos: usize) -> usize {
         let len = self.len();
         // SAFETY: pos < len is guaranteed by the caller and
         //  obviously len = self.len() <= self.len().
-        unsafe { self.sift_down_range(pos, len) };
+        unsafe { self.sift_down_range(pos, len) }
     }
 
     /// Take an element at `pos` and move it all the way down the heap,
diff --git a/library/core/src/ffi/primitives.rs b/library/core/src/ffi/primitives.rs
index 6495e61b346..0a70eb4da55 100644
--- a/library/core/src/ffi/primitives.rs
+++ b/library/core/src/ffi/primitives.rs
@@ -133,7 +133,10 @@ mod c_char_definition {
 
 mod c_long_definition {
     cfg_if! {
-        if #[cfg(all(target_pointer_width = "64", not(windows)))] {
+        if #[cfg(any(
+            all(target_pointer_width = "64", not(windows)),
+            // wasm32 Linux ABI uses 64-bit long
+            all(target_arch = "wasm32", target_os = "linux")))] {
             pub(super) type c_long = i64;
             pub(super) type c_ulong = u64;
         } else {
diff --git a/library/core/src/fmt/float.rs b/library/core/src/fmt/float.rs
index 3f10158193d..4a43c12be9a 100644
--- a/library/core/src/fmt/float.rs
+++ b/library/core/src/fmt/float.rs
@@ -29,7 +29,7 @@ fn float_to_decimal_common_exact<T>(
     fmt: &mut Formatter<'_>,
     num: &T,
     sign: flt2dec::Sign,
-    precision: usize,
+    precision: u16,
 ) -> Result
 where
     T: flt2dec::DecodableFloat,
@@ -40,7 +40,7 @@ where
         flt2dec::strategy::grisu::format_exact,
         *num,
         sign,
-        precision,
+        precision.into(),
         &mut buf,
         &mut parts,
     );
@@ -55,7 +55,7 @@ fn float_to_decimal_common_shortest<T>(
     fmt: &mut Formatter<'_>,
     num: &T,
     sign: flt2dec::Sign,
-    precision: usize,
+    precision: u16,
 ) -> Result
 where
     T: flt2dec::DecodableFloat,
@@ -68,7 +68,7 @@ where
         flt2dec::strategy::grisu::format_shortest,
         *num,
         sign,
-        precision,
+        precision.into(),
         &mut buf,
         &mut parts,
     );
@@ -101,7 +101,7 @@ fn float_to_exponential_common_exact<T>(
     fmt: &mut Formatter<'_>,
     num: &T,
     sign: flt2dec::Sign,
-    precision: usize,
+    precision: u16,
     upper: bool,
 ) -> Result
 where
@@ -113,7 +113,7 @@ where
         flt2dec::strategy::grisu::format_exact,
         *num,
         sign,
-        precision,
+        precision.into(),
         upper,
         &mut buf,
         &mut parts,
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index 3f60bb067d6..e0dc632df70 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -294,8 +294,8 @@ pub struct FormattingOptions {
     flags: u32,
     fill: char,
     align: Option<Alignment>,
-    width: Option<usize>,
-    precision: Option<usize>,
+    width: Option<u16>,
+    precision: Option<u16>,
 }
 
 impl FormattingOptions {
@@ -389,7 +389,7 @@ impl FormattingOptions {
     /// the padding specified by [`FormattingOptions::fill`]/[`FormattingOptions::align`]
     /// will be used to take up the required space.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn width(&mut self, width: Option<usize>) -> &mut Self {
+    pub fn width(&mut self, width: Option<u16>) -> &mut Self {
         self.width = width;
         self
     }
@@ -403,7 +403,7 @@ impl FormattingOptions {
     /// - For floating-point types, this indicates how many digits after the
     /// decimal point should be printed.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub fn precision(&mut self, precision: Option<usize>) -> &mut Self {
+    pub fn precision(&mut self, precision: Option<u16>) -> &mut Self {
         self.precision = precision;
         self
     }
@@ -455,12 +455,12 @@ impl FormattingOptions {
     }
     /// Returns the current width.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub const fn get_width(&self) -> Option<usize> {
+    pub const fn get_width(&self) -> Option<u16> {
         self.width
     }
     /// Returns the current precision.
     #[unstable(feature = "formatting_options", issue = "118117")]
-    pub const fn get_precision(&self) -> Option<usize> {
+    pub const fn get_precision(&self) -> Option<u16> {
         self.precision
     }
     /// Returns the current precision.
@@ -1499,15 +1499,18 @@ unsafe fn run(fmt: &mut Formatter<'_>, arg: &rt::Placeholder, args: &[rt::Argume
     unsafe { value.fmt(fmt) }
 }
 
-unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize> {
+unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<u16> {
     match *cnt {
+        #[cfg(bootstrap)]
+        rt::Count::Is(n) => Some(n as u16),
+        #[cfg(not(bootstrap))]
         rt::Count::Is(n) => Some(n),
         rt::Count::Implied => None,
         rt::Count::Param(i) => {
             debug_assert!(i < args.len());
             // SAFETY: cnt and args come from the same Arguments,
             // which guarantees this index is always within bounds.
-            unsafe { args.get_unchecked(i).as_usize() }
+            unsafe { args.get_unchecked(i).as_u16() }
         }
     }
 }
@@ -1516,11 +1519,11 @@ unsafe fn getcount(args: &[rt::Argument<'_>], cnt: &rt::Count) -> Option<usize>
 #[must_use = "don't forget to write the post padding"]
 pub(crate) struct PostPadding {
     fill: char,
-    padding: usize,
+    padding: u16,
 }
 
 impl PostPadding {
-    fn new(fill: char, padding: usize) -> PostPadding {
+    fn new(fill: char, padding: u16) -> PostPadding {
         PostPadding { fill, padding }
     }
 
@@ -1634,7 +1637,7 @@ impl<'a> Formatter<'a> {
             }
             // Check if we're over the minimum width, if so then we can also
             // just write the bytes.
-            Some(min) if width >= min => {
+            Some(min) if width >= usize::from(min) => {
                 write_prefix(self, sign, prefix)?;
                 self.buf.write_str(buf)
             }
@@ -1645,7 +1648,7 @@ impl<'a> Formatter<'a> {
                 let old_align =
                     crate::mem::replace(&mut self.options.align, Some(Alignment::Right));
                 write_prefix(self, sign, prefix)?;
-                let post_padding = self.padding(min - width, Alignment::Right)?;
+                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
                 self.buf.write_str(buf)?;
                 post_padding.write(self)?;
                 self.options.fill = old_fill;
@@ -1654,7 +1657,7 @@ impl<'a> Formatter<'a> {
             }
             // Otherwise, the sign and prefix goes after the padding
             Some(min) => {
-                let post_padding = self.padding(min - width, Alignment::Right)?;
+                let post_padding = self.padding(min - width as u16, Alignment::Right)?;
                 write_prefix(self, sign, prefix)?;
                 self.buf.write_str(buf)?;
                 post_padding.write(self)
@@ -1702,14 +1705,14 @@ impl<'a> Formatter<'a> {
         // string being formatted.
         let (s, char_count) = if let Some(max_char_count) = self.options.precision {
             let mut iter = s.char_indices();
-            let remaining = match iter.advance_by(max_char_count) {
+            let remaining = match iter.advance_by(usize::from(max_char_count)) {
                 Ok(()) => 0,
                 Err(remaining) => remaining.get(),
             };
             // SAFETY: The offset of `.char_indices()` is guaranteed to be
             // in-bounds and between character boundaries.
             let truncated = unsafe { s.get_unchecked(..iter.offset()) };
-            (truncated, max_char_count - remaining)
+            (truncated, usize::from(max_char_count) - remaining)
         } else {
             // Use the optimized char counting algorithm for the full string.
             (s, s.chars().count())
@@ -1717,11 +1720,11 @@ impl<'a> Formatter<'a> {
 
         // The `width` field is more of a minimum width parameter at this point.
         if let Some(width) = self.options.width
-            && char_count < width
+            && char_count < usize::from(width)
         {
             // If we're under the minimum width, then fill up the minimum width
             // with the specified string + some alignment.
-            let post_padding = self.padding(width - char_count, Alignment::Left)?;
+            let post_padding = self.padding(width - char_count as u16, Alignment::Left)?;
             self.buf.write_str(s)?;
             post_padding.write(self)
         } else {
@@ -1737,7 +1740,7 @@ impl<'a> Formatter<'a> {
     /// thing that is being padded.
     pub(crate) fn padding(
         &mut self,
-        padding: usize,
+        padding: u16,
         default: Alignment,
     ) -> result::Result<PostPadding, Error> {
         let align = self.align().unwrap_or(default);
@@ -1777,19 +1780,19 @@ impl<'a> Formatter<'a> {
 
                 // remove the sign from the formatted parts
                 formatted.sign = "";
-                width = width.saturating_sub(sign.len());
+                width = width.saturating_sub(sign.len() as u16);
                 self.options.fill = '0';
                 self.options.align = Some(Alignment::Right);
             }
 
             // remaining parts go through the ordinary padding process.
             let len = formatted.len();
-            let ret = if width <= len {
+            let ret = if usize::from(width) <= len {
                 // no padding
                 // SAFETY: Per the precondition.
                 unsafe { self.write_formatted_parts(&formatted) }
             } else {
-                let post_padding = self.padding(width - len, Alignment::Right)?;
+                let post_padding = self.padding(width - len as u16, Alignment::Right)?;
                 // SAFETY: Per the precondition.
                 unsafe {
                     self.write_formatted_parts(&formatted)?;
@@ -2021,7 +2024,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn width(&self) -> Option<usize> {
-        self.options.width
+        self.options.width.map(|x| x as usize)
     }
 
     /// Returns the optionally specified precision for numeric types.
@@ -2052,7 +2055,7 @@ impl<'a> Formatter<'a> {
     #[must_use]
     #[stable(feature = "fmt_flags", since = "1.5.0")]
     pub fn precision(&self) -> Option<usize> {
-        self.options.precision
+        self.options.precision.map(|x| x as usize)
     }
 
     /// Determines if the `+` flag was specified.
@@ -2792,7 +2795,7 @@ pub(crate) fn pointer_fmt_inner(ptr_addr: usize, f: &mut Formatter<'_>) -> Resul
         f.options.flags |= 1 << (rt::Flag::SignAwareZeroPad as u32);
 
         if f.options.width.is_none() {
-            f.options.width = Some((usize::BITS / 4) as usize + 2);
+            f.options.width = Some((usize::BITS / 4) as u16 + 2);
         }
     }
     f.options.flags |= 1 << (rt::Flag::Alternate as u32);
diff --git a/library/core/src/fmt/rt.rs b/library/core/src/fmt/rt.rs
index 85d089a0790..080fc6ddfc9 100644
--- a/library/core/src/fmt/rt.rs
+++ b/library/core/src/fmt/rt.rs
@@ -47,7 +47,11 @@ pub enum Alignment {
 #[derive(Copy, Clone)]
 pub enum Count {
     /// Specified with a literal number, stores the value
+    #[cfg(bootstrap)]
     Is(usize),
+    /// Specified with a literal number, stores the value
+    #[cfg(not(bootstrap))]
+    Is(u16),
     /// Specified using `$` and `*` syntaxes, stores the index into `args`
     Param(usize),
     /// Not specified
@@ -74,7 +78,7 @@ enum ArgumentType<'a> {
         formatter: unsafe fn(NonNull<()>, &mut Formatter<'_>) -> Result,
         _lifetime: PhantomData<&'a ()>,
     },
-    Count(usize),
+    Count(u16),
 }
 
 /// This struct represents a generic "argument" which is taken by format_args!().
@@ -150,8 +154,12 @@ impl Argument<'_> {
         Self::new(x, UpperExp::fmt)
     }
     #[inline]
+    #[track_caller]
     pub const fn from_usize(x: &usize) -> Argument<'_> {
-        Argument { ty: ArgumentType::Count(*x) }
+        if *x > u16::MAX as usize {
+            panic!("Formatting argument out of range");
+        }
+        Argument { ty: ArgumentType::Count(*x as u16) }
     }
 
     /// Format this placeholder argument.
@@ -181,7 +189,7 @@ impl Argument<'_> {
     }
 
     #[inline]
-    pub(super) const fn as_usize(&self) -> Option<usize> {
+    pub(super) const fn as_u16(&self) -> Option<u16> {
         match self.ty {
             ArgumentType::Count(count) => Some(count),
             ArgumentType::Placeholder { .. } => None,
diff --git a/library/core/src/iter/traits/iterator.rs b/library/core/src/iter/traits/iterator.rs
index 42886e90f99..10ae43ac3fc 100644
--- a/library/core/src/iter/traits/iterator.rs
+++ b/library/core/src/iter/traits/iterator.rs
@@ -1825,10 +1825,19 @@ pub trait Iterator {
         Inspect::new(self, f)
     }
 
-    /// Borrows an iterator, rather than consuming it.
+    /// Creates a "by reference" adapter for this instance of `Iterator`.
     ///
-    /// This is useful to allow applying iterator adapters while still
-    /// retaining ownership of the original iterator.
+    /// Consuming method calls (direct or indirect calls to `next`)
+    /// on the "by reference" adapter will consume the original iterator,
+    /// but ownership-taking methods (those with a `self` parameter)
+    /// only take ownership of the "by reference" iterator.
+    ///
+    /// This is useful for applying ownership-taking methods
+    /// (such as `take` in the example below)
+    /// without giving up ownership of the original iterator,
+    /// so you can use the original iterator afterwards.
+    ///
+    /// Uses [impl<I: Iterator + ?Sized> Iterator for &mut I { type Item = I::Item; ...}](https://doc.rust-lang.org/nightly/std/iter/trait.Iterator.html#impl-Iterator-for-%26mut+I).
     ///
     /// # Examples
     ///
@@ -4024,6 +4033,9 @@ where
     }
 }
 
+/// Implements `Iterator` for mutable references to iterators, such as those produced by [`Iterator::by_ref`].
+///
+/// This implementation passes all method calls on to the original iterator.
 #[stable(feature = "rust1", since = "1.0.0")]
 impl<I: Iterator + ?Sized> Iterator for &mut I {
     type Item = I::Item;
diff --git a/library/core/src/macros/mod.rs b/library/core/src/macros/mod.rs
index 16200184422..a527a2ea5aa 100644
--- a/library/core/src/macros/mod.rs
+++ b/library/core/src/macros/mod.rs
@@ -1743,6 +1743,21 @@ pub(crate) mod builtin {
         /* compiler built-in */
     }
 
+    /// Provide a list of type aliases and other opaque-type-containing type definitions.
+    /// This list will be used in the body of the item it is applied to to define opaque
+    /// types' hidden types.
+    /// Can only be applied to things that have bodies.
+    #[unstable(
+        feature = "type_alias_impl_trait",
+        issue = "63063",
+        reason = "`type_alias_impl_trait` has open design concerns"
+    )]
+    #[rustc_builtin_macro]
+    #[cfg(not(bootstrap))]
+    pub macro define_opaque($($tt:tt)*) {
+        /* compiler built-in */
+    }
+
     /// Unstable placeholder for type ascription.
     #[allow_internal_unstable(builtin_syntax)]
     #[unstable(
diff --git a/library/core/src/prelude/v1.rs b/library/core/src/prelude/v1.rs
index 50fd67e8395..c5975c03050 100644
--- a/library/core/src/prelude/v1.rs
+++ b/library/core/src/prelude/v1.rs
@@ -111,3 +111,11 @@ pub use crate::macros::builtin::type_ascribe;
     reason = "placeholder syntax for deref patterns"
 )]
 pub use crate::macros::builtin::deref;
+
+#[unstable(
+    feature = "type_alias_impl_trait",
+    issue = "63063",
+    reason = "`type_alias_impl_trait` has open design concerns"
+)]
+#[cfg(not(bootstrap))]
+pub use crate::macros::builtin::define_opaque;
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index ae28ec4baa0..54a65c8459e 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -3998,24 +3998,24 @@ unsafe fn atomic_umin<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 ///
 /// A fence 'A' which has (at least) [`Release`] ordering semantics, synchronizes
 /// with a fence 'B' with (at least) [`Acquire`] semantics, if and only if there
-/// exist operations X and Y, both operating on some atomic object 'M' such
+/// exist operations X and Y, both operating on some atomic object 'm' such
 /// that A is sequenced before X, Y is sequenced before B and Y observes
-/// the change to M. This provides a happens-before dependence between A and B.
+/// the change to m. This provides a happens-before dependence between A and B.
 ///
 /// ```text
 ///     Thread 1                                          Thread 2
 ///
 /// fence(Release);      A --------------
-/// x.store(3, Relaxed); X ---------    |
+/// m.store(3, Relaxed); X ---------    |
 ///                                |    |
 ///                                |    |
-///                                -------------> Y  if x.load(Relaxed) == 3 {
+///                                -------------> Y  if m.load(Relaxed) == 3 {
 ///                                     |-------> B      fence(Acquire);
 ///                                                      ...
 ///                                                  }
 /// ```
 ///
-/// Note that in the example above, it is crucial that the accesses to `x` are atomic. Fences cannot
+/// Note that in the example above, it is crucial that the accesses to `m` are atomic. Fences cannot
 /// be used to establish synchronization among non-atomic accesses in different threads. However,
 /// thanks to the happens-before relationship between A and B, any non-atomic accesses that
 /// happen-before A are now also properly synchronized with any non-atomic accesses that
diff --git a/library/core/src/time.rs b/library/core/src/time.rs
index 8b211b442ea..37b5c1076fa 100644
--- a/library/core/src/time.rs
+++ b/library/core/src/time.rs
@@ -1377,7 +1377,8 @@ impl fmt::Debug for Duration {
                     } else {
                         // We need to add padding. Use the `Formatter::padding` helper function.
                         let default_align = fmt::Alignment::Left;
-                        let post_padding = f.padding(requested_w - actual_w, default_align)?;
+                        let post_padding =
+                            f.padding((requested_w - actual_w) as u16, default_align)?;
                         emit_without_padding(f)?;
                         post_padding.write(f)
                     }
diff --git a/library/coretests/tests/num/flt2dec/mod.rs b/library/coretests/tests/num/flt2dec/mod.rs
index 6041923117c..c64bb0a3072 100644
--- a/library/coretests/tests/num/flt2dec/mod.rs
+++ b/library/coretests/tests/num/flt2dec/mod.rs
@@ -577,7 +577,7 @@ where
     }
 
     // very large output
-    assert_eq!(to_string(f, 1.1, Minus, 80000), format!("1.1{:0>79999}", ""));
+    assert_eq!(to_string(f, 1.1, Minus, 50000), format!("1.1{:0>49999}", ""));
 }
 
 pub fn to_shortest_exp_str_test<F>(mut f_: F)
@@ -914,22 +914,22 @@ where
     );
 
     // very large output
-    assert_eq!(to_string(f, 0.0, Minus, 80000, false), format!("0.{:0>79999}e0", ""));
-    assert_eq!(to_string(f, 1.0e1, Minus, 80000, false), format!("1.{:0>79999}e1", ""));
-    assert_eq!(to_string(f, 1.0e0, Minus, 80000, false), format!("1.{:0>79999}e0", ""));
+    assert_eq!(to_string(f, 0.0, Minus, 50000, false), format!("0.{:0>49999}e0", ""));
+    assert_eq!(to_string(f, 1.0e1, Minus, 50000, false), format!("1.{:0>49999}e1", ""));
+    assert_eq!(to_string(f, 1.0e0, Minus, 50000, false), format!("1.{:0>49999}e0", ""));
     assert_eq!(
-        to_string(f, 1.0e-1, Minus, 80000, false),
+        to_string(f, 1.0e-1, Minus, 50000, false),
         format!(
-            "1.000000000000000055511151231257827021181583404541015625{:0>79945}\
+            "1.000000000000000055511151231257827021181583404541015625{:0>49945}\
                         e-1",
             ""
         )
     );
     assert_eq!(
-        to_string(f, 1.0e-20, Minus, 80000, false),
+        to_string(f, 1.0e-20, Minus, 50000, false),
         format!(
             "9.999999999999999451532714542095716517295037027873924471077157760\
-                         66783064379706047475337982177734375{:0>79901}e-21",
+                         66783064379706047475337982177734375{:0>49901}e-21",
             ""
         )
     );
@@ -1150,18 +1150,18 @@ where
     );
 
     // very large output
-    assert_eq!(to_string(f, 0.0, Minus, 80000), format!("0.{:0>80000}", ""));
-    assert_eq!(to_string(f, 1.0e1, Minus, 80000), format!("10.{:0>80000}", ""));
-    assert_eq!(to_string(f, 1.0e0, Minus, 80000), format!("1.{:0>80000}", ""));
+    assert_eq!(to_string(f, 0.0, Minus, 50000), format!("0.{:0>50000}", ""));
+    assert_eq!(to_string(f, 1.0e1, Minus, 50000), format!("10.{:0>50000}", ""));
+    assert_eq!(to_string(f, 1.0e0, Minus, 50000), format!("1.{:0>50000}", ""));
     assert_eq!(
-        to_string(f, 1.0e-1, Minus, 80000),
-        format!("0.1000000000000000055511151231257827021181583404541015625{:0>79945}", "")
+        to_string(f, 1.0e-1, Minus, 50000),
+        format!("0.1000000000000000055511151231257827021181583404541015625{:0>49945}", "")
     );
     assert_eq!(
-        to_string(f, 1.0e-20, Minus, 80000),
+        to_string(f, 1.0e-20, Minus, 50000),
         format!(
             "0.0000000000000000000099999999999999994515327145420957165172950370\
-                          2787392447107715776066783064379706047475337982177734375{:0>79881}",
+                          2787392447107715776066783064379706047475337982177734375{:0>49881}",
             ""
         )
     );
diff --git a/library/std/Cargo.toml b/library/std/Cargo.toml
index 0ec167c2d16..f7379c413f1 100644
--- a/library/std/Cargo.toml
+++ b/library/std/Cargo.toml
@@ -73,7 +73,7 @@ fortanix-sgx-abi = { version = "0.5.0", features = [
 ], public = true }
 
 [target.'cfg(target_os = "hermit")'.dependencies]
-hermit-abi = { version = "0.4.0", features = [
+hermit-abi = { version = "0.5.0", features = [
     'rustc-dep-of-std',
 ], public = true }
 
diff --git a/library/std/src/backtrace.rs b/library/std/src/backtrace.rs
index fc333d7ff3f..3e641ac5d90 100644
--- a/library/std/src/backtrace.rs
+++ b/library/std/src/backtrace.rs
@@ -432,6 +432,7 @@ mod helper {
     use super::*;
     pub(super) type LazyResolve = impl (FnOnce() -> Capture) + Send + Sync + UnwindSafe;
 
+    #[cfg_attr(not(bootstrap), define_opaque(LazyResolve))]
     pub(super) fn lazy_resolve(mut capture: Capture) -> LazyResolve {
         move || {
             // Use the global backtrace lock to synchronize this as it's a
diff --git a/library/std/src/net/test.rs b/library/std/src/net/test.rs
index a5c3983cd89..df48b2f2420 100644
--- a/library/std/src/net/test.rs
+++ b/library/std/src/net/test.rs
@@ -31,3 +31,14 @@ pub fn tsa<A: ToSocketAddrs>(a: A) -> Result<Vec<SocketAddr>, String> {
         Err(e) => Err(e.to_string()),
     }
 }
+
+pub fn compare_ignore_zoneid(a: &SocketAddr, b: &SocketAddr) -> bool {
+    match (a, b) {
+        (SocketAddr::V6(a), SocketAddr::V6(b)) => {
+            a.ip().segments() == b.ip().segments()
+                && a.flowinfo() == b.flowinfo()
+                && a.port() == b.port()
+        }
+        _ => a == b,
+    }
+}
diff --git a/library/std/src/net/udp/tests.rs b/library/std/src/net/udp/tests.rs
index 1c8c58d1879..91da3135f97 100644
--- a/library/std/src/net/udp/tests.rs
+++ b/library/std/src/net/udp/tests.rs
@@ -1,4 +1,4 @@
-use crate::net::test::{next_test_ip4, next_test_ip6};
+use crate::net::test::{compare_ignore_zoneid, next_test_ip4, next_test_ip6};
 use crate::net::*;
 use crate::sync::mpsc::channel;
 use crate::thread;
@@ -46,7 +46,7 @@ fn socket_smoke_test_ip4() {
         let (nread, src) = t!(server.recv_from(&mut buf));
         assert_eq!(nread, 1);
         assert_eq!(buf[0], 99);
-        assert_eq!(src, client_ip);
+        assert_eq!(compare_ignore_zoneid(&src, &client_ip), true);
         rx2.recv().unwrap();
     })
 }
@@ -78,7 +78,9 @@ fn udp_clone_smoke() {
 
         let _t = thread::spawn(move || {
             let mut buf = [0, 0];
-            assert_eq!(sock2.recv_from(&mut buf).unwrap(), (1, addr1));
+            let res = sock2.recv_from(&mut buf).unwrap();
+            assert_eq!(res.0, 1);
+            assert_eq!(compare_ignore_zoneid(&res.1, &addr1), true);
             assert_eq!(buf[0], 1);
             t!(sock2.send_to(&[2], &addr1));
         });
@@ -94,7 +96,9 @@ fn udp_clone_smoke() {
         });
         tx1.send(()).unwrap();
         let mut buf = [0, 0];
-        assert_eq!(sock1.recv_from(&mut buf).unwrap(), (1, addr2));
+        let res = sock1.recv_from(&mut buf).unwrap();
+        assert_eq!(res.0, 1);
+        assert_eq!(compare_ignore_zoneid(&res.1, &addr2), true);
         rx2.recv().unwrap();
     })
 }
diff --git a/library/std/src/prelude/v1.rs b/library/std/src/prelude/v1.rs
index 5b324b2e916..4217f658640 100644
--- a/library/std/src/prelude/v1.rs
+++ b/library/std/src/prelude/v1.rs
@@ -103,6 +103,15 @@ pub use core::prelude::v1::type_ascribe;
 )]
 pub use core::prelude::v1::deref;
 
+// Do not `doc(no_inline)` either.
+#[unstable(
+    feature = "type_alias_impl_trait",
+    issue = "63063",
+    reason = "`type_alias_impl_trait` has open design concerns"
+)]
+#[cfg(not(bootstrap))]
+pub use core::prelude::v1::define_opaque;
+
 // The file so far is equivalent to core/src/prelude/v1.rs. It is duplicated
 // rather than glob imported because we want docs to show these re-exports as
 // pointing to within `std`.
diff --git a/library/std/src/sys/fs/hermit.rs b/library/std/src/sys/fs/hermit.rs
index e9339ff261c..1191e335daa 100644
--- a/library/std/src/sys/fs/hermit.rs
+++ b/library/std/src/sys/fs/hermit.rs
@@ -417,12 +417,12 @@ impl File {
         Ok(())
     }
 
-    pub fn seek(&self, _pos: SeekFrom) -> io::Result<u64> {
-        Err(Error::from_raw_os_error(22))
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        self.0.seek(pos)
     }
 
     pub fn tell(&self) -> io::Result<u64> {
-        self.seek(SeekFrom::Current(0))
+        self.0.tell()
     }
 
     pub fn duplicate(&self) -> io::Result<File> {
diff --git a/library/std/src/sys/fs/uefi.rs b/library/std/src/sys/fs/uefi.rs
index 45e93deffa3..56aed7dfd8e 100644
--- a/library/std/src/sys/fs/uefi.rs
+++ b/library/std/src/sys/fs/uefi.rs
@@ -1,14 +1,21 @@
 use crate::ffi::OsString;
 use crate::fmt;
-use crate::hash::{Hash, Hasher};
+use crate::hash::Hash;
 use crate::io::{self, BorrowedCursor, IoSlice, IoSliceMut, SeekFrom};
 use crate::path::{Path, PathBuf};
 use crate::sys::time::SystemTime;
 use crate::sys::unsupported;
 
+#[expect(dead_code)]
+const FILE_PERMISSIONS_MASK: u64 = r_efi::protocols::file::READ_ONLY;
+
 pub struct File(!);
 
-pub struct FileAttr(!);
+#[derive(Clone)]
+pub struct FileAttr {
+    attr: u64,
+    size: u64,
+}
 
 pub struct ReadDir(!);
 
@@ -20,42 +27,40 @@ pub struct OpenOptions {}
 #[derive(Copy, Clone, Debug, Default)]
 pub struct FileTimes {}
 
-pub struct FilePermissions(!);
+#[derive(Clone, PartialEq, Eq, Debug)]
+// Bool indicates if file is readonly
+pub struct FilePermissions(bool);
 
-pub struct FileType(!);
+#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
+// Bool indicates if directory
+pub struct FileType(bool);
 
 #[derive(Debug)]
 pub struct DirBuilder {}
 
 impl FileAttr {
     pub fn size(&self) -> u64 {
-        self.0
+        self.size
     }
 
     pub fn perm(&self) -> FilePermissions {
-        self.0
+        FilePermissions::from_attr(self.attr)
     }
 
     pub fn file_type(&self) -> FileType {
-        self.0
+        FileType::from_attr(self.attr)
     }
 
     pub fn modified(&self) -> io::Result<SystemTime> {
-        self.0
+        unsupported()
     }
 
     pub fn accessed(&self) -> io::Result<SystemTime> {
-        self.0
+        unsupported()
     }
 
     pub fn created(&self) -> io::Result<SystemTime> {
-        self.0
-    }
-}
-
-impl Clone for FileAttr {
-    fn clone(&self) -> FileAttr {
-        self.0
+        unsupported()
     }
 }
 
@@ -64,28 +69,17 @@ impl FilePermissions {
         self.0
     }
 
-    pub fn set_readonly(&mut self, _readonly: bool) {
-        self.0
+    pub fn set_readonly(&mut self, readonly: bool) {
+        self.0 = readonly
     }
-}
 
-impl Clone for FilePermissions {
-    fn clone(&self) -> FilePermissions {
-        self.0
+    const fn from_attr(attr: u64) -> Self {
+        Self(attr & r_efi::protocols::file::READ_ONLY != 0)
     }
-}
-
-impl PartialEq for FilePermissions {
-    fn eq(&self, _other: &FilePermissions) -> bool {
-        self.0
-    }
-}
 
-impl Eq for FilePermissions {}
-
-impl fmt::Debug for FilePermissions {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    #[expect(dead_code)]
+    const fn to_attr(&self) -> u64 {
+        if self.0 { r_efi::protocols::file::READ_ONLY } else { 0 }
     }
 }
 
@@ -100,39 +94,16 @@ impl FileType {
     }
 
     pub fn is_file(&self) -> bool {
-        self.0
+        !self.is_dir()
     }
 
+    // Symlinks are not supported in UEFI
     pub fn is_symlink(&self) -> bool {
-        self.0
-    }
-}
-
-impl Clone for FileType {
-    fn clone(&self) -> FileType {
-        self.0
+        false
     }
-}
-
-impl Copy for FileType {}
 
-impl PartialEq for FileType {
-    fn eq(&self, _other: &FileType) -> bool {
-        self.0
-    }
-}
-
-impl Eq for FileType {}
-
-impl Hash for FileType {
-    fn hash<H: Hasher>(&self, _h: &mut H) {
-        self.0
-    }
-}
-
-impl fmt::Debug for FileType {
-    fn fmt(&self, _f: &mut fmt::Formatter<'_>) -> fmt::Result {
-        self.0
+    const fn from_attr(attr: u64) -> Self {
+        Self(attr & r_efi::protocols::file::DIRECTORY != 0)
     }
 }
 
@@ -303,8 +274,8 @@ pub fn rename(_old: &Path, _new: &Path) -> io::Result<()> {
     unsupported()
 }
 
-pub fn set_perm(_p: &Path, perm: FilePermissions) -> io::Result<()> {
-    match perm.0 {}
+pub fn set_perm(_p: &Path, _perm: FilePermissions) -> io::Result<()> {
+    unsupported()
 }
 
 pub fn rmdir(_p: &Path) -> io::Result<()> {
diff --git a/library/std/src/sys/fs/unix.rs b/library/std/src/sys/fs/unix.rs
index 914971934bf..d944bc9c9a2 100644
--- a/library/std/src/sys/fs/unix.rs
+++ b/library/std/src/sys/fs/unix.rs
@@ -1454,6 +1454,20 @@ impl File {
         Ok(())
     }
 
+    // FIXME(#115199): Rust currently omits weak function definitions
+    // and its metadata from LLVM IR.
+    #[cfg_attr(
+        any(
+            target_os = "android",
+            all(
+                target_os = "linux",
+                target_env = "gnu",
+                target_pointer_width = "32",
+                not(target_arch = "riscv32")
+            )
+        ),
+        no_sanitize(cfi)
+    )]
     pub fn set_times(&self, times: FileTimes) -> io::Result<()> {
         #[cfg(not(any(
             target_os = "redox",
diff --git a/library/std/src/sys/pal/hermit/fd.rs b/library/std/src/sys/pal/hermit/fd.rs
index 79fc13bd4a8..3d6b99cd77b 100644
--- a/library/std/src/sys/pal/hermit/fd.rs
+++ b/library/std/src/sys/pal/hermit/fd.rs
@@ -2,8 +2,8 @@
 
 use super::hermit_abi;
 use crate::cmp;
-use crate::io::{self, IoSlice, IoSliceMut, Read};
-use crate::os::hermit::io::{FromRawFd, OwnedFd, RawFd, *};
+use crate::io::{self, IoSlice, IoSliceMut, Read, SeekFrom};
+use crate::os::hermit::io::{AsFd, AsRawFd, BorrowedFd, FromRawFd, IntoRawFd, OwnedFd, RawFd};
 use crate::sys::{cvt, unsupported};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 
@@ -66,9 +66,26 @@ impl FileDesc {
         true
     }
 
+    pub fn seek(&self, pos: SeekFrom) -> io::Result<u64> {
+        let (whence, pos) = match pos {
+            // Casting to `i64` is fine, too large values will end up as
+            // negative which will cause an error in `lseek`.
+            SeekFrom::Start(off) => (hermit_abi::SEEK_SET, off as i64),
+            SeekFrom::End(off) => (hermit_abi::SEEK_END, off),
+            SeekFrom::Current(off) => (hermit_abi::SEEK_CUR, off),
+        };
+        let n = cvt(unsafe { hermit_abi::lseek(self.as_raw_fd(), pos as isize, whence) })?;
+        Ok(n as u64)
+    }
+
+    pub fn tell(&self) -> io::Result<u64> {
+        self.seek(SeekFrom::Current(0))
+    }
+
     pub fn duplicate(&self) -> io::Result<FileDesc> {
         self.duplicate_path(&[])
     }
+
     pub fn duplicate_path(&self, _path: &[u8]) -> io::Result<FileDesc> {
         unsupported()
     }
diff --git a/library/std/src/sys/pal/unix/fd.rs b/library/std/src/sys/pal/unix/fd.rs
index 2fc33bdfefb..a08c7ccec2d 100644
--- a/library/std/src/sys/pal/unix/fd.rs
+++ b/library/std/src/sys/pal/unix/fd.rs
@@ -251,6 +251,9 @@ impl FileDesc {
     }
 
     #[cfg(all(target_os = "android", target_pointer_width = "32"))]
+    // FIXME(#115199): Rust currently omits weak function definitions
+    // and its metadata from LLVM IR.
+    #[no_sanitize(cfi)]
     pub fn read_vectored_at(&self, bufs: &mut [IoSliceMut<'_>], offset: u64) -> io::Result<usize> {
         super::weak::weak!(fn preadv64(libc::c_int, *const libc::iovec, libc::c_int, off64_t) -> isize);
 
diff --git a/library/std/src/sys/pal/unix/process/process_unix.rs b/library/std/src/sys/pal/unix/process/process_unix.rs
index 25d9e935332..be9a7e91990 100644
--- a/library/std/src/sys/pal/unix/process/process_unix.rs
+++ b/library/std/src/sys/pal/unix/process/process_unix.rs
@@ -434,6 +434,9 @@ impl Command {
         target_os = "nto",
         target_vendor = "apple",
     ))]
+    // FIXME(#115199): Rust currently omits weak function definitions
+    // and its metadata from LLVM IR.
+    #[cfg_attr(target_os = "linux", no_sanitize(cfi))]
     fn posix_spawn(
         &mut self,
         stdio: &ChildPipes,
diff --git a/library/std/src/sys/pal/unix/thread.rs b/library/std/src/sys/pal/unix/thread.rs
index 11f6998cac1..abe8d3fbf68 100644
--- a/library/std/src/sys/pal/unix/thread.rs
+++ b/library/std/src/sys/pal/unix/thread.rs
@@ -188,6 +188,9 @@ impl Thread {
     }
 
     #[cfg(any(target_os = "solaris", target_os = "illumos", target_os = "nto"))]
+    // FIXME(#115199): Rust currently omits weak function definitions
+    // and its metadata from LLVM IR.
+    #[no_sanitize(cfi)]
     pub fn set_name(name: &CStr) {
         weak! {
             fn pthread_setname_np(
diff --git a/library/std/src/sys/pal/unix/time.rs b/library/std/src/sys/pal/unix/time.rs
index 0271626380c..c0a3044660b 100644
--- a/library/std/src/sys/pal/unix/time.rs
+++ b/library/std/src/sys/pal/unix/time.rs
@@ -96,6 +96,17 @@ impl Timespec {
         }
     }
 
+    // FIXME(#115199): Rust currently omits weak function definitions
+    // and its metadata from LLVM IR.
+    #[cfg_attr(
+        all(
+            target_os = "linux",
+            target_env = "gnu",
+            target_pointer_width = "32",
+            not(target_arch = "riscv32")
+        ),
+        no_sanitize(cfi)
+    )]
     pub fn now(clock: libc::clockid_t) -> Timespec {
         use crate::mem::MaybeUninit;
         use crate::sys::cvt;
diff --git a/library/std/src/sys/pal/unix/weak.rs b/library/std/src/sys/pal/unix/weak.rs
index 7ec4787f1ea..ce3f66a8374 100644
--- a/library/std/src/sys/pal/unix/weak.rs
+++ b/library/std/src/sys/pal/unix/weak.rs
@@ -144,6 +144,9 @@ unsafe fn fetch(name: &str) -> *mut libc::c_void {
 #[cfg(not(any(target_os = "linux", target_os = "android")))]
 pub(crate) macro syscall {
     (fn $name:ident($($arg_name:ident: $t:ty),*) -> $ret:ty) => (
+        // FIXME(#115199): Rust currently omits weak function definitions
+        // and its metadata from LLVM IR.
+        #[no_sanitize(cfi)]
         unsafe fn $name($($arg_name: $t),*) -> $ret {
             weak! { fn $name($($t),*) -> $ret }
 
diff --git a/library/unwind/src/libunwind.rs b/library/unwind/src/libunwind.rs
index 1a640bbde71..ced8e82b8eb 100644
--- a/library/unwind/src/libunwind.rs
+++ b/library/unwind/src/libunwind.rs
@@ -72,9 +72,12 @@ pub const unwinder_private_data_size: usize = 2;
 #[cfg(any(target_arch = "riscv64", target_arch = "riscv32"))]
 pub const unwinder_private_data_size: usize = 2;
 
-#[cfg(target_os = "emscripten")]
+#[cfg(all(target_arch = "wasm32", target_os = "emscripten"))]
 pub const unwinder_private_data_size: usize = 20;
 
+#[cfg(all(target_arch = "wasm32", target_os = "linux"))]
+pub const unwinder_private_data_size: usize = 2;
+
 #[cfg(all(target_arch = "hexagon", target_os = "linux"))]
 pub const unwinder_private_data_size: usize = 35;
 
diff --git a/src/bootstrap/Cargo.toml b/src/bootstrap/Cargo.toml
index 2c1d85b01e6..2ea2596088f 100644
--- a/src/bootstrap/Cargo.toml
+++ b/src/bootstrap/Cargo.toml
@@ -1,7 +1,7 @@
 [package]
 name = "bootstrap"
 version = "0.0.0"
-edition = "2021"
+edition = "2024"
 build = "build.rs"
 default-run = "bootstrap"
 
diff --git a/src/bootstrap/configure.py b/src/bootstrap/configure.py
index c3b25646439..77151edd240 100755
--- a/src/bootstrap/configure.py
+++ b/src/bootstrap/configure.py
@@ -270,6 +270,11 @@ v(
     "loongarch64-unknown-linux-musl install directory",
 )
 v(
+    "musl-root-wali-wasm32",
+    "target.wasm32-wali-linux-musl.musl-root",
+    "wasm32-wali-linux-musl install directory",
+)
+v(
     "qemu-armhf-rootfs",
     "target.arm-unknown-linux-gnueabihf.qemu-rootfs",
     "rootfs in qemu testing, you probably don't want to use this",
diff --git a/src/bootstrap/download-ci-gcc-stamp b/src/bootstrap/download-ci-gcc-stamp
new file mode 100644
index 00000000000..bbe26afc952
--- /dev/null
+++ b/src/bootstrap/download-ci-gcc-stamp
@@ -0,0 +1,4 @@
+Change this file to make users of the `download-ci-gcc` configuration download
+a new version of GCC from CI, even if the GCC submodule hasn’t changed.
+
+Last change is for: https://github.com/rust-lang/rust/pull/138051
diff --git a/src/bootstrap/src/bin/sccache-plus-cl.rs b/src/bootstrap/src/bin/sccache-plus-cl.rs
index 6e87d4222e8..c161d69d5f7 100644
--- a/src/bootstrap/src/bin/sccache-plus-cl.rs
+++ b/src/bootstrap/src/bin/sccache-plus-cl.rs
@@ -4,8 +4,13 @@ use std::process::{self, Command};
 fn main() {
     let target = env::var("SCCACHE_TARGET").unwrap();
     // Locate the actual compiler that we're invoking
-    env::set_var("CC", env::var_os("SCCACHE_CC").unwrap());
-    env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap());
+
+    // SAFETY: we're in main, there are no other threads
+    unsafe {
+        env::set_var("CC", env::var_os("SCCACHE_CC").unwrap());
+        env::set_var("CXX", env::var_os("SCCACHE_CXX").unwrap());
+    }
+
     let mut cfg = cc::Build::new();
     cfg.cargo_metadata(false)
         .out_dir("/")
diff --git a/src/bootstrap/src/core/build_steps/compile.rs b/src/bootstrap/src/core/build_steps/compile.rs
index 319a2233b1c..8cb3e3ed872 100644
--- a/src/bootstrap/src/core/build_steps/compile.rs
+++ b/src/bootstrap/src/core/build_steps/compile.rs
@@ -390,24 +390,38 @@ fn copy_self_contained_objects(
         let srcdir = builder.musl_libdir(target).unwrap_or_else(|| {
             panic!("Target {:?} does not have a \"musl-libdir\" key", target.triple)
         });
-        for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
-            copy_and_stamp(
-                builder,
-                &libdir_self_contained,
-                &srcdir,
-                obj,
-                &mut target_deps,
-                DependencyType::TargetSelfContained,
-            );
-        }
-        let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
-        for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
-            let src = crt_path.join(obj);
-            let target = libdir_self_contained.join(obj);
-            builder.copy_link(&src, &target);
-            target_deps.push((target, DependencyType::TargetSelfContained));
+        if !target.starts_with("wasm32") {
+            for &obj in &["libc.a", "crt1.o", "Scrt1.o", "rcrt1.o", "crti.o", "crtn.o"] {
+                copy_and_stamp(
+                    builder,
+                    &libdir_self_contained,
+                    &srcdir,
+                    obj,
+                    &mut target_deps,
+                    DependencyType::TargetSelfContained,
+                );
+            }
+            let crt_path = builder.ensure(llvm::CrtBeginEnd { target });
+            for &obj in &["crtbegin.o", "crtbeginS.o", "crtend.o", "crtendS.o"] {
+                let src = crt_path.join(obj);
+                let target = libdir_self_contained.join(obj);
+                builder.copy_link(&src, &target);
+                target_deps.push((target, DependencyType::TargetSelfContained));
+            }
+        } else {
+            // For wasm32 targets, we need to copy the libc.a and crt1-command.o files from the
+            // musl-libdir, but we don't need the other files.
+            for &obj in &["libc.a", "crt1-command.o"] {
+                copy_and_stamp(
+                    builder,
+                    &libdir_self_contained,
+                    &srcdir,
+                    obj,
+                    &mut target_deps,
+                    DependencyType::TargetSelfContained,
+                );
+            }
         }
-
         if !target.starts_with("s390x") {
             let libunwind_path = copy_llvm_libunwind(builder, target, &libdir_self_contained);
             target_deps.push((libunwind_path, DependencyType::TargetSelfContained));
diff --git a/src/bootstrap/src/core/build_steps/format.rs b/src/bootstrap/src/core/build_steps/format.rs
index c7eafadee2d..9817e47baa1 100644
--- a/src/bootstrap/src/core/build_steps/format.rs
+++ b/src/bootstrap/src/core/build_steps/format.rs
@@ -27,7 +27,7 @@ fn rustfmt(
     rustfmt: &Path,
     paths: &[PathBuf],
     check: bool,
-) -> impl FnMut(bool) -> RustfmtStatus {
+) -> impl FnMut(bool) -> RustfmtStatus + use<> {
     let mut cmd = Command::new(rustfmt);
     // Avoid the submodule config paths from coming into play. We only allow a single global config
     // for the workspace for now.
diff --git a/src/bootstrap/src/core/build_steps/gcc.rs b/src/bootstrap/src/core/build_steps/gcc.rs
index 70789fbbeeb..5a4bc9bdbcb 100644
--- a/src/bootstrap/src/core/build_steps/gcc.rs
+++ b/src/bootstrap/src/core/build_steps/gcc.rs
@@ -14,13 +14,67 @@ use std::sync::OnceLock;
 
 use build_helper::ci::CiEnv;
 
-use crate::Kind;
-use crate::core::builder::{Builder, Cargo, RunConfig, ShouldRun, Step};
+use crate::core::builder::{Builder, Cargo, Kind, RunConfig, ShouldRun, Step};
 use crate::core::config::TargetSelection;
 use crate::utils::build_stamp::{BuildStamp, generate_smart_stamp_hash};
 use crate::utils::exec::command;
 use crate::utils::helpers::{self, t};
 
+#[derive(Debug, Clone, Hash, PartialEq, Eq)]
+pub struct Gcc {
+    pub target: TargetSelection,
+}
+
+#[derive(Clone)]
+pub struct GccOutput {
+    pub libgccjit: PathBuf,
+}
+
+impl Step for Gcc {
+    type Output = GccOutput;
+
+    const ONLY_HOSTS: bool = true;
+
+    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
+        run.path("src/gcc").alias("gcc")
+    }
+
+    fn make_run(run: RunConfig<'_>) {
+        run.builder.ensure(Gcc { target: run.target });
+    }
+
+    /// Compile GCC (specifically `libgccjit`) for `target`.
+    fn run(self, builder: &Builder<'_>) -> Self::Output {
+        let target = self.target;
+
+        // If GCC has already been built, we avoid building it again.
+        let metadata = match get_gcc_build_status(builder, target) {
+            GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path },
+            GccBuildStatus::ShouldBuild(m) => m,
+        };
+
+        let _guard = builder.msg_unstaged(Kind::Build, "GCC", target);
+        t!(metadata.stamp.remove());
+        let _time = helpers::timeit(builder);
+
+        let libgccjit_path = libgccjit_built_path(&metadata.install_dir);
+        if builder.config.dry_run() {
+            return GccOutput { libgccjit: libgccjit_path };
+        }
+
+        build_gcc(&metadata, builder, target);
+
+        let lib_alias = metadata.install_dir.join("lib/libgccjit.so.0");
+        if !lib_alias.exists() {
+            t!(builder.symlink_file(&libgccjit_path, lib_alias));
+        }
+
+        t!(metadata.stamp.write());
+
+        GccOutput { libgccjit: libgccjit_path }
+    }
+}
+
 pub struct Meta {
     stamp: BuildStamp,
     out_dir: PathBuf,
@@ -34,17 +88,45 @@ pub enum GccBuildStatus {
     ShouldBuild(Meta),
 }
 
-/// This returns whether we've already previously built GCC.
+/// Tries to download GCC from CI if it is enabled and GCC artifacts
+/// are available for the given target.
+/// Returns a path to the libgccjit.so file.
+#[cfg(not(test))]
+fn try_download_gcc(builder: &Builder<'_>, target: TargetSelection) -> Option<PathBuf> {
+    // Try to download GCC from CI if configured and available
+    if !matches!(builder.config.gcc_ci_mode, crate::core::config::GccCiMode::DownloadFromCi) {
+        return None;
+    }
+    if target != "x86_64-unknown-linux-gnu" {
+        eprintln!("GCC CI download is only available for the `x86_64-unknown-linux-gnu` target");
+        return None;
+    }
+    let sha =
+        detect_gcc_sha(&builder.config, builder.config.rust_info.is_managed_git_subrepository());
+    let root = ci_gcc_root(&builder.config);
+    let gcc_stamp = BuildStamp::new(&root).with_prefix("gcc").add_stamp(&sha);
+    if !gcc_stamp.is_up_to_date() && !builder.config.dry_run() {
+        builder.config.download_ci_gcc(&sha, &root);
+        t!(gcc_stamp.write());
+    }
+    // FIXME: put libgccjit.so into a lib directory in dist::Gcc
+    Some(root.join("libgccjit.so"))
+}
+
+#[cfg(test)]
+fn try_download_gcc(_builder: &Builder<'_>, _target: TargetSelection) -> Option<PathBuf> {
+    None
+}
+
+/// This returns information about whether GCC should be built or if it's already built.
+/// It transparently handles downloading GCC from CI if needed.
 ///
 /// It's used to avoid busting caches during x.py check -- if we've already built
 /// GCC, it's fine for us to not try to avoid doing so.
-pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus {
-    // Initialize the gcc submodule if not initialized already.
-    builder.config.update_submodule("src/gcc");
-
-    let root = builder.src.join("src/gcc");
-    let out_dir = builder.gcc_out(target).join("build");
-    let install_dir = builder.gcc_out(target).join("install");
+pub fn get_gcc_build_status(builder: &Builder<'_>, target: TargetSelection) -> GccBuildStatus {
+    if let Some(path) = try_download_gcc(builder, target) {
+        return GccBuildStatus::AlreadyBuilt(path);
+    }
 
     static STAMP_HASH_MEMO: OnceLock<String> = OnceLock::new();
     let smart_stamp_hash = STAMP_HASH_MEMO.get_or_init(|| {
@@ -55,6 +137,13 @@ pub fn prebuilt_gcc_config(builder: &Builder<'_>, target: TargetSelection) -> Gc
         )
     });
 
+    // Initialize the gcc submodule if not initialized already.
+    builder.config.update_submodule("src/gcc");
+
+    let root = builder.src.join("src/gcc");
+    let out_dir = builder.gcc_out(target).join("build");
+    let install_dir = builder.gcc_out(target).join("install");
+
     let stamp = BuildStamp::new(&out_dir).with_prefix("gcc").add_stamp(smart_stamp_hash);
 
     if stamp.is_up_to_date() {
@@ -87,125 +176,72 @@ fn libgccjit_built_path(install_dir: &Path) -> PathBuf {
     install_dir.join("lib/libgccjit.so")
 }
 
-#[derive(Debug, Clone, Hash, PartialEq, Eq)]
-pub struct Gcc {
-    pub target: TargetSelection,
-}
-
-#[derive(Clone)]
-pub struct GccOutput {
-    pub libgccjit: PathBuf,
-}
-
-impl Step for Gcc {
-    type Output = GccOutput;
-
-    const ONLY_HOSTS: bool = true;
-
-    fn should_run(run: ShouldRun<'_>) -> ShouldRun<'_> {
-        run.path("src/gcc").alias("gcc")
-    }
-
-    fn make_run(run: RunConfig<'_>) {
-        run.builder.ensure(Gcc { target: run.target });
-    }
-
-    /// Compile GCC (specifically `libgccjit`) for `target`.
-    fn run(self, builder: &Builder<'_>) -> Self::Output {
-        let target = self.target;
-
-        // If GCC has already been built, we avoid building it again.
-        let Meta { stamp, out_dir, install_dir, root } = match prebuilt_gcc_config(builder, target)
-        {
-            GccBuildStatus::AlreadyBuilt(path) => return GccOutput { libgccjit: path },
-            GccBuildStatus::ShouldBuild(m) => m,
-        };
+fn build_gcc(metadata: &Meta, builder: &Builder<'_>, target: TargetSelection) {
+    let Meta { stamp: _, out_dir, install_dir, root } = metadata;
 
-        let _guard = builder.msg_unstaged(Kind::Build, "GCC", target);
-        t!(stamp.remove());
-        let _time = helpers::timeit(builder);
-        t!(fs::create_dir_all(&out_dir));
-        t!(fs::create_dir_all(&install_dir));
+    t!(fs::create_dir_all(out_dir));
+    t!(fs::create_dir_all(install_dir));
 
-        let libgccjit_path = libgccjit_built_path(&install_dir);
-        if builder.config.dry_run() {
-            return GccOutput { libgccjit: libgccjit_path };
+    // GCC creates files (e.g. symlinks to the downloaded dependencies)
+    // in the source directory, which does not work with our CI setup, where we mount
+    // source directories as read-only on Linux.
+    // Therefore, as a part of the build in CI, we first copy the whole source directory
+    // to the build directory, and perform the build from there.
+    let src_dir = if CiEnv::is_ci() {
+        let src_dir = builder.gcc_out(target).join("src");
+        if src_dir.exists() {
+            builder.remove_dir(&src_dir);
         }
+        builder.create_dir(&src_dir);
+        builder.cp_link_r(root, &src_dir);
+        src_dir
+    } else {
+        root.clone()
+    };
 
-        // GCC creates files (e.g. symlinks to the downloaded dependencies)
-        // in the source directory, which does not work with our CI setup, where we mount
-        // source directories as read-only on Linux.
-        // Therefore, as a part of the build in CI, we first copy the whole source directory
-        // to the build directory, and perform the build from there.
-        let src_dir = if CiEnv::is_ci() {
-            let src_dir = builder.gcc_out(target).join("src");
-            if src_dir.exists() {
-                builder.remove_dir(&src_dir);
-            }
-            builder.create_dir(&src_dir);
-            builder.cp_link_r(&root, &src_dir);
-            src_dir
-        } else {
-            root
-        };
+    command(src_dir.join("contrib/download_prerequisites")).current_dir(&src_dir).run(builder);
+    let mut configure_cmd = command(src_dir.join("configure"));
+    configure_cmd
+        .current_dir(out_dir)
+        // On CI, we compile GCC with Clang.
+        // The -Wno-everything flag is needed to make GCC compile with Clang 19.
+        // `-g -O2` are the default flags that are otherwise used by Make.
+        // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml.
+        .env("CXXFLAGS", "-Wno-everything -g -O2")
+        .env("CFLAGS", "-Wno-everything -g -O2")
+        .arg("--enable-host-shared")
+        .arg("--enable-languages=jit")
+        .arg("--enable-checking=release")
+        .arg("--disable-bootstrap")
+        .arg("--disable-multilib")
+        .arg(format!("--prefix={}", install_dir.display()));
+    let cc = builder.build.cc(target).display().to_string();
+    let cc = builder
+        .build
+        .config
+        .ccache
+        .as_ref()
+        .map_or_else(|| cc.clone(), |ccache| format!("{ccache} {cc}"));
+    configure_cmd.env("CC", cc);
 
-        command(src_dir.join("contrib/download_prerequisites")).current_dir(&src_dir).run(builder);
-        let mut configure_cmd = command(src_dir.join("configure"));
-        configure_cmd
-            .current_dir(&out_dir)
-            // On CI, we compile GCC with Clang.
-            // The -Wno-everything flag is needed to make GCC compile with Clang 19.
-            // `-g -O2` are the default flags that are otherwise used by Make.
-            // FIXME(kobzol): change the flags once we have [gcc] configuration in config.toml.
-            .env("CXXFLAGS", "-Wno-everything -g -O2")
-            .env("CFLAGS", "-Wno-everything -g -O2")
-            .arg("--enable-host-shared")
-            .arg("--enable-languages=jit")
-            .arg("--enable-checking=release")
-            .arg("--disable-bootstrap")
-            .arg("--disable-multilib")
-            .arg(format!("--prefix={}", install_dir.display()));
-        let cc = builder.build.cc(target).display().to_string();
-        let cc = builder
+    if let Ok(ref cxx) = builder.build.cxx(target) {
+        let cxx = cxx.display().to_string();
+        let cxx = builder
             .build
             .config
             .ccache
             .as_ref()
-            .map_or_else(|| cc.clone(), |ccache| format!("{ccache} {cc}"));
-        configure_cmd.env("CC", cc);
-
-        if let Ok(ref cxx) = builder.build.cxx(target) {
-            let cxx = cxx.display().to_string();
-            let cxx = builder
-                .build
-                .config
-                .ccache
-                .as_ref()
-                .map_or_else(|| cxx.clone(), |ccache| format!("{ccache} {cxx}"));
-            configure_cmd.env("CXX", cxx);
-        }
-        configure_cmd.run(builder);
-
-        command("make")
-            .current_dir(&out_dir)
-            .arg("--silent")
-            .arg(format!("-j{}", builder.jobs()))
-            .run_capture_stdout(builder);
-        command("make")
-            .current_dir(&out_dir)
-            .arg("--silent")
-            .arg("install")
-            .run_capture_stdout(builder);
-
-        let lib_alias = install_dir.join("lib/libgccjit.so.0");
-        if !lib_alias.exists() {
-            t!(builder.symlink_file(&libgccjit_path, lib_alias));
-        }
-
-        t!(stamp.write());
-
-        GccOutput { libgccjit: libgccjit_path }
+            .map_or_else(|| cxx.clone(), |ccache| format!("{ccache} {cxx}"));
+        configure_cmd.env("CXX", cxx);
     }
+    configure_cmd.run(builder);
+
+    command("make")
+        .current_dir(out_dir)
+        .arg("--silent")
+        .arg(format!("-j{}", builder.jobs()))
+        .run_capture_stdout(builder);
+    command("make").current_dir(out_dir).arg("--silent").arg("install").run_capture_stdout(builder);
 }
 
 /// Configures a Cargo invocation so that it can build the GCC codegen backend.
@@ -213,3 +249,38 @@ pub fn add_cg_gcc_cargo_flags(cargo: &mut Cargo, gcc: &GccOutput) {
     // Add the path to libgccjit.so to the linker search paths.
     cargo.rustflag(&format!("-L{}", gcc.libgccjit.parent().unwrap().to_str().unwrap()));
 }
+
+/// The absolute path to the downloaded GCC artifacts.
+#[cfg(not(test))]
+fn ci_gcc_root(config: &crate::Config) -> PathBuf {
+    config.out.join(config.build).join("ci-gcc")
+}
+
+/// This retrieves the GCC sha we *want* to use, according to git history.
+#[cfg(not(test))]
+fn detect_gcc_sha(config: &crate::Config, is_git: bool) -> String {
+    use build_helper::git::get_closest_merge_commit;
+
+    let gcc_sha = if is_git {
+        get_closest_merge_commit(
+            Some(&config.src),
+            &config.git_config(),
+            &[config.src.join("src/gcc"), config.src.join("src/bootstrap/download-ci-gcc-stamp")],
+        )
+        .unwrap()
+    } else if let Some(info) = crate::utils::channel::read_commit_info_file(&config.src) {
+        info.sha.trim().to_owned()
+    } else {
+        "".to_owned()
+    };
+
+    if gcc_sha.is_empty() {
+        eprintln!("error: could not find commit hash for downloading GCC");
+        eprintln!("HELP: maybe your repository history is too shallow?");
+        eprintln!("HELP: consider disabling `download-ci-gcc`");
+        eprintln!("HELP: or fetch enough history to include one upstream commit");
+        panic!();
+    }
+
+    gcc_sha
+}
diff --git a/src/bootstrap/src/core/build_steps/vendor.rs b/src/bootstrap/src/core/build_steps/vendor.rs
index 984c70955d7..0caeb328811 100644
--- a/src/bootstrap/src/core/build_steps/vendor.rs
+++ b/src/bootstrap/src/core/build_steps/vendor.rs
@@ -103,6 +103,7 @@ impl Step for Vendor {
         // Will read the libstd Cargo.toml
         // which uses the unstable `public-dependency` feature.
         cmd.env("RUSTC_BOOTSTRAP", "1");
+        cmd.env("RUSTC", &builder.initial_rustc);
 
         cmd.current_dir(self.root_dir).arg(&self.output_dir);
 
diff --git a/src/bootstrap/src/core/builder/tests.rs b/src/bootstrap/src/core/builder/tests.rs
index e8820e3a828..b062781e68a 100644
--- a/src/bootstrap/src/core/builder/tests.rs
+++ b/src/bootstrap/src/core/builder/tests.rs
@@ -261,8 +261,14 @@ fn ci_rustc_if_unchanged_logic() {
     // Make sure "if-unchanged" logic doesn't try to use CI rustc while there are changes
     // in compiler and/or library.
     if config.download_rustc_commit.is_some() {
-        let has_changes =
-            config.last_modified_commit(&["compiler", "library"], "download-rustc", true).is_none();
+        let mut paths = vec!["compiler"];
+
+        // Handle library tree the same way as in `Config::download_ci_rustc_commit`.
+        if build_helper::ci::CiEnv::is_ci() {
+            paths.push("library");
+        }
+
+        let has_changes = config.last_modified_commit(&paths, "download-rustc", true).is_none();
 
         assert!(
             !has_changes,
diff --git a/src/bootstrap/src/core/config/config.rs b/src/bootstrap/src/core/config/config.rs
index ac24da9f86b..a07c40bdc83 100644
--- a/src/bootstrap/src/core/config/config.rs
+++ b/src/bootstrap/src/core/config/config.rs
@@ -171,6 +171,17 @@ impl LldMode {
     }
 }
 
+/// Determines how will GCC be provided.
+#[derive(Default, Clone)]
+pub enum GccCiMode {
+    /// Build GCC from the local `src/gcc` submodule.
+    #[default]
+    BuildLocally,
+    /// Try to download GCC from CI.
+    /// If it is not available on CI, it will be built locally instead.
+    DownloadFromCi,
+}
+
 /// Global configuration for the entire build and/or bootstrap.
 ///
 /// This structure is parsed from `config.toml`, and some of the fields are inferred from `git` or build-time parameters.
@@ -283,6 +294,9 @@ pub struct Config {
     pub llvm_ldflags: Option<String>,
     pub llvm_use_libcxx: bool,
 
+    // gcc codegen options
+    pub gcc_ci_mode: GccCiMode,
+
     // rust codegen options
     pub rust_optimize: RustOptimize,
     pub rust_codegen_units: Option<u32>,
@@ -676,6 +690,7 @@ pub(crate) struct TomlConfig {
     build: Option<Build>,
     install: Option<Install>,
     llvm: Option<Llvm>,
+    gcc: Option<Gcc>,
     rust: Option<Rust>,
     target: Option<HashMap<String, TomlTarget>>,
     dist: Option<Dist>,
@@ -710,7 +725,7 @@ trait Merge {
 impl Merge for TomlConfig {
     fn merge(
         &mut self,
-        TomlConfig { build, install, llvm, rust, dist, target, profile, change_id }: Self,
+        TomlConfig { build, install, llvm, gcc, rust, dist, target, profile, change_id }: Self,
         replace: ReplaceOpt,
     ) {
         fn do_merge<T: Merge>(x: &mut Option<T>, y: Option<T>, replace: ReplaceOpt) {
@@ -729,6 +744,7 @@ impl Merge for TomlConfig {
         do_merge(&mut self.build, build, replace);
         do_merge(&mut self.install, install, replace);
         do_merge(&mut self.llvm, llvm, replace);
+        do_merge(&mut self.gcc, gcc, replace);
         do_merge(&mut self.rust, rust, replace);
         do_merge(&mut self.dist, dist, replace);
 
@@ -996,6 +1012,13 @@ define_config! {
 }
 
 define_config! {
+    /// TOML representation of how the GCC build is configured.
+    struct Gcc {
+        download_ci_gcc: Option<bool> = "download-ci-gcc",
+    }
+}
+
+define_config! {
     struct Dist {
         sign_folder: Option<String> = "sign-folder",
         upload_addr: Option<String> = "upload-addr",
@@ -2136,6 +2159,16 @@ impl Config {
             config.llvm_from_ci = config.parse_download_ci_llvm(None, false);
         }
 
+        if let Some(gcc) = toml.gcc {
+            config.gcc_ci_mode = match gcc.download_ci_gcc {
+                Some(value) => match value {
+                    true => GccCiMode::DownloadFromCi,
+                    false => GccCiMode::BuildLocally,
+                },
+                None => GccCiMode::default(),
+            };
+        }
+
         if let Some(t) = toml.target {
             for (triple, cfg) in t {
                 let mut target = Target::from_triple(&triple);
@@ -2985,6 +3018,9 @@ impl Config {
         // these changes to speed up the build process for library developers. This provides consistent
         // functionality for library developers between `download-rustc=true` and `download-rustc="if-unchanged"`
         // options.
+        //
+        // If you update "library" logic here, update `builder::tests::ci_rustc_if_unchanged_logic` test
+        // logic accordingly.
         if !CiEnv::is_ci() {
             allowed_paths.push(":!library");
         }
diff --git a/src/bootstrap/src/core/download.rs b/src/bootstrap/src/core/download.rs
index c477bdb829a..95feb41ffd0 100644
--- a/src/bootstrap/src/core/download.rs
+++ b/src/bootstrap/src/core/download.rs
@@ -826,6 +826,34 @@ download-rustc = false
         let llvm_root = self.ci_llvm_root();
         self.unpack(&tarball, &llvm_root, "rust-dev");
     }
+
+    pub fn download_ci_gcc(&self, gcc_sha: &str, root_dir: &Path) {
+        let cache_prefix = format!("gcc-{gcc_sha}");
+        let cache_dst =
+            self.bootstrap_cache_path.as_ref().cloned().unwrap_or_else(|| self.out.join("cache"));
+
+        let gcc_cache = cache_dst.join(cache_prefix);
+        if !gcc_cache.exists() {
+            t!(fs::create_dir_all(&gcc_cache));
+        }
+        let base = &self.stage0_metadata.config.artifacts_server;
+        let filename = format!("gcc-nightly-{}.tar.xz", self.build.triple);
+        let tarball = gcc_cache.join(&filename);
+        if !tarball.exists() {
+            let help_on_error = "ERROR: failed to download gcc from ci
+
+    HELP: There could be two reasons behind this:
+        1) The host triple is not supported for `download-ci-gcc`.
+        2) Old builds get deleted after a certain time.
+    HELP: In either case, disable `download-ci-gcc` in your config.toml:
+
+    [gcc]
+    download-ci-gcc = false
+    ";
+            self.download_file(&format!("{base}/{gcc_sha}/{filename}"), &tarball, help_on_error);
+        }
+        self.unpack(&tarball, root_dir, "gcc");
+    }
 }
 
 fn path_is_dylib(path: &Path) -> bool {
diff --git a/src/bootstrap/src/core/sanity.rs b/src/bootstrap/src/core/sanity.rs
index fdac7f3cb17..583b8e1198a 100644
--- a/src/bootstrap/src/core/sanity.rs
+++ b/src/bootstrap/src/core/sanity.rs
@@ -34,6 +34,7 @@ pub struct Finder {
 // Targets can be removed from this list once they are present in the stage0 compiler (usually by updating the beta compiler of the bootstrap).
 const STAGE0_MISSING_TARGETS: &[&str] = &[
     // just a dummy comment so the list doesn't get onelined
+    "wasm32-wali-linux-musl",
 ];
 
 /// Minimum version threshold for libstdc++ required when using prebuilt LLVM
diff --git a/src/bootstrap/src/utils/cc_detect/tests.rs b/src/bootstrap/src/utils/cc_detect/tests.rs
index 006dfe7e5d7..c97529cbe9e 100644
--- a/src/bootstrap/src/utils/cc_detect/tests.rs
+++ b/src/bootstrap/src/utils/cc_detect/tests.rs
@@ -9,20 +9,24 @@ use crate::{Build, Config, Flags};
 fn test_cc2ar_env_specific() {
     let triple = "x86_64-unknown-linux-gnu";
     let key = "AR_x86_64_unknown_linux_gnu";
-    env::set_var(key, "custom-ar");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::set_var(key, "custom-ar") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
     let result = cc2ar(cc, target, default_ar);
-    env::remove_var(key);
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var(key) };
     assert_eq!(result, Some(PathBuf::from("custom-ar")));
 }
 
 #[test]
 fn test_cc2ar_musl() {
     let triple = "x86_64-unknown-linux-musl";
-    env::remove_var("AR_x86_64_unknown_linux_musl");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_x86_64_unknown_linux_musl") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -33,8 +37,10 @@ fn test_cc2ar_musl() {
 #[test]
 fn test_cc2ar_openbsd() {
     let triple = "x86_64-unknown-openbsd";
-    env::remove_var("AR_x86_64_unknown_openbsd");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_x86_64_unknown_openbsd") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/cc");
     let default_ar = PathBuf::from("default-ar");
@@ -45,8 +51,10 @@ fn test_cc2ar_openbsd() {
 #[test]
 fn test_cc2ar_vxworks() {
     let triple = "armv7-wrs-vxworks";
-    env::remove_var("AR_armv7_wrs_vxworks");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_armv7_wrs_vxworks") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -57,8 +65,10 @@ fn test_cc2ar_vxworks() {
 #[test]
 fn test_cc2ar_nto_i586() {
     let triple = "i586-unknown-nto-something";
-    env::remove_var("AR_i586_unknown_nto_something");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_i586_unknown_nto_something") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -69,8 +79,10 @@ fn test_cc2ar_nto_i586() {
 #[test]
 fn test_cc2ar_nto_aarch64() {
     let triple = "aarch64-unknown-nto-something";
-    env::remove_var("AR_aarch64_unknown_nto_something");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_aarch64_unknown_nto_something") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -81,8 +93,10 @@ fn test_cc2ar_nto_aarch64() {
 #[test]
 fn test_cc2ar_nto_x86_64() {
     let triple = "x86_64-unknown-nto-something";
-    env::remove_var("AR_x86_64_unknown_nto_something");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_x86_64_unknown_nto_something") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -94,8 +108,10 @@ fn test_cc2ar_nto_x86_64() {
 #[should_panic(expected = "Unknown architecture, cannot determine archiver for Neutrino QNX")]
 fn test_cc2ar_nto_unknown() {
     let triple = "powerpc-unknown-nto-something";
-    env::remove_var("AR_powerpc_unknown_nto_something");
-    env::remove_var("AR");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR_powerpc_unknown_nto_something") };
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::remove_var("AR") };
     let target = TargetSelection::from_user(triple);
     let cc = Path::new("/usr/bin/clang");
     let default_ar = PathBuf::from("default-ar");
@@ -177,7 +193,8 @@ fn test_default_compiler_wasi() {
     let build = Build::new(Config { ..Config::parse(Flags::parse(&["check".to_owned()])) });
     let target = TargetSelection::from_user("wasm32-wasi");
     let wasi_sdk = PathBuf::from("/wasi-sdk");
-    env::set_var("WASI_SDK_PATH", &wasi_sdk);
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe { env::set_var("WASI_SDK_PATH", &wasi_sdk) };
     let mut cfg = cc::Build::new();
     if let Some(result) = default_compiler(&mut cfg, Language::C, target.clone(), &build) {
         let expected = {
@@ -190,7 +207,10 @@ fn test_default_compiler_wasi() {
             "default_compiler should return a compiler path for wasi target when WASI_SDK_PATH is set"
         );
     }
-    env::remove_var("WASI_SDK_PATH");
+    // SAFETY: bootstrap tests run on a single thread
+    unsafe {
+        env::remove_var("WASI_SDK_PATH");
+    }
 }
 
 #[test]
diff --git a/src/bootstrap/src/utils/change_tracker.rs b/src/bootstrap/src/utils/change_tracker.rs
index 425ffdccad5..ec27109c117 100644
--- a/src/bootstrap/src/utils/change_tracker.rs
+++ b/src/bootstrap/src/utils/change_tracker.rs
@@ -370,4 +370,9 @@ pub const CONFIG_CHANGE_HISTORY: &[ChangeInfo] = &[
         severity: ChangeSeverity::Info,
         summary: "The rust.description option has moved to build.description and rust.description is now deprecated.",
     },
+    ChangeInfo {
+        change_id: 138051,
+        severity: ChangeSeverity::Info,
+        summary: "There is now a new `gcc` config section that can be used to download GCC from CI using `gcc.download-ci-gcc = true`",
+    },
 ];
diff --git a/src/bootstrap/src/utils/helpers.rs b/src/bootstrap/src/utils/helpers.rs
index 7ad308cd067..89d93a29acb 100644
--- a/src/bootstrap/src/utils/helpers.rs
+++ b/src/bootstrap/src/utils/helpers.rs
@@ -286,7 +286,7 @@ pub fn output(cmd: &mut Command) -> String {
 /// to finish and then return its output. This allows the spawned process
 /// to do work without immediately blocking bootstrap.
 #[track_caller]
-pub fn start_process(cmd: &mut Command) -> impl FnOnce() -> String {
+pub fn start_process(cmd: &mut Command) -> impl FnOnce() -> String + use<> {
     let child = match cmd.stderr(Stdio::inherit()).stdout(Stdio::piped()).spawn() {
         Ok(child) => child,
         Err(e) => fail(&format!("failed to execute command: {cmd:?}\nERROR: {e}")),
diff --git a/src/bootstrap/src/utils/job.rs b/src/bootstrap/src/utils/job.rs
index a60e889fd57..4949518de79 100644
--- a/src/bootstrap/src/utils/job.rs
+++ b/src/bootstrap/src/utils/job.rs
@@ -7,7 +7,9 @@ pub unsafe fn setup(_build: &mut crate::Build) {}
 #[cfg(all(unix, not(target_os = "haiku")))]
 pub unsafe fn setup(build: &mut crate::Build) {
     if build.config.low_priority {
-        libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
+        unsafe {
+            libc::setpriority(libc::PRIO_PGRP as _, 0, 10);
+        }
     }
 }
 
@@ -59,38 +61,41 @@ mod for_windows {
     use crate::Build;
 
     pub unsafe fn setup(build: &mut Build) {
-        // Enable the Windows Error Reporting dialog which msys disables,
-        // so we can JIT debug rustc
-        let mode = SetErrorMode(THREAD_ERROR_MODE::default());
-        let mode = THREAD_ERROR_MODE(mode);
-        SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
+        // SAFETY: pretty much everything below is unsafe
+        unsafe {
+            // Enable the Windows Error Reporting dialog which msys disables,
+            // so we can JIT debug rustc
+            let mode = SetErrorMode(THREAD_ERROR_MODE::default());
+            let mode = THREAD_ERROR_MODE(mode);
+            SetErrorMode(mode & !SEM_NOGPFAULTERRORBOX);
 
-        // Create a new job object for us to use
-        let job = CreateJobObjectW(None, PCWSTR::null()).unwrap();
+            // Create a new job object for us to use
+            let job = CreateJobObjectW(None, PCWSTR::null()).unwrap();
 
-        // Indicate that when all handles to the job object are gone that all
-        // process in the object should be killed. Note that this includes our
-        // entire process tree by default because we've added ourselves and our
-        // children will reside in the job by default.
-        let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default();
-        info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
-        if build.config.low_priority {
-            info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
-            info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0;
-        }
-        let r = SetInformationJobObject(
-            job,
-            JobObjectExtendedLimitInformation,
-            &info as *const _ as *const c_void,
-            size_of_val(&info) as u32,
-        );
-        assert!(r.is_ok(), "{}", io::Error::last_os_error());
+            // Indicate that when all handles to the job object are gone that all
+            // process in the object should be killed. Note that this includes our
+            // entire process tree by default because we've added ourselves and our
+            // children will reside in the job by default.
+            let mut info = JOBOBJECT_EXTENDED_LIMIT_INFORMATION::default();
+            info.BasicLimitInformation.LimitFlags = JOB_OBJECT_LIMIT_KILL_ON_JOB_CLOSE;
+            if build.config.low_priority {
+                info.BasicLimitInformation.LimitFlags |= JOB_OBJECT_LIMIT_PRIORITY_CLASS;
+                info.BasicLimitInformation.PriorityClass = BELOW_NORMAL_PRIORITY_CLASS.0;
+            }
+            let r = SetInformationJobObject(
+                job,
+                JobObjectExtendedLimitInformation,
+                &info as *const _ as *const c_void,
+                size_of_val(&info) as u32,
+            );
+            assert!(r.is_ok(), "{}", io::Error::last_os_error());
 
-        // Assign our process to this job object.
-        let r = AssignProcessToJobObject(job, GetCurrentProcess());
-        if r.is_err() {
-            CloseHandle(job).ok();
-            return;
+            // Assign our process to this job object.
+            let r = AssignProcessToJobObject(job, GetCurrentProcess());
+            if r.is_err() {
+                CloseHandle(job).ok();
+                return;
+            }
         }
 
         // Note: we intentionally leak the job object handle. When our process exits
diff --git a/src/ci/citool/Cargo.lock b/src/ci/citool/Cargo.lock
index 46343a7b86e..c061ec6ebdc 100644
--- a/src/ci/citool/Cargo.lock
+++ b/src/ci/citool/Cargo.lock
@@ -107,6 +107,7 @@ dependencies = [
  "build_helper",
  "clap",
  "csv",
+ "glob-match",
  "insta",
  "serde",
  "serde_json",
@@ -309,6 +310,12 @@ dependencies = [
 ]
 
 [[package]]
+name = "glob-match"
+version = "0.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9985c9503b412198aa4197559e9a318524ebc4519c229bfa05a535828c950b9d"
+
+[[package]]
 name = "hashbrown"
 version = "0.15.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/src/ci/citool/Cargo.toml b/src/ci/citool/Cargo.toml
index c486f2977a1..dde09224afe 100644
--- a/src/ci/citool/Cargo.toml
+++ b/src/ci/citool/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 anyhow = "1"
 clap = { version = "4.5", features = ["derive"] }
 csv = "1"
+glob-match = "0.2"
 serde = { version = "1", features = ["derive"] }
 serde_yaml = "0.9"
 serde_json = "1"
diff --git a/src/ci/citool/src/jobs.rs b/src/ci/citool/src/jobs.rs
new file mode 100644
index 00000000000..45a188fb234
--- /dev/null
+++ b/src/ci/citool/src/jobs.rs
@@ -0,0 +1,244 @@
+#[cfg(test)]
+mod tests;
+
+use std::collections::BTreeMap;
+
+use serde_yaml::Value;
+
+use crate::GitHubContext;
+
+/// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file.
+#[derive(serde::Deserialize, Debug, Clone)]
+pub struct Job {
+    /// Name of the job, e.g. mingw-check
+    pub name: String,
+    /// GitHub runner on which the job should be executed
+    pub os: String,
+    pub env: BTreeMap<String, Value>,
+    /// Should the job be only executed on a specific channel?
+    #[serde(default)]
+    pub only_on_channel: Option<String>,
+    /// Do not cancel the whole workflow if this job fails.
+    #[serde(default)]
+    pub continue_on_error: Option<bool>,
+    /// Free additional disk space in the job, by removing unused packages.
+    #[serde(default)]
+    pub free_disk: Option<bool>,
+}
+
+impl Job {
+    /// By default, the Docker image of a job is based on its name.
+    /// However, it can be overridden by its IMAGE environment variable.
+    pub fn image(&self) -> String {
+        self.env
+            .get("IMAGE")
+            .map(|v| v.as_str().expect("IMAGE value should be a string").to_string())
+            .unwrap_or_else(|| self.name.clone())
+    }
+
+    fn is_linux(&self) -> bool {
+        self.os.contains("ubuntu")
+    }
+}
+
+#[derive(serde::Deserialize, Debug)]
+struct JobEnvironments {
+    #[serde(rename = "pr")]
+    pr_env: BTreeMap<String, Value>,
+    #[serde(rename = "try")]
+    try_env: BTreeMap<String, Value>,
+    #[serde(rename = "auto")]
+    auto_env: BTreeMap<String, Value>,
+}
+
+#[derive(serde::Deserialize, Debug)]
+pub struct JobDatabase {
+    #[serde(rename = "pr")]
+    pub pr_jobs: Vec<Job>,
+    #[serde(rename = "try")]
+    pub try_jobs: Vec<Job>,
+    #[serde(rename = "auto")]
+    pub auto_jobs: Vec<Job>,
+
+    /// Shared environments for the individual run types.
+    envs: JobEnvironments,
+}
+
+impl JobDatabase {
+    /// Find `auto` jobs that correspond to the passed `pattern`.
+    /// Patterns are matched using the glob syntax.
+    /// For example `dist-*` matches all jobs starting with `dist-`.
+    fn find_auto_jobs_by_pattern(&self, pattern: &str) -> Vec<Job> {
+        self.auto_jobs
+            .iter()
+            .filter(|j| glob_match::glob_match(pattern, &j.name))
+            .cloned()
+            .collect()
+    }
+}
+
+pub fn load_job_db(db: &str) -> anyhow::Result<JobDatabase> {
+    let mut db: Value = serde_yaml::from_str(&db)?;
+
+    // We need to expand merge keys (<<), because serde_yaml can't deal with them
+    // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges.
+    db.apply_merge()?;
+    db.apply_merge()?;
+
+    let db: JobDatabase = serde_yaml::from_value(db)?;
+    Ok(db)
+}
+
+/// Representation of a job outputted to a GitHub Actions workflow.
+#[derive(serde::Serialize, Debug)]
+struct GithubActionsJob {
+    /// The main identifier of the job, used by CI scripts to determine what should be executed.
+    name: String,
+    /// Helper label displayed in GitHub Actions interface, containing the job name and a run type
+    /// prefix (PR/try/auto).
+    full_name: String,
+    os: String,
+    env: BTreeMap<String, serde_json::Value>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    continue_on_error: Option<bool>,
+    #[serde(skip_serializing_if = "Option::is_none")]
+    free_disk: Option<bool>,
+}
+
+/// Skip CI jobs that are not supposed to be executed on the given `channel`.
+fn skip_jobs(jobs: Vec<Job>, channel: &str) -> Vec<Job> {
+    jobs.into_iter()
+        .filter(|job| {
+            job.only_on_channel.is_none() || job.only_on_channel.as_deref() == Some(channel)
+        })
+        .collect()
+}
+
+/// Type of workflow that is being executed on CI
+#[derive(Debug)]
+pub enum RunType {
+    /// Workflows that run after a push to a PR branch
+    PullRequest,
+    /// Try run started with @bors try
+    TryJob { job_patterns: Option<Vec<String>> },
+    /// Merge attempt workflow
+    AutoJob,
+}
+
+/// Maximum number of custom try jobs that can be requested in a single
+/// `@bors try` request.
+const MAX_TRY_JOBS_COUNT: usize = 20;
+
+fn calculate_jobs(
+    run_type: &RunType,
+    db: &JobDatabase,
+    channel: &str,
+) -> anyhow::Result<Vec<GithubActionsJob>> {
+    let (jobs, prefix, base_env) = match run_type {
+        RunType::PullRequest => (db.pr_jobs.clone(), "PR", &db.envs.pr_env),
+        RunType::TryJob { job_patterns } => {
+            let jobs = if let Some(patterns) = job_patterns {
+                let mut jobs: Vec<Job> = vec![];
+                let mut unknown_patterns = vec![];
+                for pattern in patterns {
+                    let matched_jobs = db.find_auto_jobs_by_pattern(pattern);
+                    if matched_jobs.is_empty() {
+                        unknown_patterns.push(pattern.clone());
+                    } else {
+                        for job in matched_jobs {
+                            if !jobs.iter().any(|j| j.name == job.name) {
+                                jobs.push(job);
+                            }
+                        }
+                    }
+                }
+                if !unknown_patterns.is_empty() {
+                    return Err(anyhow::anyhow!(
+                        "Patterns `{}` did not match any auto jobs",
+                        unknown_patterns.join(", ")
+                    ));
+                }
+                if jobs.len() > MAX_TRY_JOBS_COUNT {
+                    return Err(anyhow::anyhow!(
+                        "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs expanded from {} pattern(s)",
+                        jobs.len(),
+                        patterns.len()
+                    ));
+                }
+                jobs
+            } else {
+                db.try_jobs.clone()
+            };
+            (jobs, "try", &db.envs.try_env)
+        }
+        RunType::AutoJob => (db.auto_jobs.clone(), "auto", &db.envs.auto_env),
+    };
+    let jobs = skip_jobs(jobs, channel);
+    let jobs = jobs
+        .into_iter()
+        .map(|job| {
+            let mut env: BTreeMap<String, serde_json::Value> = crate::yaml_map_to_json(base_env);
+            env.extend(crate::yaml_map_to_json(&job.env));
+            let full_name = format!("{prefix} - {}", job.name);
+
+            GithubActionsJob {
+                name: job.name,
+                full_name,
+                os: job.os,
+                env,
+                continue_on_error: job.continue_on_error,
+                free_disk: job.free_disk,
+            }
+        })
+        .collect();
+
+    Ok(jobs)
+}
+
+pub fn calculate_job_matrix(
+    db: JobDatabase,
+    gh_ctx: GitHubContext,
+    channel: &str,
+) -> anyhow::Result<()> {
+    let run_type = gh_ctx.get_run_type().ok_or_else(|| {
+        anyhow::anyhow!("Cannot determine the type of workflow that is being executed")
+    })?;
+    eprintln!("Run type: {run_type:?}");
+
+    let jobs = calculate_jobs(&run_type, &db, channel)?;
+    if jobs.is_empty() {
+        return Err(anyhow::anyhow!("Computed job list is empty"));
+    }
+
+    let run_type = match run_type {
+        RunType::PullRequest => "pr",
+        RunType::TryJob { .. } => "try",
+        RunType::AutoJob => "auto",
+    };
+
+    eprintln!("Output");
+    eprintln!("jobs={jobs:?}");
+    eprintln!("run_type={run_type}");
+    println!("jobs={}", serde_json::to_string(&jobs)?);
+    println!("run_type={run_type}");
+
+    Ok(())
+}
+
+pub fn find_linux_job<'a>(jobs: &'a [Job], name: &str) -> anyhow::Result<&'a Job> {
+    let Some(job) = jobs.iter().find(|j| j.name == name) else {
+        let available_jobs: Vec<&Job> = jobs.iter().filter(|j| j.is_linux()).collect();
+        let mut available_jobs =
+            available_jobs.iter().map(|j| j.name.to_string()).collect::<Vec<_>>();
+        available_jobs.sort();
+        return Err(anyhow::anyhow!(
+            "Job {name} not found. The following jobs are available:\n{}",
+            available_jobs.join(", ")
+        ));
+    };
+    if !job.is_linux() {
+        return Err(anyhow::anyhow!("Only Linux jobs can be executed locally"));
+    }
+
+    Ok(job)
+}
diff --git a/src/ci/citool/src/jobs/tests.rs b/src/ci/citool/src/jobs/tests.rs
new file mode 100644
index 00000000000..a489656fa5d
--- /dev/null
+++ b/src/ci/citool/src/jobs/tests.rs
@@ -0,0 +1,64 @@
+use crate::jobs::{JobDatabase, load_job_db};
+
+#[test]
+fn lookup_job_pattern() {
+    let db = load_job_db(
+        r#"
+envs:
+  pr:
+  try:
+  auto:
+
+pr:
+try:
+auto:
+    - name: dist-a
+      os: ubuntu
+      env: {}
+    - name: dist-a-alt
+      os: ubuntu
+      env: {}
+    - name: dist-b
+      os: ubuntu
+      env: {}
+    - name: dist-b-alt
+      os: ubuntu
+      env: {}
+    - name: test-a
+      os: ubuntu
+      env: {}
+    - name: test-a-alt
+      os: ubuntu
+      env: {}
+    - name: test-i686
+      os: ubuntu
+      env: {}
+    - name: dist-i686
+      os: ubuntu
+      env: {}
+    - name: test-msvc-i686-1
+      os: ubuntu
+      env: {}
+    - name: test-msvc-i686-2
+      os: ubuntu
+      env: {}
+"#,
+    )
+    .unwrap();
+    check_pattern(&db, "dist-*", &["dist-a", "dist-a-alt", "dist-b", "dist-b-alt", "dist-i686"]);
+    check_pattern(&db, "*-alt", &["dist-a-alt", "dist-b-alt", "test-a-alt"]);
+    check_pattern(&db, "dist*-alt", &["dist-a-alt", "dist-b-alt"]);
+    check_pattern(
+        &db,
+        "*i686*",
+        &["test-i686", "dist-i686", "test-msvc-i686-1", "test-msvc-i686-2"],
+    );
+}
+
+#[track_caller]
+fn check_pattern(db: &JobDatabase, pattern: &str, expected: &[&str]) {
+    let jobs =
+        db.find_auto_jobs_by_pattern(pattern).into_iter().map(|j| j.name).collect::<Vec<_>>();
+
+    assert_eq!(jobs, expected);
+}
diff --git a/src/ci/citool/src/main.rs b/src/ci/citool/src/main.rs
index 52e7638d98b..cd690ebeb06 100644
--- a/src/ci/citool/src/main.rs
+++ b/src/ci/citool/src/main.rs
@@ -1,5 +1,6 @@
 mod cpu_usage;
 mod datadog;
+mod jobs;
 mod merge_report;
 mod metrics;
 mod utils;
@@ -10,10 +11,12 @@ use std::process::Command;
 
 use anyhow::Context;
 use clap::Parser;
+use jobs::JobDatabase;
 use serde_yaml::Value;
 
 use crate::cpu_usage::load_cpu_usage;
 use crate::datadog::upload_datadog_metric;
+use crate::jobs::RunType;
 use crate::merge_report::post_merge_report;
 use crate::metrics::postprocess_metrics;
 use crate::utils::load_env_var;
@@ -22,104 +25,6 @@ const CI_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/..");
 const DOCKER_DIRECTORY: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../docker");
 const JOBS_YML_PATH: &str = concat!(env!("CARGO_MANIFEST_DIR"), "/../github-actions/jobs.yml");
 
-/// Representation of a job loaded from the `src/ci/github-actions/jobs.yml` file.
-#[derive(serde::Deserialize, Debug, Clone)]
-struct Job {
-    /// Name of the job, e.g. mingw-check
-    name: String,
-    /// GitHub runner on which the job should be executed
-    os: String,
-    env: BTreeMap<String, Value>,
-    /// Should the job be only executed on a specific channel?
-    #[serde(default)]
-    only_on_channel: Option<String>,
-    /// Rest of attributes that will be passed through to GitHub actions
-    #[serde(flatten)]
-    extra_keys: BTreeMap<String, Value>,
-}
-
-impl Job {
-    fn is_linux(&self) -> bool {
-        self.os.contains("ubuntu")
-    }
-
-    /// By default, the Docker image of a job is based on its name.
-    /// However, it can be overridden by its IMAGE environment variable.
-    fn image(&self) -> String {
-        self.env
-            .get("IMAGE")
-            .map(|v| v.as_str().expect("IMAGE value should be a string").to_string())
-            .unwrap_or_else(|| self.name.clone())
-    }
-}
-
-#[derive(serde::Deserialize, Debug)]
-struct JobEnvironments {
-    #[serde(rename = "pr")]
-    pr_env: BTreeMap<String, Value>,
-    #[serde(rename = "try")]
-    try_env: BTreeMap<String, Value>,
-    #[serde(rename = "auto")]
-    auto_env: BTreeMap<String, Value>,
-}
-
-#[derive(serde::Deserialize, Debug)]
-struct JobDatabase {
-    #[serde(rename = "pr")]
-    pr_jobs: Vec<Job>,
-    #[serde(rename = "try")]
-    try_jobs: Vec<Job>,
-    #[serde(rename = "auto")]
-    auto_jobs: Vec<Job>,
-
-    /// Shared environments for the individual run types.
-    envs: JobEnvironments,
-}
-
-impl JobDatabase {
-    fn find_auto_job_by_name(&self, name: &str) -> Option<Job> {
-        self.auto_jobs.iter().find(|j| j.name == name).cloned()
-    }
-}
-
-fn load_job_db(path: &Path) -> anyhow::Result<JobDatabase> {
-    let db = utils::read_to_string(path)?;
-    let mut db: Value = serde_yaml::from_str(&db)?;
-
-    // We need to expand merge keys (<<), because serde_yaml can't deal with them
-    // `apply_merge` only applies the merge once, so do it a few times to unwrap nested merges.
-    db.apply_merge()?;
-    db.apply_merge()?;
-
-    let db: JobDatabase = serde_yaml::from_value(db)?;
-    Ok(db)
-}
-
-/// Representation of a job outputted to a GitHub Actions workflow.
-#[derive(serde::Serialize, Debug)]
-struct GithubActionsJob {
-    /// The main identifier of the job, used by CI scripts to determine what should be executed.
-    name: String,
-    /// Helper label displayed in GitHub Actions interface, containing the job name and a run type
-    /// prefix (PR/try/auto).
-    full_name: String,
-    os: String,
-    env: BTreeMap<String, serde_json::Value>,
-    #[serde(flatten)]
-    extra_keys: BTreeMap<String, serde_json::Value>,
-}
-
-/// Type of workflow that is being executed on CI
-#[derive(Debug)]
-enum RunType {
-    /// Workflows that run after a push to a PR branch
-    PullRequest,
-    /// Try run started with @bors try
-    TryJob { custom_jobs: Option<Vec<String>> },
-    /// Merge attempt workflow
-    AutoJob,
-}
-
 struct GitHubContext {
     event_name: String,
     branch_ref: String,
@@ -130,24 +35,31 @@ impl GitHubContext {
     fn get_run_type(&self) -> Option<RunType> {
         match (self.event_name.as_str(), self.branch_ref.as_str()) {
             ("pull_request", _) => Some(RunType::PullRequest),
-            ("push", "refs/heads/try-perf") => Some(RunType::TryJob { custom_jobs: None }),
+            ("push", "refs/heads/try-perf") => Some(RunType::TryJob { job_patterns: None }),
             ("push", "refs/heads/try" | "refs/heads/automation/bors/try") => {
-                let custom_jobs = self.get_custom_jobs();
-                let custom_jobs = if !custom_jobs.is_empty() { Some(custom_jobs) } else { None };
-                Some(RunType::TryJob { custom_jobs })
+                let patterns = self.get_try_job_patterns();
+                let patterns = if !patterns.is_empty() { Some(patterns) } else { None };
+                Some(RunType::TryJob { job_patterns: patterns })
             }
             ("push", "refs/heads/auto") => Some(RunType::AutoJob),
             _ => None,
         }
     }
 
-    /// Tries to parse names of specific CI jobs that should be executed in the form of
-    /// try-job: <job-name>
-    /// from the commit message of the passed GitHub context.
-    fn get_custom_jobs(&self) -> Vec<String> {
+    /// Tries to parse patterns of CI jobs that should be executed
+    /// from the commit message of the passed GitHub context
+    ///
+    /// They can be specified in the form of
+    /// try-job: <job-pattern>
+    /// or
+    /// try-job: `<job-pattern>`
+    /// (to avoid GitHub rendering the glob patterns as Markdown)
+    fn get_try_job_patterns(&self) -> Vec<String> {
         if let Some(ref msg) = self.commit_message {
             msg.lines()
                 .filter_map(|line| line.trim().strip_prefix("try-job: "))
+                // Strip backticks if present
+                .map(|l| l.trim_matches('`'))
                 .map(|l| l.trim().to_string())
                 .collect()
         } else {
@@ -164,15 +76,6 @@ fn load_github_ctx() -> anyhow::Result<GitHubContext> {
     Ok(GitHubContext { event_name, branch_ref: load_env_var("GITHUB_REF")?, commit_message })
 }
 
-/// Skip CI jobs that are not supposed to be executed on the given `channel`.
-fn skip_jobs(jobs: Vec<Job>, channel: &str) -> Vec<Job> {
-    jobs.into_iter()
-        .filter(|job| {
-            job.only_on_channel.is_none() || job.only_on_channel.as_deref() == Some(channel)
-        })
-        .collect()
-}
-
 fn yaml_map_to_json(map: &BTreeMap<String, Value>) -> BTreeMap<String, serde_json::Value> {
     map.into_iter()
         .map(|(key, value)| {
@@ -184,124 +87,13 @@ fn yaml_map_to_json(map: &BTreeMap<String, Value>) -> BTreeMap<String, serde_jso
         .collect()
 }
 
-/// Maximum number of custom try jobs that can be requested in a single
-/// `@bors try` request.
-const MAX_TRY_JOBS_COUNT: usize = 20;
-
-fn calculate_jobs(
-    run_type: &RunType,
-    db: &JobDatabase,
-    channel: &str,
-) -> anyhow::Result<Vec<GithubActionsJob>> {
-    let (jobs, prefix, base_env) = match run_type {
-        RunType::PullRequest => (db.pr_jobs.clone(), "PR", &db.envs.pr_env),
-        RunType::TryJob { custom_jobs } => {
-            let jobs = if let Some(custom_jobs) = custom_jobs {
-                if custom_jobs.len() > MAX_TRY_JOBS_COUNT {
-                    return Err(anyhow::anyhow!(
-                        "It is only possible to schedule up to {MAX_TRY_JOBS_COUNT} custom jobs, received {} custom jobs",
-                        custom_jobs.len()
-                    ));
-                }
-
-                let mut jobs = vec![];
-                let mut unknown_jobs = vec![];
-                for custom_job in custom_jobs {
-                    if let Some(job) = db.find_auto_job_by_name(custom_job) {
-                        jobs.push(job);
-                    } else {
-                        unknown_jobs.push(custom_job.clone());
-                    }
-                }
-                if !unknown_jobs.is_empty() {
-                    return Err(anyhow::anyhow!(
-                        "Custom job(s) `{}` not found in auto jobs",
-                        unknown_jobs.join(", ")
-                    ));
-                }
-                jobs
-            } else {
-                db.try_jobs.clone()
-            };
-            (jobs, "try", &db.envs.try_env)
-        }
-        RunType::AutoJob => (db.auto_jobs.clone(), "auto", &db.envs.auto_env),
-    };
-    let jobs = skip_jobs(jobs, channel);
-    let jobs = jobs
-        .into_iter()
-        .map(|job| {
-            let mut env: BTreeMap<String, serde_json::Value> = yaml_map_to_json(base_env);
-            env.extend(yaml_map_to_json(&job.env));
-            let full_name = format!("{prefix} - {}", job.name);
-
-            GithubActionsJob {
-                name: job.name,
-                full_name,
-                os: job.os,
-                env,
-                extra_keys: yaml_map_to_json(&job.extra_keys),
-            }
-        })
-        .collect();
-
-    Ok(jobs)
-}
-
-fn calculate_job_matrix(
-    db: JobDatabase,
-    gh_ctx: GitHubContext,
-    channel: &str,
-) -> anyhow::Result<()> {
-    let run_type = gh_ctx.get_run_type().ok_or_else(|| {
-        anyhow::anyhow!("Cannot determine the type of workflow that is being executed")
-    })?;
-    eprintln!("Run type: {run_type:?}");
-
-    let jobs = calculate_jobs(&run_type, &db, channel)?;
-    if jobs.is_empty() {
-        return Err(anyhow::anyhow!("Computed job list is empty"));
-    }
-
-    let run_type = match run_type {
-        RunType::PullRequest => "pr",
-        RunType::TryJob { .. } => "try",
-        RunType::AutoJob => "auto",
-    };
-
-    eprintln!("Output");
-    eprintln!("jobs={jobs:?}");
-    eprintln!("run_type={run_type}");
-    println!("jobs={}", serde_json::to_string(&jobs)?);
-    println!("run_type={run_type}");
-
-    Ok(())
-}
-
-fn find_linux_job<'a>(jobs: &'a [Job], name: &str) -> anyhow::Result<&'a Job> {
-    let Some(job) = jobs.iter().find(|j| j.name == name) else {
-        let available_jobs: Vec<&Job> = jobs.iter().filter(|j| j.is_linux()).collect();
-        let mut available_jobs =
-            available_jobs.iter().map(|j| j.name.to_string()).collect::<Vec<_>>();
-        available_jobs.sort();
-        return Err(anyhow::anyhow!(
-            "Job {name} not found. The following jobs are available:\n{}",
-            available_jobs.join(", ")
-        ));
-    };
-    if !job.is_linux() {
-        return Err(anyhow::anyhow!("Only Linux jobs can be executed locally"));
-    }
-
-    Ok(job)
-}
-
 fn run_workflow_locally(db: JobDatabase, job_type: JobType, name: String) -> anyhow::Result<()> {
     let jobs = match job_type {
         JobType::Auto => &db.auto_jobs,
         JobType::PR => &db.pr_jobs,
     };
-    let job = find_linux_job(jobs, &name).with_context(|| format!("Cannot find job {name}"))?;
+    let job =
+        jobs::find_linux_job(jobs, &name).with_context(|| format!("Cannot find job {name}"))?;
 
     let mut custom_env: BTreeMap<String, String> = BTreeMap::new();
     // Replicate src/ci/scripts/setup-environment.sh
@@ -385,7 +177,7 @@ enum Args {
 }
 
 #[derive(clap::ValueEnum, Clone)]
-enum JobType {
+pub enum JobType {
     /// Merge attempt ("auto") job
     Auto,
     /// Pull request job
@@ -395,7 +187,10 @@ enum JobType {
 fn main() -> anyhow::Result<()> {
     let args = Args::parse();
     let default_jobs_file = Path::new(JOBS_YML_PATH);
-    let load_db = |jobs_path| load_job_db(jobs_path).context("Cannot load jobs.yml");
+    let load_db = |jobs_path| {
+        let db = utils::read_to_string(jobs_path)?;
+        Ok::<_, anyhow::Error>(jobs::load_job_db(&db).context("Cannot load jobs.yml")?)
+    };
 
     match args {
         Args::CalculateJobMatrix { jobs_file } => {
@@ -407,7 +202,7 @@ fn main() -> anyhow::Result<()> {
                 .trim()
                 .to_string();
 
-            calculate_job_matrix(load_db(jobs_path)?, gh_ctx, &channel)
+            jobs::calculate_job_matrix(load_db(jobs_path)?, gh_ctx, &channel)
                 .context("Failed to calculate job matrix")?;
         }
         Args::RunJobLocally { job_type, name } => {
diff --git a/src/ci/citool/src/merge_report.rs b/src/ci/citool/src/merge_report.rs
index 5dd662280f0..17e42d49286 100644
--- a/src/ci/citool/src/merge_report.rs
+++ b/src/ci/citool/src/merge_report.rs
@@ -4,7 +4,7 @@ use std::collections::HashMap;
 use anyhow::Context;
 use build_helper::metrics::{JsonRoot, TestOutcome};
 
-use crate::JobDatabase;
+use crate::jobs::JobDatabase;
 use crate::metrics::get_test_suites;
 
 type Sha = String;
diff --git a/src/doc/book b/src/doc/book
-Subproject 4a01a9182496f807aaa5f72d93a25ce18bcbe10
+Subproject 81a976a237f84b8392c4ce1bd5fd076eb757a2e
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
-Subproject daa4b763cd848f986813b5cf8069e1649f7147a
+Subproject 1e27e5e6d5133ae4612f5cc195c15fc8d51b1c9
diff --git a/src/doc/nomicon b/src/doc/nomicon
-Subproject 8f5c7322b65d079aa5b242eb10d89a98e12471e
+Subproject b4448fa406a6dccde62d1e2f34f70fc51814cdc
diff --git a/src/doc/reference b/src/doc/reference
-Subproject 615b4cec60c269cfc105d511c93287620032d5b
+Subproject dda31c85f2ef2e5d2f0f2f643c9231690a30a62
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
-Subproject 66543bbc5b7dbd4e679092c07ae06ba6c73fd91
+Subproject 6f69823c28ae8d929d6c815181c73d3e99ef16d
diff --git a/src/doc/rustc-dev-guide/src/tests/ci.md b/src/doc/rustc-dev-guide/src/tests/ci.md
index ae6adb678af..0c0f750a45d 100644
--- a/src/doc/rustc-dev-guide/src/tests/ci.md
+++ b/src/doc/rustc-dev-guide/src/tests/ci.md
@@ -133,29 +133,37 @@ There are several use-cases for try builds:
   Again, a working compiler build is needed for this, which can be produced by
   the [dist-x86_64-linux] CI job.
 - Run a specific CI job (e.g. Windows tests) on a PR, to quickly test if it
-  passes the test suite executed by that job. You can select which CI jobs will
-  be executed in the try build by adding up to 10 lines containing `try-job:
-  <name of job>` to the PR description. All such specified jobs will be executed
-  in the try build once the `@bors try` command is used on the PR. If no try
-  jobs are specified in this way, the jobs defined in the `try` section of
-  [`jobs.yml`] will be executed by default.
+  passes the test suite executed by that job.
+
+You can select which CI jobs will
+be executed in the try build by adding lines containing `try-job:
+<job pattern>` to the PR description. All such specified jobs will be executed
+in the try build once the `@bors try` command is used on the PR. If no try
+jobs are specified in this way, the jobs defined in the `try` section of
+[`jobs.yml`] will be executed by default.
+
+Each pattern can either be an exact name of a job or a glob pattern that matches multiple jobs,
+for example `*msvc*` or `*-alt`. You can start at most 20 jobs in a single try build. When using
+glob patterns, you might want to wrap them in backticks (`` ` ``) to avoid GitHub rendering
+the pattern as Markdown.
 
 > **Using `try-job` PR description directives**
 >
-> 1. Identify which set of try-jobs (max 10) you would like to exercise. You can
+> 1. Identify which set of try-jobs you would like to exercise. You can
 >    find the name of the CI jobs in [`jobs.yml`].
 >
-> 2. Amend PR description to include (usually at the end of the PR description)
->    e.g.
+> 2. Amend PR description to include a set of patterns (usually at the end
+>    of the PR description), for example:
 >
 >    ```text
 >    This PR fixes #123456.
 >
 >    try-job: x86_64-msvc
 >    try-job: test-various
+>    try-job: `*-alt`
 >    ```
 >
->    Each `try-job` directive must be on its own line.
+>    Each `try-job` pattern must be on its own line.
 >
 > 3. Run the prescribed try jobs with `@bors try`. As aforementioned, this
 >    requires the user to either (1) have `try` permissions or (2) be delegated
diff --git a/src/doc/rustc/src/SUMMARY.md b/src/doc/rustc/src/SUMMARY.md
index b1d7e5421c1..542ee9fffce 100644
--- a/src/doc/rustc/src/SUMMARY.md
+++ b/src/doc/rustc/src/SUMMARY.md
@@ -72,6 +72,7 @@
     - [powerpc-unknown-linux-gnuspe](platform-support/powerpc-unknown-linux-gnuspe.md)
     - [powerpc-unknown-linux-muslspe](platform-support/powerpc-unknown-linux-muslspe.md)
     - [powerpc64-ibm-aix](platform-support/aix.md)
+    - [powerpc64le-unknown-linux-gnu](platform-support/powerpc64le-unknown-linux-gnu.md)
     - [powerpc64le-unknown-linux-musl](platform-support/powerpc64le-unknown-linux-musl.md)
     - [riscv32e\*-unknown-none-elf](platform-support/riscv32e-unknown-none-elf.md)
     - [riscv32i\*-unknown-none-elf](platform-support/riscv32-unknown-none-elf.md)
@@ -97,6 +98,7 @@
     - [wasm32-wasip1](platform-support/wasm32-wasip1.md)
     - [wasm32-wasip1-threads](platform-support/wasm32-wasip1-threads.md)
     - [wasm32-wasip2](platform-support/wasm32-wasip2.md)
+    - [wasm32-wali-linux-musl](platform-support/wasm32-wali-linux.md)
     - [wasm32-unknown-emscripten](platform-support/wasm32-unknown-emscripten.md)
     - [wasm32-unknown-unknown](platform-support/wasm32-unknown-unknown.md)
     - [wasm32v1-none](platform-support/wasm32v1-none.md)
diff --git a/src/doc/rustc/src/platform-support.md b/src/doc/rustc/src/platform-support.md
index f78ab151b9c..70880e0d61f 100644
--- a/src/doc/rustc/src/platform-support.md
+++ b/src/doc/rustc/src/platform-support.md
@@ -96,7 +96,7 @@ target | notes
 [`loongarch64-unknown-linux-musl`](platform-support/loongarch-linux.md) | LoongArch64 Linux, LP64D ABI (kernel 5.19, musl 1.2.5)
 `powerpc-unknown-linux-gnu` | PowerPC Linux (kernel 3.2, glibc 2.17)
 `powerpc64-unknown-linux-gnu` | PPC64 Linux (kernel 3.2, glibc 2.17)
-`powerpc64le-unknown-linux-gnu` | PPC64LE Linux (kernel 3.10, glibc 2.17)
+[`powerpc64le-unknown-linux-gnu`](platform-support/powerpc64le-unknown-linux-gnu.md) | PPC64LE Linux (kernel 3.10, glibc 2.17)
 [`powerpc64le-unknown-linux-musl`](platform-support/powerpc64le-unknown-linux-musl.md) | PPC64LE Linux (kernel 4.19, musl 1.2.3)
 [`riscv64gc-unknown-linux-gnu`](platform-support/riscv64gc-unknown-linux-gnu.md) | RISC-V Linux (kernel 4.20, glibc 2.29)
 [`riscv64gc-unknown-linux-musl`](platform-support/riscv64gc-unknown-linux-musl.md) | RISC-V Linux (kernel 4.20, musl 1.2.3)
@@ -404,6 +404,7 @@ target | std | host | notes
 [`thumbv8m.main-nuttx-eabi`](platform-support/nuttx.md) | ✓ |  | ARMv8M Mainline with NuttX
 [`thumbv8m.main-nuttx-eabihf`](platform-support/nuttx.md) | ✓ |  | ARMv8M Mainline with NuttX, hardfloat
 [`wasm64-unknown-unknown`](platform-support/wasm64-unknown-unknown.md) | ? |  | WebAssembly
+[`wasm32-wali-linux-musl`](platform-support/wasm32-wali-linux.md) | ? |  | WebAssembly with [WALI](https://github.com/arjunr2/WALI)
 [`x86_64-apple-tvos`](platform-support/apple-tvos.md) | ✓ |  | x86 64-bit tvOS
 [`x86_64-apple-watchos-sim`](platform-support/apple-watchos.md) | ✓ |  | x86 64-bit Apple WatchOS simulator
 [`x86_64-pc-cygwin`](platform-support/x86_64-pc-cygwin.md) | ? |  | 64-bit x86 Cygwin |
diff --git a/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-gnu.md b/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-gnu.md
new file mode 100644
index 00000000000..6cb34b2a777
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/powerpc64le-unknown-linux-gnu.md
@@ -0,0 +1,47 @@
+# `powerpc64le-unknown-linux-gnu`
+
+**Tier: 2**
+
+Target for 64-bit little endian PowerPC Linux programs
+
+## Target maintainers
+
+- David Tenty `daltenty@ibm.com`, https://github.com/daltenty
+- Chris Cambly, `ccambly@ca.ibm.com`, https://github.com/gilamn5tr
+
+## Requirements
+
+Building the target itself requires a 64-bit little endian PowerPC compiler that is supported by `cc-rs`.
+
+## Building the target
+
+The target can be built by enabling it for a `rustc` build.
+
+```toml
+[build]
+target = ["powerpc64le-unknown-linux-gnu"]
+```
+
+Make sure your C compiler is included in `$PATH`, then add it to the `config.toml`:
+
+```toml
+[target.powerpc64le-unknown-linux-gnu]
+cc = "powerpc64le-linux-gnu-gcc"
+cxx = "powerpc64le-linux-gnu-g++"
+ar = "powerpc64le-linux-gnu-ar"
+linker = "powerpc64le-linux-gnu-gcc"
+```
+
+## Building Rust programs
+
+This target is distributed through `rustup`, and requires no special
+configuration.
+
+## Cross-compilation
+
+This target can be cross-compiled from any host.
+
+## Testing
+
+This target can be tested as normal with `x.py` on a 64-bit little endian
+PowerPC host or via QEMU emulation.
diff --git a/src/doc/rustc/src/platform-support/wasm32-wali-linux.md b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md
new file mode 100644
index 00000000000..0c46ea2c01d
--- /dev/null
+++ b/src/doc/rustc/src/platform-support/wasm32-wali-linux.md
@@ -0,0 +1,98 @@
+# `wasm32-wali-linux-*`
+
+**Tier: 3**
+
+WebAssembly targets that use the [WebAssembly Linux Interface (WALI)](https://github.com/arjunr2/WALI) with 32-bit memory. The latest status of the WALI specification and support are documented within the repo.
+
+WALI offers seamless targetability of traditional Linux applications to Wasm by exposing Linux syscalls strategically into the sandbox. Numerous applications and build system work unmodified over WALI, including complex low-level system libraries -- a list of applications are included in the research paper linked in the main repo.
+
+From the wider Wasm ecosystem perspective, implementing WALI within engines allows layering of high-level security policies (e.g. WASI) above it, arming the latter's implementations with sandboxing and portability.
+
+## Target maintainers
+
+- Arjun Ramesh [@arjunr2](https://github.com/arjunr2)
+
+## Requirements
+
+### Compilation
+This target is cross-compiled and requires an installation of the [WALI compiler/sysroot](https://github.com/arjunr2/WALI). This produces standard `wasm32` binaries with the WALI interface methods as module imports that need to be implemented by a supported engine (see the  "Execution" section below).
+
+`wali` targets *minimally require* the following LLVM feature flags:
+
+* [Bulk memory] - `+bulk-memory`
+* Mutable imported globals - `+mutable-globals`
+* [Sign-extending operations] - `+sign-ext`
+* [Threading/Atomics] - `+atomics`
+
+[Bulk memory]: https://github.com/WebAssembly/spec/blob/main/proposals/bulk-memory-operations/Overview.md
+[Sign-extending operations]: https://github.com/WebAssembly/spec/blob/main/proposals/sign-extension-ops/Overview.md
+[Threading/Atomics]: https://github.com/WebAssembly/threads/blob/main/proposals/threads/Overview.md
+
+> **Note**: Users can expect that new enabled-by-default Wasm features for LLVM are transitively incorporatable into this target -- see [wasm32-unknown-unknown](wasm32-unknown-unknown.md) for detailed information on WebAssembly features.
+
+
+> **Note**: The WALI ABI is similar to default Clang wasm32 ABIs but *not identical*. The primary difference is 64-bit `long` types as opposed to 32-bit for wasm32. This is required to mantain minimum source code changes for 64-bit host platforms currently supported. This may change in the future as the spec evolves.
+
+### Execution
+Running generated WALI binaries also requires a supported compliant engine implementation -- a working implementation in the [WebAssembly Micro-Runtime (WAMR)](https://github.com/arjunr2/WALI) is included in the repo.
+
+> **Note**: WALI is still somewhat experimental and bugs may exist in the Rust support, WALI toolchain, or the LLVM compiler. The former can be filed in Rust repos while the latter two in the WALI repo.
+
+## Building the target
+
+You can build Rust with support for the target by adding it to the `target`
+list in `config.toml`, and pointing to the toolchain artifacts from the previous section ("Requirements->Compilation"). A sample `config.toml` for the `musl` environment will look like this, where `<WALI-root>` is the absolute path to the root directory of the [WALI repo](https://github.com/arjunr2/WALI):
+
+```toml
+[build]
+target = ["wasm32-wali-linux-musl"]
+
+[target.wasm32-wali-linux-musl]
+musl-root = "<WALI>/wali-musl/sysroot"
+llvm-config = "<WALI>/llvm-project/build/bin/llvm-config"
+cc = "<WALI>/llvm-project/build/bin/clang-18"
+cxx = "<WALI>/llvm-project/build/bin/clang-18"
+ar = "<WALI>/llvm-project/build/bin/llvm-ar"
+ranlib = "<WALI>/llvm-project/build/bin/llvm-ranlib"
+llvm-libunwind = "system"
+crt-static = true
+```
+
+> The `llvm-config` settings are only temporary, and the changes will eventually be upstreamed into LLVM
+
+## Building Rust programs
+
+Rust does not yet ship pre-compiled artifacts for this target. To compile for
+this target, you will either need to build Rust with the target enabled (see
+"Building the target" above), or build your own copy of `core` by using
+`build-std` or similar.
+
+Rust program builds can use this target normally. Currently, linking WALI programs may require pointing the `linker` to the llvm build in the [Cargo config](https://doc.rust-lang.org/cargo/reference/config.html) (until LLVM is upstreamed). A `config.toml` for Cargo will look like the following:
+
+```toml
+[target.wasm32-wali-linux-musl]
+linker = "<WALI>/llvm-project/build/bin/lld"
+```
+
+Note that the following `cfg` directives are set for `wasm32-wali-linux-*`:
+
+* `cfg(target_arch = "wasm32")`
+* `cfg(target_family = {"wasm", "unix"})`
+* `cfg(target_r = "wasm")`
+* `cfg(target_os = "linux")`
+* `cfg(target_env = *)`
+
+### Restrictions
+
+Hardware or platform-specific support, besides `syscall` is mostly unsupported in WALI for ISA portability (these tend to be uncommon).
+
+## Testing
+
+Currently testing is not supported for `wali` targets and the Rust project doesn't run any tests for this target.
+
+However, standard ISA-agnostic tests for Linux should be thereotically reusable for WALI targets and minor changes. Testing integration will be continually incorporated as support evolves.
+
+
+## Cross-compilation toolchains and C code
+
+Most fully featured C code is compilable with the WALI toolchain -- examples can be seen in the repo.
diff --git a/src/doc/unstable-book/src/compiler-flags/crate-attr.md b/src/doc/unstable-book/src/compiler-flags/crate-attr.md
new file mode 100644
index 00000000000..8c9c501a23e
--- /dev/null
+++ b/src/doc/unstable-book/src/compiler-flags/crate-attr.md
@@ -0,0 +1,16 @@
+# `crate-attr`
+
+The tracking issue for this feature is: [#138287](https://github.com/rust-lang/rust/issues/138287).
+
+------------------------
+
+The `-Z crate-attr` flag allows you to inject attributes into the crate root.
+For example, `-Z crate-attr=crate_name="test"` acts as if `#![crate_name="test"]` were present before the first source line of the crate root.
+
+To inject multiple attributes, pass `-Z crate-attr` multiple times.
+
+Formally, the expansion behaves as follows:
+1. The crate is parsed as if `-Z crate-attr` were not present.
+2. The attributes in `-Z crate-attr` are parsed.
+3. The attributes are injected at the top of the crate root.
+4. Macro expansion is performed.
diff --git a/src/doc/unstable-book/src/language-features/default-field-values.md b/src/doc/unstable-book/src/language-features/default-field-values.md
index 3143b2d7cae..6da6c4e6c57 100644
--- a/src/doc/unstable-book/src/language-features/default-field-values.md
+++ b/src/doc/unstable-book/src/language-features/default-field-values.md
@@ -67,7 +67,7 @@ have default field values.
 ## Lints
 
 When manually implementing the `Default` trait for a type that has default
-field values, if any of these are overriden in the impl the
+field values, if any of these are overridden in the impl the
 `default_overrides_default_fields` lint will trigger. This lint is in place
 to avoid surprising diverging behavior between `S { .. }` and
 `S::default()`, where using the same type in both ways could result in
diff --git a/src/etc/test-float-parse/Cargo.toml b/src/etc/test-float-parse/Cargo.toml
index 56cb5cddeea..bacb9e09f3f 100644
--- a/src/etc/test-float-parse/Cargo.toml
+++ b/src/etc/test-float-parse/Cargo.toml
@@ -7,8 +7,8 @@ publish = false
 [dependencies]
 indicatif = { version = "0.17.8", default-features = false }
 num = "0.4.3"
-rand = "0.8.5"
-rand_chacha = "0.3"
+rand = "0.9.0"
+rand_chacha = "0.9.0"
 rayon = "1"
 
 [lib]
diff --git a/src/etc/test-float-parse/src/gen/fuzz.rs b/src/etc/test-float-parse/src/gen/fuzz.rs
index 7fc999d1671..1d6c5562a14 100644
--- a/src/etc/test-float-parse/src/gen/fuzz.rs
+++ b/src/etc/test-float-parse/src/gen/fuzz.rs
@@ -6,7 +6,7 @@ use std::ops::Range;
 use std::sync::Mutex;
 
 use rand::Rng;
-use rand::distributions::{Distribution, Standard};
+use rand::distr::{Distribution, StandardUniform};
 use rand_chacha::ChaCha8Rng;
 use rand_chacha::rand_core::SeedableRng;
 
@@ -47,7 +47,7 @@ impl<F: Float> Fuzz<F> {
 
 impl<F: Float> Generator<F> for Fuzz<F>
 where
-    Standard: Distribution<<F as Float>::Int>,
+    StandardUniform: Distribution<<F as Float>::Int>,
 {
     const SHORT_NAME: &'static str = "fuzz";
 
@@ -74,13 +74,13 @@ where
 
 impl<F: Float> Iterator for Fuzz<F>
 where
-    Standard: Distribution<<F as Float>::Int>,
+    StandardUniform: Distribution<<F as Float>::Int>,
 {
     type Item = <Self as Generator<F>>::WriteCtx;
 
     fn next(&mut self) -> Option<Self::Item> {
         let _ = self.iter.next()?;
-        let i: F::Int = self.rng.gen();
+        let i: F::Int = self.rng.random();
 
         Some(F::from_bits(i))
     }
diff --git a/src/etc/test-float-parse/src/gen/many_digits.rs b/src/etc/test-float-parse/src/gen/many_digits.rs
index aab8d5d704b..741e11437fe 100644
--- a/src/etc/test-float-parse/src/gen/many_digits.rs
+++ b/src/etc/test-float-parse/src/gen/many_digits.rs
@@ -3,7 +3,7 @@ use std::fmt::Write;
 use std::marker::PhantomData;
 use std::ops::{Range, RangeInclusive};
 
-use rand::distributions::{Distribution, Uniform};
+use rand::distr::{Distribution, Uniform};
 use rand::{Rng, SeedableRng};
 use rand_chacha::ChaCha8Rng;
 
@@ -40,7 +40,7 @@ impl<F: Float> Generator<F> for RandDigits<F> {
 
     fn new() -> Self {
         let rng = ChaCha8Rng::from_seed(SEED);
-        let range = Uniform::from(0..10);
+        let range = Uniform::try_from(0..10).unwrap();
 
         Self { rng, iter: 0..ITERATIONS, uniform: range, marker: PhantomData }
     }
@@ -55,11 +55,11 @@ impl<F: Float> Iterator for RandDigits<F> {
 
     fn next(&mut self) -> Option<Self::Item> {
         let _ = self.iter.next()?;
-        let num_digits = self.rng.gen_range(POSSIBLE_NUM_DIGITS);
-        let has_decimal = self.rng.gen_bool(0.2);
-        let has_exp = self.rng.gen_bool(0.2);
+        let num_digits = self.rng.random_range(POSSIBLE_NUM_DIGITS);
+        let has_decimal = self.rng.random_bool(0.2);
+        let has_exp = self.rng.random_bool(0.2);
 
-        let dec_pos = if has_decimal { Some(self.rng.gen_range(0..num_digits)) } else { None };
+        let dec_pos = if has_decimal { Some(self.rng.random_range(0..num_digits)) } else { None };
 
         let mut s = String::with_capacity(num_digits);
 
@@ -75,7 +75,7 @@ impl<F: Float> Iterator for RandDigits<F> {
         }
 
         if has_exp {
-            let exp = self.rng.gen_range(EXP_RANGE);
+            let exp = self.rng.random_range(EXP_RANGE);
             write!(s, "e{exp}").unwrap();
         }
 
diff --git a/src/etc/test-float-parse/src/lib.rs b/src/etc/test-float-parse/src/lib.rs
index def66398d9f..e2f84b085c6 100644
--- a/src/etc/test-float-parse/src/lib.rs
+++ b/src/etc/test-float-parse/src/lib.rs
@@ -10,7 +10,7 @@ use std::sync::OnceLock;
 use std::sync::atomic::{AtomicU64, Ordering};
 use std::{fmt, time};
 
-use rand::distributions::{Distribution, Standard};
+use rand::distr::{Distribution, StandardUniform};
 use rayon::prelude::*;
 use time::{Duration, Instant};
 use traits::{Float, Generator, Int};
@@ -132,7 +132,7 @@ fn register_float<F: Float>(tests: &mut Vec<TestInfo>, cfg: &Config)
 where
     RangeInclusive<F::Int>: Iterator<Item = F::Int>,
     <F::Int as TryFrom<u128>>::Error: std::fmt::Debug,
-    Standard: Distribution<<F as traits::Float>::Int>,
+    StandardUniform: Distribution<<F as traits::Float>::Int>,
 {
     if F::BITS <= MAX_BITS_FOR_EXHAUUSTIVE {
         // Only run exhaustive tests if there is a chance of completion.
diff --git a/src/librustdoc/html/render/span_map.rs b/src/librustdoc/html/render/span_map.rs
index 4610e092cdf..3228f71df07 100644
--- a/src/librustdoc/html/render/span_map.rs
+++ b/src/librustdoc/html/render/span_map.rs
@@ -272,7 +272,7 @@ impl<'tcx> Visitor<'tcx> for SpanMapVisitor<'tcx> {
 
     fn visit_item(&mut self, item: &'tcx Item<'tcx>) {
         match item.kind {
-            ItemKind::Static(_, _, _)
+            ItemKind::Static(..)
             | ItemKind::Const(_, _, _)
             | ItemKind::Fn { .. }
             | ItemKind::Macro(_, _)
diff --git a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
index 4f024ecaf29..707312a97f3 100644
--- a/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
+++ b/src/tools/clippy/clippy_utils/src/ast_utils/mod.rs
@@ -364,6 +364,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 generics: lg,
                 contract: lc,
                 body: lb,
+                define_opaque: _,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
@@ -371,6 +372,7 @@ pub fn eq_item_kind(l: &ItemKind, r: &ItemKind) -> bool {
                 generics: rg,
                 contract: rc,
                 body: rb,
+                define_opaque: _,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
@@ -502,6 +504,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 generics: lg,
                 contract: lc,
                 body: lb,
+                define_opaque: _,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
@@ -509,6 +512,7 @@ pub fn eq_foreign_item_kind(l: &ForeignItemKind, r: &ForeignItemKind) -> bool {
                 generics: rg,
                 contract: rc,
                 body: rb,
+                define_opaque: _,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
@@ -567,6 +571,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
                 generics: lg,
                 contract: lc,
                 body: lb,
+                define_opaque: _,
             }),
             Fn(box ast::Fn {
                 defaultness: rd,
@@ -574,6 +579,7 @@ pub fn eq_assoc_item_kind(l: &AssocItemKind, r: &AssocItemKind) -> bool {
                 generics: rg,
                 contract: rc,
                 body: rb,
+                define_opaque: _,
             }),
         ) => {
             eq_defaultness(*ld, *rd)
diff --git a/src/tools/clippy/tests/ui/crashes/ice-10972-tait.rs b/src/tools/clippy/tests/ui/crashes/ice-10972-tait.rs
deleted file mode 100644
index 11ddbfc3a04..00000000000
--- a/src/tools/clippy/tests/ui/crashes/ice-10972-tait.rs
+++ /dev/null
@@ -1,10 +0,0 @@
-//@ check-pass
-// ICE: #10972
-// asked to assemble constituent types of unexpected type: Binder(Foo, [])
-#![feature(type_alias_impl_trait)]
-
-use std::fmt::Debug;
-type Foo = impl Debug;
-const FOO2: Foo = 22_u32;
-
-pub fn main() {}
diff --git a/src/tools/clippy/tests/ui/implied_bounds_in_impls.fixed b/src/tools/clippy/tests/ui/implied_bounds_in_impls.fixed
index bac7af59491..4fe3fa4eab5 100644
--- a/src/tools/clippy/tests/ui/implied_bounds_in_impls.fixed
+++ b/src/tools/clippy/tests/ui/implied_bounds_in_impls.fixed
@@ -192,6 +192,7 @@ impl Atpit for () {
 
 type Tait = impl DerefMut;
 //~^ implied_bounds_in_impls
+#[define_opaque(Tait)]
 fn define() -> Tait {
     &mut [] as &mut [()]
 }
diff --git a/src/tools/clippy/tests/ui/implied_bounds_in_impls.rs b/src/tools/clippy/tests/ui/implied_bounds_in_impls.rs
index 2014cd46ada..6cc824db110 100644
--- a/src/tools/clippy/tests/ui/implied_bounds_in_impls.rs
+++ b/src/tools/clippy/tests/ui/implied_bounds_in_impls.rs
@@ -192,6 +192,7 @@ impl Atpit for () {
 
 type Tait = impl Deref + DerefMut;
 //~^ implied_bounds_in_impls
+#[define_opaque(Tait)]
 fn define() -> Tait {
     &mut [] as &mut [()]
 }
diff --git a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
index aef5eb5b890..bd6339b7870 100644
--- a/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
+++ b/src/tools/clippy/tests/ui/missing_const_for_fn/cant_be_const.rs
@@ -207,6 +207,7 @@ mod msrv {
 mod with_ty_alias {
     type Foo = impl std::fmt::Debug;
 
+    #[define_opaque(Foo)]
     fn foo(_: Foo) {
         let _: Foo = 1;
     }
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs
index 8a85c566227..f317674bc1a 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs
+++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.rs
@@ -17,6 +17,7 @@ mod issue10041 {
     struct Bomb2;
 
     impl Bomb2 {
+        #[define_opaque(X)]
         pub fn new() -> X {
             //~^ ERROR: overflow evaluating the requirement
             0i32
diff --git a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr
index 77c1b64ebc8..8ecd0437e7d 100644
--- a/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr
+++ b/src/tools/clippy/tests/ui/new_ret_no_self_overflow.stderr
@@ -1,5 +1,5 @@
 error[E0275]: overflow evaluating the requirement `<i32 as std::ops::Add>::Output == issue10041::X`
-  --> tests/ui/new_ret_no_self_overflow.rs:20:25
+  --> tests/ui/new_ret_no_self_overflow.rs:21:25
    |
 LL |         pub fn new() -> X {
    |                         ^
diff --git a/src/tools/miri/src/alloc_addresses/mod.rs b/src/tools/miri/src/alloc_addresses/mod.rs
index ff3a25e94bd..5d257029a46 100644
--- a/src/tools/miri/src/alloc_addresses/mod.rs
+++ b/src/tools/miri/src/alloc_addresses/mod.rs
@@ -198,8 +198,8 @@ trait EvalContextExtPriv<'tcx>: crate::MiriInterpCxExt<'tcx> {
                 }
                 AllocKind::Dead => unreachable!(),
             };
-            // Ensure this pointer's provenance is exposed, so that it can be used by FFI code.
-            return interp_ok(base_ptr.expose_provenance().try_into().unwrap());
+            // We don't have to expose this pointer yet, we do that in `prepare_for_native_call`.
+            return interp_ok(base_ptr.addr().try_into().unwrap());
         }
         // We are not in native lib mode, so we control the addresses ourselves.
         if let Some((reuse_addr, clock)) = global_state.reuse.take_addr(
diff --git a/src/tools/miri/src/shims/native_lib.rs b/src/tools/miri/src/shims/native_lib.rs
index c6fcb0355eb..0258a76c3e7 100644
--- a/src/tools/miri/src/shims/native_lib.rs
+++ b/src/tools/miri/src/shims/native_lib.rs
@@ -266,7 +266,7 @@ fn imm_to_carg<'tcx>(v: &ImmTy<'tcx>, cx: &impl HasDataLayout) -> InterpResult<'
             CArg::USize(v.to_scalar().to_target_usize(cx)?.try_into().unwrap()),
         ty::RawPtr(..) => {
             let s = v.to_scalar().to_pointer(cx)?.addr();
-            // This relies on the `expose_provenance` in `addr_from_alloc_id`.
+            // This relies on the `expose_provenance` in `prepare_for_native_call`.
             CArg::RawPtr(std::ptr::with_exposed_provenance_mut(s.bytes_usize()))
         }
         _ => throw_unsup_format!("unsupported argument type for native call: {}", v.layout.ty),
diff --git a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
index 28c824fd31d..24badc52f25 100644
--- a/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
+++ b/src/tools/rust-analyzer/crates/hir-def/src/hir/format_args.rs
@@ -137,7 +137,7 @@ pub enum FormatAlignment {
 #[derive(Clone, Debug, PartialEq, Eq)]
 pub enum FormatCount {
     /// `{:5}` or `{:.5}`
-    Literal(usize),
+    Literal(u16),
     /// `{:.*}`, `{:.5$}`, or `{:a$}`, etc.
     Argument(FormatArgPosition),
 }
diff --git a/src/tools/tidy/src/deps.rs b/src/tools/tidy/src/deps.rs
index f0e0c317e7b..569d3c67b04 100644
--- a/src/tools/tidy/src/deps.rs
+++ b/src/tools/tidy/src/deps.rs
@@ -1,11 +1,12 @@
 //! Checks the licenses of third-party dependencies.
 
-use std::collections::HashSet;
+use std::collections::{HashMap, HashSet};
 use std::fs::{File, read_dir};
 use std::io::Write;
 use std::path::Path;
 
 use build_helper::ci::CiEnv;
+use cargo_metadata::semver::Version;
 use cargo_metadata::{Metadata, Package, PackageId};
 
 #[path = "../../../bootstrap/src/utils/proc_macro_deps.rs"]
@@ -445,6 +446,7 @@ const PERMITTED_RUSTC_DEPENDENCIES: &[&str] = &[
     "windows_x86_64_gnu",
     "windows_x86_64_gnullvm",
     "windows_x86_64_msvc",
+    "wit-bindgen-rt@0.33.0", // via wasi
     "writeable",
     "yoke",
     "yoke-derive",
@@ -802,7 +804,17 @@ fn check_permitted_dependencies(
 
     // Check that the PERMITTED_DEPENDENCIES does not have unused entries.
     for permitted in permitted_dependencies {
-        if !deps.iter().any(|dep_id| &pkg_from_id(metadata, dep_id).name == permitted) {
+        fn compare(pkg: &Package, permitted: &str) -> bool {
+            if let Some((name, version)) = permitted.split_once("@") {
+                let Ok(version) = Version::parse(version) else {
+                    return false;
+                };
+                pkg.name == name && pkg.version == version
+            } else {
+                pkg.name == permitted
+            }
+        }
+        if !deps.iter().any(|dep_id| compare(pkg_from_id(metadata, dep_id), permitted)) {
             tidy_error!(
                 bad,
                 "could not find allowed package `{permitted}`\n\
@@ -813,14 +825,30 @@ fn check_permitted_dependencies(
     }
 
     // Get in a convenient form.
-    let permitted_dependencies: HashSet<_> = permitted_dependencies.iter().cloned().collect();
+    let permitted_dependencies: HashMap<_, _> = permitted_dependencies
+        .iter()
+        .map(|s| {
+            if let Some((name, version)) = s.split_once('@') {
+                (name, Version::parse(version).ok())
+            } else {
+                (*s, None)
+            }
+        })
+        .collect();
 
     for dep in deps {
         let dep = pkg_from_id(metadata, dep);
         // If this path is in-tree, we don't require it to be explicitly permitted.
-        if dep.source.is_some() && !permitted_dependencies.contains(dep.name.as_str()) {
-            tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
-            has_permitted_dep_error = true;
+        if dep.source.is_some() {
+            let is_eq = if let Some(version) = permitted_dependencies.get(dep.name.as_str()) {
+                if let Some(version) = version { version == &dep.version } else { true }
+            } else {
+                false
+            };
+            if !is_eq {
+                tidy_error!(bad, "Dependency for {descr} not explicitly permitted: {}", dep.id);
+                has_permitted_dep_error = true;
+            }
         }
     }
 
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 253e13375c7..2b9ae195478 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -4058,7 +4058,6 @@ ui/type-alias-enum-variants/issue-63151-dead-code-lint-fields-in-patterns.rs
 ui/type-alias-impl-trait/issue-101750.rs
 ui/type-alias-impl-trait/issue-104817.rs
 ui/type-alias-impl-trait/issue-109054.rs
-ui/type-alias-impl-trait/issue-52843-closure-constrain.rs
 ui/type-alias-impl-trait/issue-52843.rs
 ui/type-alias-impl-trait/issue-53092-2.rs
 ui/type-alias-impl-trait/issue-53092.rs
diff --git a/tests/assembly/targets/targets-elf.rs b/tests/assembly/targets/targets-elf.rs
index dc564c60f80..8f2fef0e9c9 100644
--- a/tests/assembly/targets/targets-elf.rs
+++ b/tests/assembly/targets/targets-elf.rs
@@ -559,6 +559,9 @@
 //@ revisions: wasm32_wasip2
 //@ [wasm32_wasip2] compile-flags: --target wasm32-wasip2
 //@ [wasm32_wasip2] needs-llvm-components: webassembly
+//@ revisions: wasm32_wali_linux_musl
+//@ [wasm32_wali_linux_musl] compile-flags: --target wasm32-wali-linux-musl
+//@ [wasm32_wali_linux_musl] needs-llvm-components: webassembly
 //@ revisions: wasm64_unknown_unknown
 //@ [wasm64_unknown_unknown] compile-flags: --target wasm64-unknown-unknown
 //@ [wasm64_unknown_unknown] needs-llvm-components: webassembly
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs
index 3edc68e1347..9048c6a1f18 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-const-generics.rs
@@ -9,18 +9,16 @@
 
 extern crate core;
 
-mod defining_module {
-    pub type Type1 = impl Send;
+pub type Type1 = impl Send;
 
-    pub fn foo()
-    where
-        Type1: 'static,
-    {
-        pub struct Foo<T, const N: usize>([T; N]);
-        let _: Type1 = Foo([0; 32]);
-    }
+#[define_opaque(Type1)]
+pub fn foo()
+where
+    Type1: 'static,
+{
+    pub struct Foo<T, const N: usize>([T; N]);
+    let _: Type1 = Foo([0; 32]);
 }
-use defining_module::*;
 
 pub fn foo1(_: Type1) {}
 // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
@@ -29,6 +27,6 @@ pub fn foo2(_: Type1, _: Type1) {}
 pub fn foo3(_: Type1, _: Type1, _: Type1) {}
 // CHECK: define{{.*}}4foo3{{.*}}!type ![[TYPE3:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 
-// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EEE"}
-// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EES2_E"}
-// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo3FooIu3i32Lu5usize32EES2_S2_E"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EEE"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_E"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu{{[0-9]+}}NtNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo3FooIu3i32Lu5usize32EES2_S2_E"}
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs
index 09cfd2e10d6..36d2e8c9f25 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-lifetimes.rs
@@ -9,22 +9,18 @@
 
 extern crate core;
 
-mod defining_module {
+pub type Type1 = impl Send;
 
-    pub type Type1 = impl Send;
-
-    pub fn foo<'a>()
-    where
-        Type1: 'static,
-    {
-        pub struct Foo<'a>(&'a i32);
-        pub struct Bar<'a, 'b>(&'a i32, &'b Foo<'b>);
-        let _: Type1 = Bar;
-    }
+#[define_opaque(Type1)]
+pub fn foo<'a>()
+where
+    Type1: 'static,
+{
+    pub struct Foo<'a>(&'a i32);
+    pub struct Bar<'a, 'b>(&'a i32, &'b Foo<'b>);
+    let _: Type1 = Bar;
 }
 
-use defining_module::*;
-
 pub fn foo1(_: Type1) {}
 // CHECK: define{{.*}}4foo1{{.*}}!type ![[TYPE1:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 pub fn foo2(_: Type1, _: Type1) {}
diff --git a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
index ffbfe021ba3..a8ba8db1be3 100644
--- a/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
+++ b/tests/codegen/sanitizer/cfi/emit-type-metadata-id-itanium-cxx-abi-paths.rs
@@ -9,47 +9,41 @@
 
 extern crate core;
 
-mod defining_module {
-    pub type Type1 = impl Send;
-    pub type Type2 = impl Send;
-    pub type Type3 = impl Send;
-    pub type Type4 = impl Send;
+pub type Type1 = impl Send;
+pub type Type2 = impl Send;
+pub type Type3 = impl Send;
+pub type Type4 = impl Send;
 
-    pub fn foo()
-    where
-        Type1: 'static,
-        Type2: 'static,
-        Type4: 'static,
-    {
-        // Type in extern path
-        extern "C" {
-            fn bar();
-        }
-        let _: Type1 = bar;
-
-        // Type in closure path
-        || {
-            pub struct Foo;
-            let _: Type2 = Foo;
-        };
+#[define_opaque(Type1, Type2, Type4)]
+pub fn foo() {
+    // Type in extern path
+    extern "C" {
+        fn bar();
+    }
+    let _: Type1 = bar;
 
-        // Type in const path
-        const {
-            pub struct Foo;
-            fn bar() -> Type3 {
-                Foo
-            }
-        };
+    // Type in closure path
+    || {
+        pub struct Foo;
+        let _: Type2 = Foo;
+    };
 
-        // Type in impl path
-        struct Foo;
-        impl Foo {
-            fn bar(&self) {}
+    // Type in const path
+    const {
+        pub struct Foo;
+        #[define_opaque(Type3)]
+        fn bar() -> Type3 {
+            Foo
         }
-        let _: Type4 = <Foo>::bar;
+    };
+
+    // Type in impl path
+    struct Foo;
+    impl Foo {
+        fn bar(&self) {}
     }
+    let _: Type4 = <Foo>::bar;
 }
-use defining_module::*;
 
 // Force arguments to be passed by using a reference. Otherwise, they may end up PassMode::Ignore
 
@@ -78,15 +72,15 @@ pub fn foo11(_: &Type4, _: &Type4) {}
 pub fn foo12(_: &Type4, _: &Type4, _: &Type4) {}
 // CHECK: define{{.*}}5foo12{{.*}}!type ![[TYPE12:[0-9]+]] !type !{{[0-9]+}} !type !{{[0-9]+}} !type !{{[0-9]+}}
 
-// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
-// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
-// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
-// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
-// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
-// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
-// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
-// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
-// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
-// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
-// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
-// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvNtC{{[[:print:]]+}}_{{[[:print:]]+}}15defining_module3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}
+// CHECK: ![[TYPE1]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barEE"}
+// CHECK: ![[TYPE2]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_E"}
+// CHECK: ![[TYPE3]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNFNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo10{{[{}][{}]}}extern{{[}][}]}}3barES0_S0_E"}
+// CHECK: ![[TYPE4]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooEE"}
+// CHECK: ![[TYPE5]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_E"}
+// CHECK: ![[TYPE6]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNCNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo11{{[{}][{}]}}closure{{[}][}]}}3FooES0_S0_E"}
+// CHECK: ![[TYPE7]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooEE"}
+// CHECK: ![[TYPE8]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_E"}
+// CHECK: ![[TYPE9]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NtNkNvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo12{{[{}][{}]}}constant{{[}][}]}}3FooES0_S0_E"}
+// CHECK: ![[TYPE10]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barEE"}
+// CHECK: ![[TYPE11]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_E"}
+// CHECK: ![[TYPE12]] = !{i64 0, !"_ZTSFvu3refIu{{[0-9]+}}NvNINvC{{[[:print:]]+}}_{{[[:print:]]+}}3foo8{{[{}][{}]}}impl{{[}][}]}}3barES0_S0_E"}
diff --git a/tests/crashes/120016.rs b/tests/crashes/120016.rs
index 09175689256..faba1af91b4 100644
--- a/tests/crashes/120016.rs
+++ b/tests/crashes/120016.rs
@@ -6,6 +6,7 @@
 struct Bug {
     V1: [(); {
         type F = impl std::future::Future<Output = impl Sized>;
+        #[define_opaque(F)]
         fn concrete_use() -> F {
             //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
             async {}
diff --git a/tests/crashes/122904-2.rs b/tests/crashes/122904-2.rs
index 85ed91c2fa4..db66b8625db 100644
--- a/tests/crashes/122904-2.rs
+++ b/tests/crashes/122904-2.rs
@@ -6,10 +6,12 @@ type Alias<'a> = impl T;
 struct S;
 impl<'a> T for &'a S {}
 
+#[define_opaque(Alias)]
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     with_positive(|&n| ());
 }
 
+#[define_opaque(Alias)]
 fn main(Alias<'_>) {
     with_positive(|&a| ());
 }
diff --git a/tests/crashes/122904.rs b/tests/crashes/122904.rs
index 8b8bb35d56c..2068cd9d239 100644
--- a/tests/crashes/122904.rs
+++ b/tests/crashes/122904.rs
@@ -6,6 +6,7 @@ type Alias<'a> = impl T;
 struct S;
 impl<'a> T for &'a S {}
 
+#[define_opaque(Alias)]
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     with_positive(|&n| ());
 }
diff --git a/tests/crashes/125185.rs b/tests/crashes/125185.rs
index 8693d6c7662..e77666ca73d 100644
--- a/tests/crashes/125185.rs
+++ b/tests/crashes/125185.rs
@@ -1,16 +1,26 @@
 //@ known-bug: rust-lang/rust#125185
 //@ compile-flags: -Zvalidate-mir
 
+#![feature(type_alias_impl_trait)]
+
 type Foo = impl Send;
 
 struct A;
 
-const VALUE: Foo = value();
+#[define_opaque(Foo)]
+const fn foo() -> Foo {
+    value()
+}
+
+const VALUE: Foo = foo();
 
-fn test(foo: Foo<'a>, f: impl for<'b> FnMut()) {
+#[define_opaque(Foo)]
+fn test(foo: Foo, f: impl for<'b> FnMut()) {
     match VALUE {
         0 | 0 => {}
 
         _ => (),
     }
 }
+
+fn main() {}
diff --git a/tests/crashes/126680.rs b/tests/crashes/126680.rs
index b1566d5e6be..dcb6ccad6b4 100644
--- a/tests/crashes/126680.rs
+++ b/tests/crashes/126680.rs
@@ -8,14 +8,18 @@ use std::path::Path;
 struct A {
     pub func: fn(check: Bar, b: Option<&Path>),
 }
-const MY_A: A = A {
-    func: |check, b| {
-        if check {
-            ()
-        } else if let Some(_) = b.and_then(|p| p.parent()) {
-            ()
-        }
-    },
-};
+
+#[define_opaque(Bar)]
+fn foo() -> A {
+    A {
+        func: |check, b| {
+            if check {
+                ()
+            } else if let Some(_) = b.and_then(|p| p.parent()) {
+                ()
+            }
+        },
+    }
+}
 
 fn main() {}
diff --git a/tests/crashes/131298.rs b/tests/crashes/131298.rs
deleted file mode 100644
index 833f1b04ffa..00000000000
--- a/tests/crashes/131298.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-//@ known-bug: #131298
-
-fn dyn_hoops<T>() -> *const dyn Iterator<Item = impl Captures> {
-    loop {}
-}
-
-mod typeck {
-    type Opaque = impl Sized;
-    fn define() -> Opaque {
-        let _: Opaque = super::dyn_hoops::<u8>();
-    }
-}
diff --git a/tests/crashes/131886.rs b/tests/crashes/131886.rs
index 2c692dfb777..16cb815f1c2 100644
--- a/tests/crashes/131886.rs
+++ b/tests/crashes/131886.rs
@@ -1,5 +1,5 @@
 //@ known-bug: #131886
-//@ compile-flags: -Zvalidate-mir --crate-type=lib
+//@ compile-flags: -Zvalidate-mir
 #![feature(type_alias_impl_trait)]
 
 type Tait = impl Sized;
@@ -7,6 +7,9 @@ type Tait = impl Sized;
 trait Foo<'a>: Bar<'a, 'a, Tait> {}
 trait Bar<'a, 'b, T> {}
 
+#[define_opaque(Tait)]
 fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
     let _ = x as &dyn Bar<'_, '_, ()>;
 }
+
+fn main() {}
diff --git a/tests/crashes/135528.rs b/tests/crashes/135528.rs
index a1418f40be6..171550e209e 100644
--- a/tests/crashes/135528.rs
+++ b/tests/crashes/135528.rs
@@ -7,10 +7,12 @@ fn set(x: &isize) -> isize {
     *x
 }
 
+#[define_opaque(Tait)]
 fn d(x: Tait) {
     set(x);
 }
 
+#[define_opaque(Tait)]
 fn other_define() -> Tait {
     ()
 }
diff --git a/tests/crashes/137049.rs b/tests/crashes/137049.rs
index a7132e4fa17..3dbbf280733 100644
--- a/tests/crashes/137049.rs
+++ b/tests/crashes/137049.rs
@@ -22,6 +22,7 @@ impl<T: Project1<Assoc1 = ()>> Project2 for PhantomData<T> {
 
 type Alias<T> = impl Project2;
 
+#[define_opaque(Alias)]
 fn constrain<T>() -> Alias<T> {
     PhantomData::<T>
 }
diff --git a/tests/crashes/137865.rs b/tests/crashes/137865.rs
deleted file mode 100644
index 7ecd8c734d3..00000000000
--- a/tests/crashes/137865.rs
+++ /dev/null
@@ -1,5 +0,0 @@
-//@ known-bug: #137865
-trait Foo {
-    type Assoc<const N: Self>;
-    fn foo() -> Self::Assoc<3>;
-}
diff --git a/tests/crashes/138048.rs b/tests/crashes/138048.rs
deleted file mode 100644
index fd59f46c752..00000000000
--- a/tests/crashes/138048.rs
+++ /dev/null
@@ -1,8 +0,0 @@
-//@ known-bug: #138048
-struct Foo;
-
-impl<'b> Foo {
-    fn bar<const V: u8>() {
-        let V;
-    }
-}
diff --git a/tests/debuginfo/pretty-huge-vec.rs b/tests/debuginfo/pretty-huge-vec.rs
index 093fbc5b12d..6938158e365 100644
--- a/tests/debuginfo/pretty-huge-vec.rs
+++ b/tests/debuginfo/pretty-huge-vec.rs
@@ -1,5 +1,6 @@
 //@ ignore-windows-gnu: #128981
 //@ ignore-android: FIXME(#10381)
+//@ ignore-aix: FIXME(#137965)
 //@ compile-flags:-g
 
 // === GDB TESTS ===================================================================================
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff
index a1be927e1c0..45fc7365d8d 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-abort.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-abort.diff
@@ -29,6 +29,16 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
+                      let mut _22: std::option::Option<u16>;
+                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
+                          let mut _23: isize;
+                          let _24: u16;
+                          let mut _25: usize;
+                          scope 7 {
+                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
+                              }
+                          }
+                      }
                   }
               }
           }
@@ -65,9 +75,12 @@
   
       bb3: {
           StorageLive(_6);
-          _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
-          _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
+          StorageLive(_24);
+          StorageLive(_22);
+          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
+          StorageLive(_23);
+          _23 = discriminant(_22);
+          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
       }
   
       bb4: {
@@ -135,7 +148,33 @@
       }
   
       bb9: {
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageDead(_24);
+          _7 = discriminant(_6);
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+      }
+  
+      bb10: {
           unreachable;
       }
+  
+      bb11: {
+          _6 = const Option::<usize>::None;
+          goto -> bb9;
+      }
+  
+      bb12: {
+          _24 = move ((_22 as Some).0: u16);
+          StorageLive(_25);
+          _25 = copy _24 as usize (IntToInt);
+          _6 = Option::<usize>::Some(move _25);
+          StorageDead(_25);
+          goto -> bb9;
+      }
+  }
+  
+  ALLOC0 (size: 8, align: 4) {
+      00 00 00 00 __ __ __ __                         │ ....░░░░
   }
   
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff
index 87ab71feb2f..578d2c2194b 100644
--- a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.panic-unwind.diff
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.32bit.panic-unwind.diff
@@ -29,6 +29,16 @@
                   debug precision => _8;
                   let _8: usize;
                   scope 5 (inlined Formatter::<'_>::precision) {
+                      let mut _22: std::option::Option<u16>;
+                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
+                          let mut _23: isize;
+                          let _24: u16;
+                          let mut _25: usize;
+                          scope 7 {
+                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
+                              }
+                          }
+                      }
                   }
               }
           }
@@ -65,9 +75,12 @@
   
       bb3: {
           StorageLive(_6);
-          _6 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<usize>);
-          _7 = discriminant(_6);
-          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb9];
+          StorageLive(_24);
+          StorageLive(_22);
+          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
+          StorageLive(_23);
+          _23 = discriminant(_22);
+          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
       }
   
       bb4: {
@@ -135,7 +148,33 @@
       }
   
       bb9: {
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageDead(_24);
+          _7 = discriminant(_6);
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+      }
+  
+      bb10: {
           unreachable;
       }
+  
+      bb11: {
+          _6 = const Option::<usize>::None;
+          goto -> bb9;
+      }
+  
+      bb12: {
+          _24 = move ((_22 as Some).0: u16);
+          StorageLive(_25);
+          _25 = copy _24 as usize (IntToInt);
+          _6 = Option::<usize>::Some(move _25);
+          StorageDead(_25);
+          goto -> bb9;
+      }
+  }
+  
+  ALLOC0 (size: 8, align: 4) {
+      00 00 00 00 __ __ __ __                         │ ....░░░░
   }
   
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff
new file mode 100644
index 00000000000..5f0f7d6cc74
--- /dev/null
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-abort.diff
@@ -0,0 +1,180 @@
+- // MIR for `float_to_exponential_common` before GVN
++ // MIR for `float_to_exponential_common` after GVN
+  
+  fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
+      debug fmt => _1;
+      debug num => _2;
+      debug upper => _3;
+      let mut _0: std::result::Result<(), std::fmt::Error>;
+      let _4: bool;
+      let mut _6: std::option::Option<usize>;
+      let mut _7: isize;
+      let mut _9: &mut std::fmt::Formatter<'_>;
+      let mut _10: &T;
+      let mut _11: core::num::flt2dec::Sign;
+      let mut _12: u32;
+      let mut _13: u32;
+      let mut _14: usize;
+      let mut _15: bool;
+      let mut _16: &mut std::fmt::Formatter<'_>;
+      let mut _17: &T;
+      let mut _18: core::num::flt2dec::Sign;
+      let mut _19: bool;
+      scope 1 {
+          debug force_sign => _4;
+          let _5: core::num::flt2dec::Sign;
+          scope 2 {
+              debug sign => _5;
+              scope 3 {
+                  debug precision => _8;
+                  let _8: usize;
+                  scope 5 (inlined Formatter::<'_>::precision) {
+                      let mut _22: std::option::Option<u16>;
+                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
+                          let mut _23: isize;
+                          let _24: u16;
+                          let mut _25: usize;
+                          scope 7 {
+                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 4 (inlined Formatter::<'_>::sign_plus) {
+          let mut _20: u32;
+          let mut _21: u32;
+      }
+  
+      bb0: {
+          StorageLive(_4);
+          StorageLive(_20);
+          StorageLive(_21);
+          _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _20 = BitAnd(move _21, const 1_u32);
+          StorageDead(_21);
+          _4 = Ne(move _20, const 0_u32);
+          StorageDead(_20);
+          StorageLive(_5);
+          switchInt(copy _4) -> [0: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+-         _5 = MinusPlus;
++         _5 = const MinusPlus;
+          goto -> bb3;
+      }
+  
+      bb2: {
+-         _5 = core::num::flt2dec::Sign::Minus;
++         _5 = const core::num::flt2dec::Sign::Minus;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageLive(_6);
+          StorageLive(_24);
+          StorageLive(_22);
+          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
+          StorageLive(_23);
+          _23 = discriminant(_22);
+          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+      }
+  
+      bb4: {
+-         StorageLive(_8);
++         nop;
+          _8 = copy ((_6 as Some).0: usize);
+          StorageLive(_9);
+          _9 = copy _1;
+          StorageLive(_10);
+          _10 = copy _2;
+          StorageLive(_11);
+          _11 = copy _5;
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+          _14 = copy _8;
+-         _13 = move _14 as u32 (IntToInt);
++         _13 = copy _8 as u32 (IntToInt);
+          StorageDead(_14);
+          _12 = Add(move _13, const 1_u32);
+          StorageDead(_13);
+          StorageLive(_15);
+          _15 = copy _3;
+-         _0 = float_to_exponential_common_exact::<T>(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind unreachable];
++         _0 = float_to_exponential_common_exact::<T>(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind unreachable];
+      }
+  
+      bb5: {
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageDead(_9);
+-         StorageDead(_8);
++         nop;
+          goto -> bb8;
+      }
+  
+      bb6: {
+          StorageLive(_16);
+          _16 = copy _1;
+          StorageLive(_17);
+          _17 = copy _2;
+          StorageLive(_18);
+          _18 = copy _5;
+          StorageLive(_19);
+          _19 = copy _3;
+-         _0 = float_to_exponential_common_shortest::<T>(move _16, move _17, move _18, move _19) -> [return: bb7, unwind unreachable];
++         _0 = float_to_exponential_common_shortest::<T>(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind unreachable];
+      }
+  
+      bb7: {
+          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageDead(_16);
+          goto -> bb8;
+      }
+  
+      bb8: {
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageDead(_6);
+          return;
+      }
+  
+      bb9: {
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageDead(_24);
+          _7 = discriminant(_6);
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+      }
+  
+      bb10: {
+          unreachable;
+      }
+  
+      bb11: {
+          _6 = const Option::<usize>::None;
+          goto -> bb9;
+      }
+  
+      bb12: {
+          _24 = move ((_22 as Some).0: u16);
+          StorageLive(_25);
+          _25 = copy _24 as usize (IntToInt);
+          _6 = Option::<usize>::Some(move _25);
+          StorageDead(_25);
+          goto -> bb9;
+      }
+  }
+  
+  ALLOC0 (size: 16, align: 8) {
+      00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
+  }
+  
diff --git a/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff
new file mode 100644
index 00000000000..10cc46a8b82
--- /dev/null
+++ b/tests/mir-opt/funky_arms.float_to_exponential_common.GVN.64bit.panic-unwind.diff
@@ -0,0 +1,180 @@
+- // MIR for `float_to_exponential_common` before GVN
++ // MIR for `float_to_exponential_common` after GVN
+  
+  fn float_to_exponential_common(_1: &mut Formatter<'_>, _2: &T, _3: bool) -> Result<(), std::fmt::Error> {
+      debug fmt => _1;
+      debug num => _2;
+      debug upper => _3;
+      let mut _0: std::result::Result<(), std::fmt::Error>;
+      let _4: bool;
+      let mut _6: std::option::Option<usize>;
+      let mut _7: isize;
+      let mut _9: &mut std::fmt::Formatter<'_>;
+      let mut _10: &T;
+      let mut _11: core::num::flt2dec::Sign;
+      let mut _12: u32;
+      let mut _13: u32;
+      let mut _14: usize;
+      let mut _15: bool;
+      let mut _16: &mut std::fmt::Formatter<'_>;
+      let mut _17: &T;
+      let mut _18: core::num::flt2dec::Sign;
+      let mut _19: bool;
+      scope 1 {
+          debug force_sign => _4;
+          let _5: core::num::flt2dec::Sign;
+          scope 2 {
+              debug sign => _5;
+              scope 3 {
+                  debug precision => _8;
+                  let _8: usize;
+                  scope 5 (inlined Formatter::<'_>::precision) {
+                      let mut _22: std::option::Option<u16>;
+                      scope 6 (inlined Option::<u16>::map::<usize, {closure@Formatter<'_>::precision::{closure#0}}>) {
+                          let mut _23: isize;
+                          let _24: u16;
+                          let mut _25: usize;
+                          scope 7 {
+                              scope 8 (inlined Formatter::<'_>::precision::{closure#0}) {
+                              }
+                          }
+                      }
+                  }
+              }
+          }
+      }
+      scope 4 (inlined Formatter::<'_>::sign_plus) {
+          let mut _20: u32;
+          let mut _21: u32;
+      }
+  
+      bb0: {
+          StorageLive(_4);
+          StorageLive(_20);
+          StorageLive(_21);
+          _21 = copy (((*_1).0: std::fmt::FormattingOptions).0: u32);
+          _20 = BitAnd(move _21, const 1_u32);
+          StorageDead(_21);
+          _4 = Ne(move _20, const 0_u32);
+          StorageDead(_20);
+          StorageLive(_5);
+          switchInt(copy _4) -> [0: bb2, otherwise: bb1];
+      }
+  
+      bb1: {
+-         _5 = MinusPlus;
++         _5 = const MinusPlus;
+          goto -> bb3;
+      }
+  
+      bb2: {
+-         _5 = core::num::flt2dec::Sign::Minus;
++         _5 = const core::num::flt2dec::Sign::Minus;
+          goto -> bb3;
+      }
+  
+      bb3: {
+          StorageLive(_6);
+          StorageLive(_24);
+          StorageLive(_22);
+          _22 = copy (((*_1).0: std::fmt::FormattingOptions).4: std::option::Option<u16>);
+          StorageLive(_23);
+          _23 = discriminant(_22);
+          switchInt(move _23) -> [0: bb11, 1: bb12, otherwise: bb10];
+      }
+  
+      bb4: {
+-         StorageLive(_8);
++         nop;
+          _8 = copy ((_6 as Some).0: usize);
+          StorageLive(_9);
+          _9 = copy _1;
+          StorageLive(_10);
+          _10 = copy _2;
+          StorageLive(_11);
+          _11 = copy _5;
+          StorageLive(_12);
+          StorageLive(_13);
+          StorageLive(_14);
+          _14 = copy _8;
+-         _13 = move _14 as u32 (IntToInt);
++         _13 = copy _8 as u32 (IntToInt);
+          StorageDead(_14);
+          _12 = Add(move _13, const 1_u32);
+          StorageDead(_13);
+          StorageLive(_15);
+          _15 = copy _3;
+-         _0 = float_to_exponential_common_exact::<T>(move _9, move _10, move _11, move _12, move _15) -> [return: bb5, unwind continue];
++         _0 = float_to_exponential_common_exact::<T>(copy _1, copy _2, move _11, move _12, copy _3) -> [return: bb5, unwind continue];
+      }
+  
+      bb5: {
+          StorageDead(_15);
+          StorageDead(_12);
+          StorageDead(_11);
+          StorageDead(_10);
+          StorageDead(_9);
+-         StorageDead(_8);
++         nop;
+          goto -> bb8;
+      }
+  
+      bb6: {
+          StorageLive(_16);
+          _16 = copy _1;
+          StorageLive(_17);
+          _17 = copy _2;
+          StorageLive(_18);
+          _18 = copy _5;
+          StorageLive(_19);
+          _19 = copy _3;
+-         _0 = float_to_exponential_common_shortest::<T>(move _16, move _17, move _18, move _19) -> [return: bb7, unwind continue];
++         _0 = float_to_exponential_common_shortest::<T>(copy _1, copy _2, move _18, copy _3) -> [return: bb7, unwind continue];
+      }
+  
+      bb7: {
+          StorageDead(_19);
+          StorageDead(_18);
+          StorageDead(_17);
+          StorageDead(_16);
+          goto -> bb8;
+      }
+  
+      bb8: {
+          StorageDead(_5);
+          StorageDead(_4);
+          StorageDead(_6);
+          return;
+      }
+  
+      bb9: {
+          StorageDead(_23);
+          StorageDead(_22);
+          StorageDead(_24);
+          _7 = discriminant(_6);
+          switchInt(move _7) -> [1: bb4, 0: bb6, otherwise: bb10];
+      }
+  
+      bb10: {
+          unreachable;
+      }
+  
+      bb11: {
+          _6 = const Option::<usize>::None;
+          goto -> bb9;
+      }
+  
+      bb12: {
+          _24 = move ((_22 as Some).0: u16);
+          StorageLive(_25);
+          _25 = copy _24 as usize (IntToInt);
+          _6 = Option::<usize>::Some(move _25);
+          StorageDead(_25);
+          goto -> bb9;
+      }
+  }
+  
+  ALLOC0 (size: 16, align: 8) {
+      00 00 00 00 00 00 00 00 __ __ __ __ __ __ __ __ │ ........░░░░░░░░
+  }
+  
diff --git a/tests/mir-opt/funky_arms.rs b/tests/mir-opt/funky_arms.rs
index fc3691049eb..403a22ebed3 100644
--- a/tests/mir-opt/funky_arms.rs
+++ b/tests/mir-opt/funky_arms.rs
@@ -1,5 +1,6 @@
 // skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 #![feature(flt2dec)]
 
diff --git a/tests/pretty/hir-pretty-attr.pp b/tests/pretty/hir-pretty-attr.pp
index 586810b0046..d8cc8c424ca 100644
--- a/tests/pretty/hir-pretty-attr.pp
+++ b/tests/pretty/hir-pretty-attr.pp
@@ -6,6 +6,6 @@ extern crate std;
 //@ pretty-mode:hir
 //@ pp-exact:hir-pretty-attr.pp
 
-#[attr="Repr([ReprC, ReprPacked(Align(4 bytes)), ReprTransparent])")]
+#[attr = Repr([ReprC, ReprPacked(Align(4 bytes)), ReprTransparent])]
 struct Example {
 }
diff --git a/tests/run-make/musl-default-linking/rmake.rs b/tests/run-make/musl-default-linking/rmake.rs
index d203595a447..017444cfcdd 100644
--- a/tests/run-make/musl-default-linking/rmake.rs
+++ b/tests/run-make/musl-default-linking/rmake.rs
@@ -45,8 +45,21 @@ fn main() {
 
         let target_spec: serde_json::Value =
             serde_json::from_str(&target_spec_json).expect("failed to parse target-spec-json");
-        let default = &target_spec["crt-static-default"];
 
+        let target_families = &target_spec["target-family"];
+        // WebAssembly doesn't support dynamic linking yet; all musl targets
+        // need to be statically linked.
+        if target_families
+            .as_array()
+            .expect("target-family wasn't an array")
+            .iter()
+            .filter_map(|x| x.as_str())
+            .any(|family| family == "wasm")
+        {
+            continue;
+        }
+
+        let default = &target_spec["crt-static-default"];
         // If the value is `null`, then the default to dynamically link from
         // musl_base was not overridden.
         if default.is_null() {
diff --git a/tests/run-make/rust-lld/rmake.rs b/tests/run-make/rust-lld/rmake.rs
index e5ae9435388..35f716c24c7 100644
--- a/tests/run-make/rust-lld/rmake.rs
+++ b/tests/run-make/rust-lld/rmake.rs
@@ -60,7 +60,8 @@ fn main() {
 }
 
 fn find_lld_version_in_logs(stderr: String) -> bool {
-    let lld_version_re =
-        Regex::new(r"^warning: linker std(out|err): LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
+    // Strip the `-Wlinker-messages` wrappers prefixing the linker output.
+    let stderr = Regex::new(r"warning: linker std(out|err):").unwrap().replace_all(&stderr, "");
+    let lld_version_re = Regex::new(r"^LLD [0-9]+\.[0-9]+\.[0-9]+").unwrap();
     stderr.lines().any(|line| lld_version_re.is_match(line.trim()))
 }
diff --git a/tests/rustdoc-json/enums/discriminant/struct.rs b/tests/rustdoc-json/enums/discriminant/struct.rs
index 82437f5ef03..f2bed77902b 100644
--- a/tests/rustdoc-json/enums/discriminant/struct.rs
+++ b/tests/rustdoc-json/enums/discriminant/struct.rs
@@ -1,5 +1,5 @@
 #[repr(i32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(SignedInt(I32))])\")]\n"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(SignedInt(I32))])]\n"]'
 pub enum Foo {
     //@ is    "$.index[*][?(@.name=='Struct')].inner.variant.discriminant" null
     //@ count "$.index[*][?(@.name=='Struct')].inner.variant.kind.struct.fields[*]" 0
diff --git a/tests/rustdoc-json/enums/discriminant/tuple.rs b/tests/rustdoc-json/enums/discriminant/tuple.rs
index 25bba07e8f7..201c1cdc88e 100644
--- a/tests/rustdoc-json/enums/discriminant/tuple.rs
+++ b/tests/rustdoc-json/enums/discriminant/tuple.rs
@@ -1,5 +1,5 @@
 #[repr(u32)]
-//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr=\"Repr([ReprInt(UnsignedInt(U32))])\")]\n"]'
+//@ is "$.index[*][?(@.name=='Foo')].attrs" '["#[attr = Repr([ReprInt(UnsignedInt(U32))])]\n"]'
 pub enum Foo {
     //@ is    "$.index[*][?(@.name=='Tuple')].inner.variant.discriminant" null
     //@ count "$.index[*][?(@.name=='Tuple')].inner.variant.kind.tuple[*]" 0
diff --git a/tests/ui/associated-inherent-types/constrain_opaque_types_during_projection.rs b/tests/ui/associated-inherent-types/constrain_opaque_types_during_projection.rs
index 292733cd492..929fa354cd0 100644
--- a/tests/ui/associated-inherent-types/constrain_opaque_types_during_projection.rs
+++ b/tests/ui/associated-inherent-types/constrain_opaque_types_during_projection.rs
@@ -11,7 +11,8 @@ impl Foo<i32> {
 
 type Tait = impl Sized;
 
-fn bar(_: Tait) {
+#[define_opaque(Tait)]
+fn bar() {
     let x: Foo<Tait>::Assoc = 42;
 }
 
diff --git a/tests/ui/associated-inherent-types/issue-109299-1.stderr b/tests/ui/associated-inherent-types/issue-109299-1.stderr
index 77a78da852f..940ccd7e400 100644
--- a/tests/ui/associated-inherent-types/issue-109299-1.stderr
+++ b/tests/ui/associated-inherent-types/issue-109299-1.stderr
@@ -29,7 +29,7 @@ error: unconstrained opaque type
 LL | type X = impl for<T> Fn() -> Lexer<T>::Cursor;
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `X` must be used in combination with a concrete type within the same module
+   = note: `X` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/associated-type-bounds/dont-imply-atb-in-closure-inference.rs b/tests/ui/associated-type-bounds/dont-imply-atb-in-closure-inference.rs
index fecb3b15338..1cfbefb9daa 100644
--- a/tests/ui/associated-type-bounds/dont-imply-atb-in-closure-inference.rs
+++ b/tests/ui/associated-type-bounds/dont-imply-atb-in-closure-inference.rs
@@ -11,10 +11,8 @@ impl<T> IsPtr for T {
 
 type Tait = impl IsPtr<Assoc: Fn(i32)> + Fn(u32);
 
-fn hello()
-where
-    Tait:,
-{
+#[define_opaque(Tait)]
+fn hello() {
     let _: Tait = |x| {};
 }
 
diff --git a/tests/ui/associated-type-bounds/duplicate.rs b/tests/ui/associated-type-bounds/duplicate.rs
index 2b4a01376d7..e9d94787e98 100644
--- a/tests/ui/associated-type-bounds/duplicate.rs
+++ b/tests/ui/associated-type-bounds/duplicate.rs
@@ -179,19 +179,25 @@ where
 
 type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
 //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
 //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
 //~| ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
+//~| ERROR unconstrained opaque type
 
 trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
 //~^ ERROR the value of the associated type `Item` in trait `Iterator` is already specified [E0719]
diff --git a/tests/ui/associated-type-bounds/duplicate.stderr b/tests/ui/associated-type-bounds/duplicate.stderr
index 0dabcbdce1b..1ce212a9ff3 100644
--- a/tests/ui/associated-type-bounds/duplicate.stderr
+++ b/tests/ui/associated-type-bounds/duplicate.stderr
@@ -325,7 +325,7 @@ LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:182:36
+  --> $DIR/duplicate.rs:183:36
    |
 LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -333,7 +333,7 @@ LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:184:39
+  --> $DIR/duplicate.rs:186:39
    |
 LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -341,7 +341,7 @@ LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:186:40
+  --> $DIR/duplicate.rs:189:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -349,7 +349,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:186:40
+  --> $DIR/duplicate.rs:189:40
    |
 LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -359,7 +359,7 @@ LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:189:40
+  --> $DIR/duplicate.rs:193:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -367,7 +367,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:189:40
+  --> $DIR/duplicate.rs:193:40
    |
 LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    |                            ----------  ^^^^^^^^^^ re-bound here
@@ -377,7 +377,7 @@ LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:192:43
+  --> $DIR/duplicate.rs:197:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -385,7 +385,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:192:43
+  --> $DIR/duplicate.rs:197:43
    |
 LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    |                            -------------  ^^^^^^^^^^^^^ re-bound here
@@ -395,7 +395,7 @@ LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:196:36
+  --> $DIR/duplicate.rs:202:36
    |
 LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -403,7 +403,7 @@ LL | trait TRI1<T: Iterator<Item: Copy, Item: Send>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:198:36
+  --> $DIR/duplicate.rs:204:36
    |
 LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        ----------  ^^^^^^^^^^ re-bound here
@@ -411,7 +411,7 @@ LL | trait TRI2<T: Iterator<Item: Copy, Item: Copy>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:200:39
+  --> $DIR/duplicate.rs:206:39
    |
 LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        -------------  ^^^^^^^^^^^^^ re-bound here
@@ -419,7 +419,7 @@ LL | trait TRI3<T: Iterator<Item: 'static, Item: 'static>> {}
    |                        `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:202:34
+  --> $DIR/duplicate.rs:208:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -427,7 +427,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:202:34
+  --> $DIR/duplicate.rs:208:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -437,7 +437,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:202:34
+  --> $DIR/duplicate.rs:208:34
    |
 LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -447,7 +447,7 @@ LL | trait TRS1: Iterator<Item: Copy, Item: Send> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:206:34
+  --> $DIR/duplicate.rs:212:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -455,7 +455,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:206:34
+  --> $DIR/duplicate.rs:212:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -465,7 +465,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:206:34
+  --> $DIR/duplicate.rs:212:34
    |
 LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -475,7 +475,7 @@ LL | trait TRS2: Iterator<Item: Copy, Item: Copy> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:210:37
+  --> $DIR/duplicate.rs:216:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -483,7 +483,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:210:37
+  --> $DIR/duplicate.rs:216:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -493,7 +493,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:210:37
+  --> $DIR/duplicate.rs:216:37
    |
 LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -503,7 +503,7 @@ LL | trait TRS3: Iterator<Item: 'static, Item: 'static> {}
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:216:29
+  --> $DIR/duplicate.rs:222:29
    |
 LL |     T: Iterator<Item: Copy, Item: Send>,
    |                 ----------  ^^^^^^^^^^ re-bound here
@@ -511,7 +511,7 @@ LL |     T: Iterator<Item: Copy, Item: Send>,
    |                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:222:29
+  --> $DIR/duplicate.rs:228:29
    |
 LL |     T: Iterator<Item: Copy, Item: Copy>,
    |                 ----------  ^^^^^^^^^^ re-bound here
@@ -519,7 +519,7 @@ LL |     T: Iterator<Item: Copy, Item: Copy>,
    |                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:228:32
+  --> $DIR/duplicate.rs:234:32
    |
 LL |     T: Iterator<Item: 'static, Item: 'static>,
    |                 -------------  ^^^^^^^^^^^^^ re-bound here
@@ -527,7 +527,7 @@ LL |     T: Iterator<Item: 'static, Item: 'static>,
    |                 `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:234:32
+  --> $DIR/duplicate.rs:240:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Send>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -535,7 +535,7 @@ LL |     Self: Iterator<Item: Copy, Item: Send>,
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:234:32
+  --> $DIR/duplicate.rs:240:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Send>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -545,7 +545,7 @@ LL |     Self: Iterator<Item: Copy, Item: Send>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:234:32
+  --> $DIR/duplicate.rs:240:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Send>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -555,7 +555,7 @@ LL |     Self: Iterator<Item: Copy, Item: Send>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:242:32
+  --> $DIR/duplicate.rs:248:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -563,7 +563,7 @@ LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:242:32
+  --> $DIR/duplicate.rs:248:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -573,7 +573,7 @@ LL |     Self: Iterator<Item: Copy, Item: Copy>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:242:32
+  --> $DIR/duplicate.rs:248:32
    |
 LL |     Self: Iterator<Item: Copy, Item: Copy>,
    |                    ----------  ^^^^^^^^^^ re-bound here
@@ -583,7 +583,7 @@ LL |     Self: Iterator<Item: Copy, Item: Copy>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:250:35
+  --> $DIR/duplicate.rs:256:35
    |
 LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
@@ -591,7 +591,7 @@ LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |                    `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:250:35
+  --> $DIR/duplicate.rs:256:35
    |
 LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
@@ -601,7 +601,7 @@ LL |     Self: Iterator<Item: 'static, Item: 'static>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:250:35
+  --> $DIR/duplicate.rs:256:35
    |
 LL |     Self: Iterator<Item: 'static, Item: 'static>,
    |                    -------------  ^^^^^^^^^^^^^ re-bound here
@@ -611,7 +611,7 @@ LL |     Self: Iterator<Item: 'static, Item: 'static>,
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:257:34
+  --> $DIR/duplicate.rs:263:34
    |
 LL |     type A: Iterator<Item: Copy, Item: Send>;
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -619,7 +619,7 @@ LL |     type A: Iterator<Item: Copy, Item: Send>;
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:257:34
+  --> $DIR/duplicate.rs:263:34
    |
 LL |     type A: Iterator<Item: Copy, Item: Send>;
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -629,7 +629,7 @@ LL |     type A: Iterator<Item: Copy, Item: Send>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:262:34
+  --> $DIR/duplicate.rs:268:34
    |
 LL |     type A: Iterator<Item: Copy, Item: Copy>;
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -637,7 +637,7 @@ LL |     type A: Iterator<Item: Copy, Item: Copy>;
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:262:34
+  --> $DIR/duplicate.rs:268:34
    |
 LL |     type A: Iterator<Item: Copy, Item: Copy>;
    |                      ----------  ^^^^^^^^^^ re-bound here
@@ -647,7 +647,7 @@ LL |     type A: Iterator<Item: Copy, Item: Copy>;
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:267:37
+  --> $DIR/duplicate.rs:273:37
    |
 LL |     type A: Iterator<Item: 'static, Item: 'static>;
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -655,7 +655,7 @@ LL |     type A: Iterator<Item: 'static, Item: 'static>;
    |                      `Item` bound here first
 
 error[E0719]: the value of the associated type `Item` in trait `Iterator` is already specified
-  --> $DIR/duplicate.rs:267:37
+  --> $DIR/duplicate.rs:273:37
    |
 LL |     type A: Iterator<Item: 'static, Item: 'static>;
    |                      -------------  ^^^^^^^^^^^^^ re-bound here
@@ -697,7 +697,55 @@ help: consider specifying the generic argument
 LL |     iter::empty::<T>()
    |                +++++
 
-error: aborting due to 81 previous errors
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:180:51
+   |
+LL | type ETAI1<T: Iterator<Item: Copy, Item: Send>> = impl Copy;
+   |                                                   ^^^^^^^^^
+   |
+   = note: `ETAI1` must be used in combination with a concrete type within the same crate
+
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:183:51
+   |
+LL | type ETAI2<T: Iterator<Item: Copy, Item: Copy>> = impl Copy;
+   |                                                   ^^^^^^^^^
+   |
+   = note: `ETAI2` must be used in combination with a concrete type within the same crate
+
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:186:57
+   |
+LL | type ETAI3<T: Iterator<Item: 'static, Item: 'static>> = impl Copy;
+   |                                                         ^^^^^^^^^
+   |
+   = note: `ETAI3` must be used in combination with a concrete type within the same crate
+
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:189:14
+   |
+LL | type ETAI4 = impl Iterator<Item: Copy, Item: Send>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ETAI4` must be used in combination with a concrete type within the same crate
+
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:193:14
+   |
+LL | type ETAI5 = impl Iterator<Item: Copy, Item: Copy>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ETAI5` must be used in combination with a concrete type within the same crate
+
+error: unconstrained opaque type
+  --> $DIR/duplicate.rs:197:14
+   |
+LL | type ETAI6 = impl Iterator<Item: 'static, Item: 'static>;
+   |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `ETAI6` must be used in combination with a concrete type within the same crate
+
+error: aborting due to 87 previous errors
 
 Some errors have detailed explanations: E0282, E0719.
 For more information about an error, try `rustc --explain E0282`.
diff --git a/tests/ui/associated-type-bounds/hrtb.rs b/tests/ui/associated-type-bounds/hrtb.rs
index 1bf574f2e65..8ff7faec3a0 100644
--- a/tests/ui/associated-type-bounds/hrtb.rs
+++ b/tests/ui/associated-type-bounds/hrtb.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 
 trait A<'a> {}
 trait B<'b> {}
diff --git a/tests/ui/associated-type-bounds/supertrait-defines-ty.rs b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
index ed1c1fa6f03..1c09ff3d3fb 100644
--- a/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
+++ b/tests/ui/associated-type-bounds/supertrait-defines-ty.rs
@@ -1,4 +1,7 @@
 //@ check-pass
+//@ revisions: current next
+//@[next] compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver (explicit revisions)
 
 // Make sure that we don't look into associated type bounds when looking for
 // supertraits that define an associated type. Fixes #76593.
diff --git a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs
index fb6a4fcbe97..540c083e309 100644
--- a/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs
+++ b/tests/ui/associated-type-bounds/trait-alias-impl-trait.rs
@@ -31,6 +31,7 @@ impl Tr1 for S1 {
 }
 
 type Et1 = impl Tr1<As1: Copy>;
+#[define_opaque(Et1)]
 fn def_et1() -> Et1 {
     S1
 }
@@ -39,6 +40,7 @@ pub fn use_et1() {
 }
 
 type Et2 = impl Tr1<As1: 'static>;
+#[define_opaque(Et2)]
 fn def_et2() -> Et2 {
     S1
 }
@@ -47,6 +49,7 @@ pub fn use_et2() {
 }
 
 type Et3 = impl Tr1<As1: Clone + Iterator<Item: Add<u8, Output: Into<u8>>>>;
+#[define_opaque(Et3)]
 fn def_et3() -> Et3 {
     struct A;
     impl Tr1 for A {
@@ -68,6 +71,7 @@ pub fn use_et3() {
 }
 
 type Et4 = impl Tr1<As1: for<'a> Tr2<'a>>;
+#[define_opaque(Et4)]
 fn def_et4() -> Et4 {
     #[derive(Copy, Clone)]
     struct A;
diff --git a/tests/ui/associated-types/issue-59324.rs b/tests/ui/associated-types/issue-59324.rs
index 7421e08c898..3abe8473052 100644
--- a/tests/ui/associated-types/issue-59324.rs
+++ b/tests/ui/associated-types/issue-59324.rs
@@ -15,6 +15,7 @@ pub trait ThriftService<Bug: NotFoo>:
 {
     fn get_service(
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
+    //~| ERROR the trait bound `Bug: Foo` is not satisfied
         &self,
     ) -> Self::AssocType;
     //~^ ERROR the trait bound `Bug: Foo` is not satisfied
diff --git a/tests/ui/associated-types/issue-59324.stderr b/tests/ui/associated-types/issue-59324.stderr
index dc8f9cfe895..f5e696b7ac1 100644
--- a/tests/ui/associated-types/issue-59324.stderr
+++ b/tests/ui/associated-types/issue-59324.stderr
@@ -32,6 +32,7 @@ error[E0277]: the trait bound `Bug: Foo` is not satisfied
    |
 LL | /     fn get_service(
 LL | |
+LL | |
 LL | |         &self,
 LL | |     ) -> Self::AssocType;
    | |_________________________^ the trait `Foo` is not implemented for `Bug`
@@ -41,8 +42,18 @@ help: consider further restricting type parameter `Bug` with trait `Foo`
 LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
+error[E0277]: the trait bound `Bug: Foo` is not satisfied
+  --> $DIR/issue-59324.rs:16:5
+   |
+LL | /     fn get_service(
+LL | |
+LL | |
+LL | |         &self,
+LL | |     ) -> Self::AssocType;
+   | |_________________________^ the trait `Foo` is not implemented for `Bug`
+
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -54,7 +65,7 @@ LL | pub trait Foo: NotFoo {
    | ^^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: the trait bound `Bug: Foo` is not satisfied
-  --> $DIR/issue-59324.rs:19:10
+  --> $DIR/issue-59324.rs:20:10
    |
 LL |     ) -> Self::AssocType;
    |          ^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `Bug`
@@ -65,7 +76,7 @@ LL | pub trait ThriftService<Bug: NotFoo + Foo>:
    |                                     +++++
 
 error[E0277]: the trait bound `(): Foo` is not satisfied
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ the trait `Foo` is not implemented for `()`
@@ -78,7 +89,7 @@ LL | pub trait Foo: NotFoo {
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0277]: the size for values of type `(dyn ThriftService<(), AssocType = _> + 'static)` cannot be known at compilation time
-  --> $DIR/issue-59324.rs:23:29
+  --> $DIR/issue-59324.rs:24:29
    |
 LL | fn with_factory<H>(factory: dyn ThriftService<()>) {}
    |                             ^^^^^^^^^^^^^^^^^^^^^ doesn't have a size known at compile-time
@@ -95,6 +106,6 @@ help: function arguments must have a statically known size, borrowed types alway
 LL | fn with_factory<H>(factory: &dyn ThriftService<()>) {}
    |                             +
 
-error: aborting due to 7 previous errors
+error: aborting due to 8 previous errors
 
 For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/async-await/async-fn/impl-trait.rs b/tests/ui/async-await/async-fn/impl-trait.rs
index f284de8981a..89c41ceb2da 100644
--- a/tests/ui/async-await/async-fn/impl-trait.rs
+++ b/tests/ui/async-await/async-fn/impl-trait.rs
@@ -4,11 +4,14 @@
 #![feature(type_alias_impl_trait)]
 
 type Tait = impl AsyncFn();
+#[define_opaque(Tait)]
 fn tait() -> Tait {
     || async {}
 }
 
-fn foo(x: impl AsyncFn()) -> impl AsyncFn() { x }
+fn foo(x: impl AsyncFn()) -> impl AsyncFn() {
+    x
+}
 
 fn param<T: AsyncFn()>() {}
 
diff --git a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
index 4a8b5af5769..f9eeb361b13 100644
--- a/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
+++ b/tests/ui/async-await/issues/issue-60655-latebound-regions.rs
@@ -11,15 +11,17 @@ pub type Func = impl Sized;
 
 // Late bound region should be allowed to escape the function, since it's bound
 // in the type.
+#[define_opaque(Func)]
 fn null_function_ptr() -> Func {
     None::<for<'a> fn(&'a ())>
 }
 
 async fn async_nop(_: &u8) {}
 
-pub type ServeFut = impl Future<Output=()>;
+pub type ServeFut = impl Future<Output = ()>;
 
 // Late bound regions occur in the coroutine witness type here.
+#[define_opaque(ServeFut)]
 fn serve() -> ServeFut {
     async move {
         let x = 5;
diff --git a/tests/ui/async-await/normalize-output-in-signature-deduction.rs b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
index 19d70c2c6ee..e2238d85093 100644
--- a/tests/ui/async-await/normalize-output-in-signature-deduction.rs
+++ b/tests/ui/async-await/normalize-output-in-signature-deduction.rs
@@ -13,6 +13,7 @@ pub trait Trait {}
 
 pub type TAIT<T> = impl Trait;
 
+#[define_opaque(TAIT)]
 async fn foo<T>() -> TAIT<T> {
     Foo
 }
diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.rs b/tests/ui/attributes/collapse-debuginfo-invalid.rs
index d6b3554a5a8..ccf11df2eb0 100644
--- a/tests/ui/attributes/collapse-debuginfo-invalid.rs
+++ b/tests/ui/attributes/collapse-debuginfo-invalid.rs
@@ -24,15 +24,15 @@ const BAR: u32 = 3;
 //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
 fn foo() {
     let _ = #[collapse_debuginfo(yes)] || { };
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     let _ = 3;
     let _ = #[collapse_debuginfo(yes)] 3;
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     match (3, 4) {
         #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+        //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
         _ => (),
     }
 }
@@ -50,7 +50,7 @@ type Map = HashMap<u32, u32>;
 //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
 enum Foo {
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     Variant,
 }
 
@@ -58,7 +58,7 @@ enum Foo {
 //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
 struct Bar {
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     field: u32,
 }
 
@@ -73,7 +73,7 @@ union Qux {
 //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
 trait Foobar {
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     type Bar;
 }
 
@@ -85,6 +85,7 @@ impl Foobar for Bar {
     type Bar = u32;
 }
 
+#[define_opaque(AFoobar)]
 fn constraining() -> AFoobar {
     Bar { field: 3 }
 }
@@ -93,11 +94,11 @@ fn constraining() -> AFoobar {
 //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
 impl Bar {
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     const FOO: u32 = 3;
 
     #[collapse_debuginfo(yes)]
-//~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
+    //~^ ERROR `collapse_debuginfo` attribute should be applied to macro definitions
     fn bar(&self) {}
 }
 
diff --git a/tests/ui/attributes/collapse-debuginfo-invalid.stderr b/tests/ui/attributes/collapse-debuginfo-invalid.stderr
index 70376f985cb..081e4445a86 100644
--- a/tests/ui/attributes/collapse-debuginfo-invalid.stderr
+++ b/tests/ui/attributes/collapse-debuginfo-invalid.stderr
@@ -176,7 +176,7 @@ LL | type AFoobar = impl Foobar;
    | --------------------------- not a macro definition
 
 error: `collapse_debuginfo` attribute should be applied to macro definitions
-  --> $DIR/collapse-debuginfo-invalid.rs:92:1
+  --> $DIR/collapse-debuginfo-invalid.rs:93:1
    |
 LL |   #[collapse_debuginfo(yes)]
    |   ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -200,7 +200,7 @@ LL |     type Bar;
    |     --------- not a macro definition
 
 error: `collapse_debuginfo` attribute should be applied to macro definitions
-  --> $DIR/collapse-debuginfo-invalid.rs:95:5
+  --> $DIR/collapse-debuginfo-invalid.rs:96:5
    |
 LL |     #[collapse_debuginfo(yes)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -209,7 +209,7 @@ LL |     const FOO: u32 = 3;
    |     ------------------- not a macro definition
 
 error: `collapse_debuginfo` attribute should be applied to macro definitions
-  --> $DIR/collapse-debuginfo-invalid.rs:99:5
+  --> $DIR/collapse-debuginfo-invalid.rs:100:5
    |
 LL |     #[collapse_debuginfo(yes)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/attributes/z-crate-attr.rs b/tests/ui/attributes/z-crate-attr/basic.rs
index 119a48d5d65..119a48d5d65 100644
--- a/tests/ui/attributes/z-crate-attr.rs
+++ b/tests/ui/attributes/z-crate-attr/basic.rs
diff --git a/tests/ui/attributes/z-crate-attr/cfg-false.rs b/tests/ui/attributes/z-crate-attr/cfg-false.rs
new file mode 100644
index 00000000000..db37cfdd086
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/cfg-false.rs
@@ -0,0 +1,7 @@
+// Ensure that `-Z crate-attr=cfg(FALSE)` can comment out the whole crate
+//@ compile-flags: --crate-type=lib -Zcrate-attr=cfg(FALSE)
+//@ check-pass
+
+// NOTE: duplicate items are load-bearing
+fn foo() {}
+fn foo() {}
diff --git a/tests/ui/attributes/z-crate-attr/comments.rs b/tests/ui/attributes/z-crate-attr/comments.rs
new file mode 100644
index 00000000000..c1ab041f344
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/comments.rs
@@ -0,0 +1,5 @@
+//@ check-pass
+//@ compile-flags: -Zcrate-attr=/*hi-there*/feature(rustc_attrs)
+
+#[rustc_dummy]
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/crate-name.rs b/tests/ui/attributes/z-crate-attr/crate-name.rs
new file mode 100644
index 00000000000..d49830390e2
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/crate-name.rs
@@ -0,0 +1,6 @@
+// Ensure that `crate_name` and `crate_type` can be set through `-Z crate-attr`.
+//@ check-pass
+//@ compile-flags: -Zcrate-attr=crate_name="override"
+fn main() {
+    assert_eq!(module_path!(), "r#override");
+}
diff --git a/tests/ui/attributes/z-crate-attr/crate-type.rs b/tests/ui/attributes/z-crate-attr/crate-type.rs
new file mode 100644
index 00000000000..0e7411865af
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/crate-type.rs
@@ -0,0 +1,3 @@
+//@ check-pass
+//@ compile-flags: -Zcrate-attr=crate_type="lib"
+// notice the lack of `main` is load-bearing
diff --git a/tests/ui/attributes/z-crate-attr/garbage.rs b/tests/ui/attributes/z-crate-attr/garbage.rs
new file mode 100644
index 00000000000..ec81dd1bcaa
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/garbage.rs
@@ -0,0 +1,4 @@
+// Show diagnostics for invalid tokens
+//@ compile-flags: -Zcrate-attr=`%~@$#
+//@ error-pattern:unknown start of token
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/garbage.stderr b/tests/ui/attributes/z-crate-attr/garbage.stderr
new file mode 100644
index 00000000000..082046e31f8
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/garbage.stderr
@@ -0,0 +1,20 @@
+error: unknown start of token: `
+  --> <crate attribute>:1:1
+   |
+LL | `%~@$#
+   | ^
+   |
+help: Unicode character '`' (Grave Accent) looks like ''' (Single Quote), but it is not
+   |
+LL - `%~@$#
+LL + '%~@$#
+   |
+
+error: expected identifier, found `%`
+  --> <crate attribute>:1:2
+   |
+LL | `%~@$#
+   |  ^ expected identifier
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/attributes/z-crate-attr/injection.rs b/tests/ui/attributes/z-crate-attr/injection.rs
new file mode 100644
index 00000000000..0c5c81ca71a
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/injection.rs
@@ -0,0 +1,3 @@
+//@ compile-flags: '-Zcrate-attr=feature(yeet_expr)]fn main(){}#[inline'
+//@ error-pattern:unexpected closing delimiter
+fn foo() {}
diff --git a/tests/ui/attributes/z-crate-attr/injection.stderr b/tests/ui/attributes/z-crate-attr/injection.stderr
new file mode 100644
index 00000000000..6fec98baf8d
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/injection.stderr
@@ -0,0 +1,8 @@
+error: unexpected closing delimiter: `]`
+  --> <crate attribute>:1:19
+   |
+LL | feature(yeet_expr)]fn main(){}#[inline
+   |                   ^ unexpected closing delimiter
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.rs b/tests/ui/attributes/z-crate-attr/inner-attr.rs
new file mode 100644
index 00000000000..522c906dcd8
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/inner-attr.rs
@@ -0,0 +1,4 @@
+//@ compile-flags: -Zcrate-attr=#![feature(foo)]
+//@ error-pattern:expected identifier
+
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/inner-attr.stderr b/tests/ui/attributes/z-crate-attr/inner-attr.stderr
new file mode 100644
index 00000000000..06a063d310b
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/inner-attr.stderr
@@ -0,0 +1,8 @@
+error: expected identifier, found `#`
+  --> <crate attribute>:1:1
+   |
+LL | #![feature(foo)]
+   | ^ expected identifier
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/z-crate-attr/multiple.rs b/tests/ui/attributes/z-crate-attr/multiple.rs
new file mode 100644
index 00000000000..ee13253f625
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/multiple.rs
@@ -0,0 +1,3 @@
+//@ compile-flags: -Zcrate-attr=feature(foo),feature(bar)
+//@ error-pattern:invalid crate attr
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/multiple.stderr b/tests/ui/attributes/z-crate-attr/multiple.stderr
new file mode 100644
index 00000000000..9f968a7e134
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/multiple.stderr
@@ -0,0 +1,8 @@
+error: invalid crate attribute
+  --> <crate attribute>:1:1
+   |
+LL | feature(foo),feature(bar)
+   | ^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/attributes/z-crate-attr/respect-existing-attrs.rs b/tests/ui/attributes/z-crate-attr/respect-existing-attrs.rs
new file mode 100644
index 00000000000..71f2559998f
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/respect-existing-attrs.rs
@@ -0,0 +1,9 @@
+// Make sure that existing root attributes are still respected even when `-Zcrate-attr` is present.
+//@ run-pass
+//@ compile-flags: -Zcrate-attr=feature(rustc_attrs)
+#![crate_name = "override"]
+
+#[rustc_dummy]
+fn main() {
+    assert_eq!(module_path!(), "r#override");
+}
diff --git a/tests/ui/attributes/z-crate-attr/shebang.rs b/tests/ui/attributes/z-crate-attr/shebang.rs
new file mode 100644
index 00000000000..195393acaf5
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/shebang.rs
@@ -0,0 +1,6 @@
+#!/usr/bin/env -S cargo +nightly -Zscript
+// Make sure that shebangs are still allowed even when `-Zcrate-attr` is present.
+//@ check-pass
+//@ compile-flags: -Zcrate-attr=feature(rustc_attrs)
+#[rustc_dummy]
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs
new file mode 100644
index 00000000000..fc1d7f39a59
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.rs
@@ -0,0 +1,4 @@
+// Show diagnostics for unbalanced parens.
+//@ compile-flags: -Zcrate-attr=(
+//@ error-pattern:unclosed delimiter
+fn main() {}
diff --git a/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr
new file mode 100644
index 00000000000..47b1b764ba9
--- /dev/null
+++ b/tests/ui/attributes/z-crate-attr/unbalanced-paren.stderr
@@ -0,0 +1,10 @@
+error: this file contains an unclosed delimiter
+  --> <crate attribute>:1:2
+   |
+LL | (
+   | -^
+   | |
+   | unclosed delimiter
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/autodiff/autodiff_illegal.rs b/tests/ui/autodiff/autodiff_illegal.rs
index c0548d2bbb8..e810b9ba565 100644
--- a/tests/ui/autodiff/autodiff_illegal.rs
+++ b/tests/ui/autodiff/autodiff_illegal.rs
@@ -12,41 +12,40 @@ use std::autodiff::autodiff;
 // We can't use Duplicated on scalars
 #[autodiff(df1, Reverse, Duplicated)]
 pub fn f1(x: f64) {
-//~^ ERROR     Duplicated can not be used for this type
+    //~^ ERROR     Duplicated can not be used for this type
     unimplemented!()
 }
 
 // Too many activities
 #[autodiff(df3, Reverse, Duplicated, Const)]
 pub fn f3(x: f64) {
-//~^^ ERROR     expected 1 activities, but found 2
+    //~^^ ERROR     expected 1 activities, but found 2
     unimplemented!()
 }
 
 // To few activities
 #[autodiff(df4, Reverse)]
 pub fn f4(x: f64) {
-//~^^ ERROR     expected 1 activities, but found 0
+    //~^^ ERROR     expected 1 activities, but found 0
     unimplemented!()
 }
 
 // We can't use Dual in Reverse mode
 #[autodiff(df5, Reverse, Dual)]
 pub fn f5(x: f64) {
-//~^^ ERROR     Dual can not be used in Reverse Mode
+    //~^^ ERROR     Dual can not be used in Reverse Mode
     unimplemented!()
 }
 
 // We can't use Duplicated in Forward mode
 #[autodiff(df6, Forward, Duplicated)]
 pub fn f6(x: f64) {
-//~^^ ERROR Duplicated can not be used in Forward Mode
-//~^^ ERROR Duplicated can not be used for this type
+    //~^^ ERROR Duplicated can not be used in Forward Mode
+    //~^^ ERROR Duplicated can not be used for this type
     unimplemented!()
 }
 
 fn dummy() {
-
     #[autodiff(df7, Forward, Dual)]
     let mut x = 5;
     //~^ ERROR autodiff must be applied to function
@@ -64,21 +63,21 @@ fn dummy() {
 // Malformed, where args?
 #[autodiff]
 pub fn f7(x: f64) {
-//~^ ERROR autodiff must be applied to function
+    //~^ ERROR autodiff must be applied to function
     unimplemented!()
 }
 
 // Malformed, where args?
 #[autodiff()]
 pub fn f8(x: f64) {
-//~^ ERROR autodiff requires at least a name and mode
+    //~^ ERROR autodiff requires at least a name and mode
     unimplemented!()
 }
 
 // Invalid attribute syntax
 #[autodiff = ""]
 pub fn f9(x: f64) {
-//~^ ERROR autodiff must be applied to function
+    //~^ ERROR autodiff must be applied to function
     unimplemented!()
 }
 
@@ -87,21 +86,21 @@ fn fn_exists() {}
 // We colide with an already existing function
 #[autodiff(fn_exists, Reverse, Active)]
 pub fn f10(x: f64) {
-//~^^ ERROR the name `fn_exists` is defined multiple times [E0428]
+    //~^^ ERROR the name `fn_exists` is defined multiple times [E0428]
     unimplemented!()
 }
 
 // Malformed, missing a mode
 #[autodiff(df11)]
 pub fn f11() {
-//~^ ERROR autodiff requires at least a name and mode
+    //~^ ERROR autodiff requires at least a name and mode
     unimplemented!()
 }
 
 // Invalid Mode
 #[autodiff(df12, Debug)]
 pub fn f12() {
-//~^^ ERROR unknown Mode: `Debug`. Use `Forward` or `Reverse`
+    //~^^ ERROR unknown Mode: `Debug`. Use `Forward` or `Reverse`
     unimplemented!()
 }
 
@@ -109,7 +108,7 @@ pub fn f12() {
 // or use two autodiff macros.
 #[autodiff(df13, Forward, Reverse)]
 pub fn f13() {
-//~^^ ERROR did not recognize Activity: `Reverse`
+    //~^^ ERROR did not recognize Activity: `Reverse`
     unimplemented!()
 }
 
@@ -130,7 +129,7 @@ type MyFloat = f32;
 // like THIR which has type information available.
 #[autodiff(df15, Reverse, Active, Active)]
 fn f15(x: MyFloat) -> f32 {
-//~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433]
+    //~^^ ERROR failed to resolve: use of undeclared type `MyFloat` [E0433]
     unimplemented!()
 }
 
@@ -141,7 +140,9 @@ fn f16(x: f32) -> MyFloat {
 }
 
 #[repr(transparent)]
-struct F64Trans { inner: f64 }
+struct F64Trans {
+    inner: f64,
+}
 
 // We would like to support `#[repr(transparent)]` f32/f64 wrapper in return type in the future
 #[autodiff(df17, Reverse, Active, Active)]
@@ -156,5 +157,24 @@ fn f18(x: F64Trans) -> f64 {
     unimplemented!()
 }
 
+// Invalid return activity
+#[autodiff(df19, Forward, Dual, Active)]
+fn f19(x: f32) -> f32 {
+    //~^^ ERROR invalid return activity Active in Forward Mode
+    unimplemented!()
+}
+
+#[autodiff(df20, Reverse, Active, Dual)]
+fn f20(x: f32) -> f32 {
+    //~^^ ERROR invalid return activity Dual in Reverse Mode
+    unimplemented!()
+}
+
+// Duplicated cannot be used as return activity
+#[autodiff(df21, Reverse, Active, Duplicated)]
+fn f21(x: f32) -> f32 {
+    //~^^ ERROR invalid return activity Duplicated in Reverse Mode
+    unimplemented!()
+}
 
 fn main() {}
diff --git a/tests/ui/autodiff/autodiff_illegal.stderr b/tests/ui/autodiff/autodiff_illegal.stderr
index 3a7242b2f5d..47d53492700 100644
--- a/tests/ui/autodiff/autodiff_illegal.stderr
+++ b/tests/ui/autodiff/autodiff_illegal.stderr
@@ -1,5 +1,5 @@
 error[E0658]: attributes on expressions are experimental
-  --> $DIR/autodiff_illegal.rs:54:5
+  --> $DIR/autodiff_illegal.rs:53:5
    |
 LL |     #[autodiff(df7, Forward, Dual)]
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -53,25 +53,25 @@ LL | pub fn f6(x: f64) {
    |              ^^^
 
 error: autodiff must be applied to function
-  --> $DIR/autodiff_illegal.rs:51:5
+  --> $DIR/autodiff_illegal.rs:50:5
    |
 LL |     let mut x = 5;
    |     ^^^^^^^^^^^^^^
 
 error: autodiff must be applied to function
-  --> $DIR/autodiff_illegal.rs:55:5
+  --> $DIR/autodiff_illegal.rs:54:5
    |
 LL |     x = x + 3;
    |     ^
 
 error: autodiff must be applied to function
-  --> $DIR/autodiff_illegal.rs:60:5
+  --> $DIR/autodiff_illegal.rs:59:5
    |
 LL |     let add_one_v2 = |x: u32| -> u32 { x + 1 };
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error: autodiff must be applied to function
-  --> $DIR/autodiff_illegal.rs:66:1
+  --> $DIR/autodiff_illegal.rs:65:1
    |
 LL | / pub fn f7(x: f64) {
 LL | |
@@ -80,7 +80,7 @@ LL | | }
    | |_^
 
 error: autodiff requires at least a name and mode
-  --> $DIR/autodiff_illegal.rs:73:1
+  --> $DIR/autodiff_illegal.rs:72:1
    |
 LL | / pub fn f8(x: f64) {
 LL | |
@@ -89,7 +89,7 @@ LL | | }
    | |_^
 
 error: autodiff must be applied to function
-  --> $DIR/autodiff_illegal.rs:80:1
+  --> $DIR/autodiff_illegal.rs:79:1
    |
 LL | / pub fn f9(x: f64) {
 LL | |
@@ -98,7 +98,7 @@ LL | | }
    | |_^
 
 error[E0428]: the name `fn_exists` is defined multiple times
-  --> $DIR/autodiff_illegal.rs:88:1
+  --> $DIR/autodiff_illegal.rs:87:1
    |
 LL | fn fn_exists() {}
    | -------------- previous definition of the value `fn_exists` here
@@ -110,7 +110,7 @@ LL | #[autodiff(fn_exists, Reverse, Active)]
    = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: autodiff requires at least a name and mode
-  --> $DIR/autodiff_illegal.rs:96:1
+  --> $DIR/autodiff_illegal.rs:95:1
    |
 LL | / pub fn f11() {
 LL | |
@@ -119,19 +119,43 @@ LL | | }
    | |_^
 
 error: unknown Mode: `Debug`. Use `Forward` or `Reverse`
-  --> $DIR/autodiff_illegal.rs:102:18
+  --> $DIR/autodiff_illegal.rs:101:18
    |
 LL | #[autodiff(df12, Debug)]
    |                  ^^^^^
 
 error: did not recognize Activity: `Reverse`
-  --> $DIR/autodiff_illegal.rs:110:27
+  --> $DIR/autodiff_illegal.rs:109:27
    |
 LL | #[autodiff(df13, Forward, Reverse)]
    |                           ^^^^^^^
 
+error: invalid return activity Active in Forward Mode
+  --> $DIR/autodiff_illegal.rs:161:1
+   |
+LL | #[autodiff(df19, Forward, Dual, Active)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid return activity Dual in Reverse Mode
+  --> $DIR/autodiff_illegal.rs:167:1
+   |
+LL | #[autodiff(df20, Reverse, Active, Dual)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: invalid return activity Duplicated in Reverse Mode
+  --> $DIR/autodiff_illegal.rs:174:1
+   |
+LL | #[autodiff(df21, Reverse, Active, Duplicated)]
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
+
 error[E0433]: failed to resolve: use of undeclared type `MyFloat`
-  --> $DIR/autodiff_illegal.rs:131:1
+  --> $DIR/autodiff_illegal.rs:130:1
    |
 LL | #[autodiff(df15, Reverse, Active, Active)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `MyFloat`
@@ -139,14 +163,14 @@ LL | #[autodiff(df15, Reverse, Active, Active)]
    = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error[E0433]: failed to resolve: use of undeclared type `F64Trans`
-  --> $DIR/autodiff_illegal.rs:153:1
+  --> $DIR/autodiff_illegal.rs:154:1
    |
 LL | #[autodiff(df18, Reverse, Active, Active)]
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ use of undeclared type `F64Trans`
    |
    = note: this error originates in the attribute macro `autodiff` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: aborting due to 19 previous errors
+error: aborting due to 22 previous errors
 
 Some errors have detailed explanations: E0428, E0433, E0658.
 For more information about an error, try `rustc --explain E0428`.
diff --git a/tests/ui/borrowck/overwrite-anon-late-param-regions.rs b/tests/ui/borrowck/overwrite-anon-late-param-regions.rs
index 7b0f784068f..8e0e005cd78 100644
--- a/tests/ui/borrowck/overwrite-anon-late-param-regions.rs
+++ b/tests/ui/borrowck/overwrite-anon-late-param-regions.rs
@@ -6,6 +6,7 @@
 #![feature(type_alias_impl_trait)]
 type Opaque2<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque2)]
 fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'a>) {
     |x| x
     //~^ ERROR lifetime may not live long enough
diff --git a/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr b/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr
index c5b7284271e..96b3ebf1eb4 100644
--- a/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr
+++ b/tests/ui/borrowck/overwrite-anon-late-param-regions.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/overwrite-anon-late-param-regions.rs:10:9
+  --> $DIR/overwrite-anon-late-param-regions.rs:11:9
    |
 LL |     |x| x
    |      -  ^ closure was supposed to return data with lifetime `'2` but it is returning data with lifetime `'1`
@@ -8,7 +8,7 @@ LL |     |x| x
    |      has type `(&'2 str, &str)`
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/overwrite-anon-late-param-regions.rs:10:5
+  --> $DIR/overwrite-anon-late-param-regions.rs:11:5
    |
 LL | type Opaque2<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/check-cfg/allow-same-level.rs b/tests/ui/check-cfg/allow-same-level.rs
index 5eef50e08e2..8260b57bad4 100644
--- a/tests/ui/check-cfg/allow-same-level.rs
+++ b/tests/ui/check-cfg/allow-same-level.rs
@@ -3,7 +3,7 @@
 //
 // It should work, but due to interactions between how #[cfg]s are
 // expanded, the lint machinery and the check-cfg impl, we
-// miss the #[allow], althrough we probably shoudln't.
+// miss the #[allow], althrough we probably shouldn't.
 //
 // cf. https://github.com/rust-lang/rust/issues/124735
 //
diff --git a/tests/ui/coherence/coherence-with-closure.rs b/tests/ui/coherence/coherence-with-closure.rs
index 5b6a62b24d4..ac2c5584392 100644
--- a/tests/ui/coherence/coherence-with-closure.rs
+++ b/tests/ui/coherence/coherence-with-closure.rs
@@ -1,6 +1,7 @@
 // Test that encountering closures during coherence does not cause issues.
 #![feature(type_alias_impl_trait)]
 type OpaqueClosure = impl Sized;
+#[define_opaque(OpaqueClosure)]
 fn defining_use() -> OpaqueClosure {
     || ()
 }
diff --git a/tests/ui/coherence/coherence-with-closure.stderr b/tests/ui/coherence/coherence-with-closure.stderr
index 501279ffe6a..37f393ceeb7 100644
--- a/tests/ui/coherence/coherence-with-closure.stderr
+++ b/tests/ui/coherence/coherence-with-closure.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueClosure>`
-  --> $DIR/coherence-with-closure.rs:11:1
+  --> $DIR/coherence-with-closure.rs:12:1
    |
 LL | impl Trait for Wrapper<OpaqueClosure> {}
    | ------------------------------------- first implementation here
diff --git a/tests/ui/coherence/coherence-with-coroutine.rs b/tests/ui/coherence/coherence-with-coroutine.rs
index 6b0617e950b..0e65a6c1da0 100644
--- a/tests/ui/coherence/coherence-with-coroutine.rs
+++ b/tests/ui/coherence/coherence-with-coroutine.rs
@@ -7,6 +7,7 @@
 //@ [specialized]check-pass
 
 type OpaqueCoroutine = impl Sized;
+#[define_opaque(OpaqueCoroutine)]
 fn defining_use() -> OpaqueCoroutine {
     #[coroutine]
     || {
diff --git a/tests/ui/coherence/coherence-with-coroutine.stock.stderr b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
index 5f58b3088f1..c7af384df6d 100644
--- a/tests/ui/coherence/coherence-with-coroutine.stock.stderr
+++ b/tests/ui/coherence/coherence-with-coroutine.stock.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait` for type `Wrapper<OpaqueCoroutine>`
-  --> $DIR/coherence-with-coroutine.rs:22:1
+  --> $DIR/coherence-with-coroutine.rs:23:1
    |
 LL | impl Trait for Wrapper<OpaqueCoroutine> {}
    | --------------------------------------- first implementation here
diff --git a/tests/ui/coherence/issue-99663-2.rs b/tests/ui/coherence/issue-99663-2.rs
index 675e9fdfdba..9827df1d5e7 100644
--- a/tests/ui/coherence/issue-99663-2.rs
+++ b/tests/ui/coherence/issue-99663-2.rs
@@ -8,6 +8,7 @@ struct Outer<T: ?Sized> {
 
 type InnerSend<T: ?Sized> = impl Send;
 
+#[define_opaque(InnerSend)]
 fn constrain<T: ?Sized>() -> InnerSend<T> {
     ()
 }
diff --git a/tests/ui/coherence/issue-99663.rs b/tests/ui/coherence/issue-99663.rs
index 00d15977d8f..49156952990 100644
--- a/tests/ui/coherence/issue-99663.rs
+++ b/tests/ui/coherence/issue-99663.rs
@@ -8,6 +8,7 @@ struct Send<T> {
 
 type InnerSend<T> = impl Sized;
 
+#[define_opaque(InnerSend)]
 fn constrain<T>() -> InnerSend<T> {
     ()
 }
diff --git a/tests/ui/coherence/occurs-check/opaques.current.stderr b/tests/ui/coherence/occurs-check/opaques.current.stderr
index f3fc22027c2..d3850df5218 100644
--- a/tests/ui/coherence/occurs-check/opaques.current.stderr
+++ b/tests/ui/coherence/occurs-check/opaques.current.stderr
@@ -1,11 +1,11 @@
 error[E0119]: conflicting implementations of trait `Trait<_>`
-  --> $DIR/opaques.rs:28:1
+  --> $DIR/opaques.rs:27:1
    |
 LL | impl<T> Trait<T> for T {
    | ---------------------- first implementation here
 ...
-LL | impl<T> Trait<T> for defining_scope::Alias<T> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+LL | impl<T> Trait<T> for Alias<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/occurs-check/opaques.next.stderr b/tests/ui/coherence/occurs-check/opaques.next.stderr
index 04fd139f901..508e6f40234 100644
--- a/tests/ui/coherence/occurs-check/opaques.next.stderr
+++ b/tests/ui/coherence/occurs-check/opaques.next.stderr
@@ -1,17 +1,17 @@
 error[E0119]: conflicting implementations of trait `Trait<_>`
-  --> $DIR/opaques.rs:28:1
+  --> $DIR/opaques.rs:27:1
    |
 LL | impl<T> Trait<T> for T {
    | ---------------------- first implementation here
 ...
-LL | impl<T> Trait<T> for defining_scope::Alias<T> {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+LL | impl<T> Trait<T> for Alias<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error[E0282]: type annotations needed
-  --> $DIR/opaques.rs:11:23
+  --> $DIR/opaques.rs:11:19
    |
-LL |     pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
-   |                       ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
+LL | pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
+   |                   ^^^^^^^^^^^^^^^^^^^^^^ cannot infer type
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/coherence/occurs-check/opaques.rs b/tests/ui/coherence/occurs-check/opaques.rs
index e197256c78c..5ea654189a9 100644
--- a/tests/ui/coherence/occurs-check/opaques.rs
+++ b/tests/ui/coherence/occurs-check/opaques.rs
@@ -4,14 +4,13 @@
 
 // A regression test for #105787
 #![feature(type_alias_impl_trait)]
-mod defining_scope {
-    use super::*;
-    pub type Alias<T> = impl Sized;
 
-    pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
-        //[next]~^ ERROR type annotations needed
-        x
-    }
+pub type Alias<T> = impl Sized;
+
+#[define_opaque(Alias)]
+pub fn cast<T>(x: Container<Alias<T>, T>) -> Container<T, T> {
+    //[next]~^ ERROR type annotations needed
+    x
 }
 
 struct Container<T: Trait<U>, U> {
@@ -25,12 +24,12 @@ trait Trait<T> {
 impl<T> Trait<T> for T {
     type Assoc = Box<u32>;
 }
-impl<T> Trait<T> for defining_scope::Alias<T> {
+impl<T> Trait<T> for Alias<T> {
     //~^ ERROR conflicting implementations of trait
     type Assoc = usize;
 }
 
 fn main() {
-    let x: Box<u32> = defining_scope::cast::<()>(Container { x: 0 }).x;
+    let x: Box<u32> = cast::<()>(Container { x: 0 }).x;
     println!("{}", *x);
 }
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
index 02e9eb65570..ea91933e694 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.rs
@@ -7,6 +7,7 @@
 
 type Identity<T> = impl Sized;
 
+#[define_opaque(Identity)]
 fn define_identity<T>(x: T) -> Identity<T> {
     x
 }
@@ -16,6 +17,7 @@ impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
 
 type Opaque<T> = impl Sized;
 
+#[define_opaque(Opaque)]
 fn define_local<T>() -> Opaque<T> {
     Local
 }
diff --git a/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
index 57f5bbd2278..6203742b47c 100644
--- a/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
+++ b/tests/ui/coherence/orphan-check-opaque-types-not-covering.stderr
@@ -1,5 +1,5 @@
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:14:6
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:15:6
    |
 LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
    |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
@@ -8,7 +8,7 @@ LL | impl<T> foreign::Trait0<Local, T, ()> for Identity<T> {}
    = note: in this case, 'before' refers to the following order: `impl<..> ForeignTrait<T1, ..., Tn> for T0`, where `T0` is the first and `Tn` is the last
 
 error[E0210]: type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
-  --> $DIR/orphan-check-opaque-types-not-covering.rs:23:6
+  --> $DIR/orphan-check-opaque-types-not-covering.rs:25:6
    |
 LL | impl<T> foreign::Trait1<Local, T> for Opaque<T> {}
    |      ^ type parameter `T` must be covered by another type when it appears before the first local type (`Local`)
diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
index 56b8acbf88c..446112cc617 100644
--- a/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
+++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.rs
@@ -3,14 +3,14 @@
 
 type Foo = impl Sized;
 
-fn with_bound<const N: usize>() -> Foo
+#[define_opaque(Foo)]
+fn with_bound<const N: usize>()
 where
     [u8; (N / 2) as usize]: Sized,
 {
     let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
     //~^ ERROR mismatched types
     //~| ERROR non-primitive cast: `usize` as `Foo`
-    todo!()
 }
 
 fn main() {
diff --git a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
index e9fb8c0f403..9f48a8563c8 100644
--- a/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/opaque_type.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/opaque_type.rs:10:17
+  --> $DIR/opaque_type.rs:11:17
    |
 LL | type Foo = impl Sized;
    |            ---------- the found opaque type
@@ -11,7 +11,7 @@ LL |     let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
            found opaque type `Foo`
 
 error[E0605]: non-primitive cast: `usize` as `Foo`
-  --> $DIR/opaque_type.rs:10:17
+  --> $DIR/opaque_type.rs:11:17
    |
 LL |     let _: [u8; (N / 2) as Foo] = [0; (N / 2) as usize];
    |                 ^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs
new file mode 100644
index 00000000000..bc54aad59ba
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.rs
@@ -0,0 +1,10 @@
+struct Foo<'a>(&'a ());
+
+// We need a lifetime in scope or else we do not write a user type annotation as a fast-path.
+impl<'a> Foo<'a> {
+    fn bar<const V: u8>() {
+        let V;
+        //~^ ERROR constant parameters cannot be referenced in patterns
+    }
+}
+fn main() {}
diff --git a/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr
new file mode 100644
index 00000000000..299ff4165e0
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/bad-param-in-pat.stderr
@@ -0,0 +1,11 @@
+error[E0158]: constant parameters cannot be referenced in patterns
+  --> $DIR/bad-param-in-pat.rs:6:13
+   |
+LL |     fn bar<const V: u8>() {
+   |            ----------- constant defined here
+LL |         let V;
+   |             ^ can't be used in patterns
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
new file mode 100644
index 00000000000..29171c8006a
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.feat.stderr
@@ -0,0 +1,25 @@
+warning: the feature `generic_const_parameter_types` is incomplete and may not be safe to use and/or cause compiler crashes
+  --> $DIR/references-parent-generics.rs:3:27
+   |
+LL | #![cfg_attr(feat, feature(generic_const_parameter_types))]
+   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #137626 <https://github.com/rust-lang/rust/issues/137626> for more information
+   = note: `#[warn(incomplete_features)]` on by default
+
+error: `Self` is forbidden as the type of a const generic parameter
+  --> $DIR/references-parent-generics.rs:7:25
+   |
+LL |     type Assoc<const N: Self>;
+   |                         ^^^^
+   |
+   = note: the only supported types are integers, `bool`, and `char`
+
+error: anonymous constants referencing generics are not yet supported
+  --> $DIR/references-parent-generics.rs:14:21
+   |
+LL |     let x: T::Assoc<3>;
+   |                     ^
+
+error: aborting due to 2 previous errors; 1 warning emitted
+
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
new file mode 100644
index 00000000000..64b41318814
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.nofeat.stderr
@@ -0,0 +1,16 @@
+error: `Self` is forbidden as the type of a const generic parameter
+  --> $DIR/references-parent-generics.rs:7:25
+   |
+LL |     type Assoc<const N: Self>;
+   |                         ^^^^
+   |
+   = note: the only supported types are integers, `bool`, and `char`
+
+error: anonymous constants referencing generics are not yet supported
+  --> $DIR/references-parent-generics.rs:14:21
+   |
+LL |     let x: T::Assoc<3>;
+   |                     ^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
new file mode 100644
index 00000000000..21994eb83b4
--- /dev/null
+++ b/tests/ui/const-generics/generic_const_parameter_types/references-parent-generics.rs
@@ -0,0 +1,18 @@
+//@ revisions: feat nofeat
+
+#![cfg_attr(feat, feature(generic_const_parameter_types))]
+//[feat]~^ WARN the feature `generic_const_parameter_types` is incomplete
+
+trait Foo {
+    type Assoc<const N: Self>;
+    //~^ ERROR `Self` is forbidden as the type of a const generic parameter
+}
+
+fn foo<T: Foo>() {
+    // We used to end up feeding the type of this anon const to be `T`, but the anon const
+    // doesn't inherit the generics of `foo`, which led to index oob errors.
+    let x: T::Assoc<3>;
+    //~^ ERROR anonymous constants referencing generics are not yet supported
+}
+
+fn main() {}
diff --git a/tests/ui/const-generics/opaque_types.rs b/tests/ui/const-generics/opaque_types.rs
index 2c7170c889f..788d7951999 100644
--- a/tests/ui/const-generics/opaque_types.rs
+++ b/tests/ui/const-generics/opaque_types.rs
@@ -1,9 +1,8 @@
 #![feature(type_alias_impl_trait)]
 
 type Foo = impl Sized;
-//~^ ERROR: cycle
-//~| ERROR: cycle
 
+#[define_opaque(Foo)]
 fn foo<const C: Foo>() {}
 //~^ ERROR: `Foo` is forbidden as the type of a const generic parameter
 //~| ERROR: item does not constrain
diff --git a/tests/ui/const-generics/opaque_types.stderr b/tests/ui/const-generics/opaque_types.stderr
index a060488b328..f67e1c8ce69 100644
--- a/tests/ui/const-generics/opaque_types.stderr
+++ b/tests/ui/const-generics/opaque_types.stderr
@@ -1,26 +1,26 @@
 error: `Foo` is forbidden as the type of a const generic parameter
-  --> $DIR/opaque_types.rs:7:17
+  --> $DIR/opaque_types.rs:6:17
    |
 LL | fn foo<const C: Foo>() {}
    |                 ^^^
    |
    = note: the only supported types are integers, `bool`, and `char`
 
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/opaque_types.rs:7:4
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/opaque_types.rs:6:4
    |
 LL | fn foo<const C: Foo>() {}
    |    ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/opaque_types.rs:3:12
    |
 LL | type Foo = impl Sized;
    |            ^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/opaque_types.rs:12:11
+  --> $DIR/opaque_types.rs:11:11
    |
 LL | type Foo = impl Sized;
    |            ---------- the expected opaque type
@@ -31,106 +31,6 @@ LL |     foo::<42>();
    = note: expected opaque type `Foo`
                      found type `{integer}`
 
-error[E0391]: cycle detected when computing type of `Foo::{opaque#0}`
-  --> $DIR/opaque_types.rs:3:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires computing type of opaque `Foo::{opaque#0}`...
-  --> $DIR/opaque_types.rs:3:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-note: ...which requires type-checking `main`...
-  --> $DIR/opaque_types.rs:11:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-note: ...which requires evaluating type-level constant...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires const-evaluating + checking `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires caching mir of `main::{constant#0}` for CTFE...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires elaborating drops for `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-   = note: ...which requires normalizing `Foo`...
-   = note: ...which again requires computing type of `Foo::{opaque#0}`, completing the cycle
-note: cycle used when checking that `Foo::{opaque#0}` is well-formed
-  --> $DIR/opaque_types.rs:3:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error[E0391]: cycle detected when computing type of opaque `Foo::{opaque#0}`
-  --> $DIR/opaque_types.rs:3:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   |
-note: ...which requires type-checking `main`...
-  --> $DIR/opaque_types.rs:11:1
-   |
-LL | fn main() {
-   | ^^^^^^^^^
-note: ...which requires evaluating type-level constant...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires const-evaluating + checking `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires caching mir of `main::{constant#0}` for CTFE...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires elaborating drops for `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires borrow-checking `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires promoting constants in MIR for `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-note: ...which requires const checking `main::{constant#0}`...
-  --> $DIR/opaque_types.rs:12:11
-   |
-LL |     foo::<42>();
-   |           ^^
-   = note: ...which again requires computing type of opaque `Foo::{opaque#0}`, completing the cycle
-note: cycle used when computing type of `Foo::{opaque#0}`
-  --> $DIR/opaque_types.rs:3:12
-   |
-LL | type Foo = impl Sized;
-   |            ^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0308, E0391.
-For more information about an error, try `rustc --explain E0308`.
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/const-generics/opaque_types2.rs b/tests/ui/const-generics/opaque_types2.rs
index fd57438bb61..69f813cf84a 100644
--- a/tests/ui/const-generics/opaque_types2.rs
+++ b/tests/ui/const-generics/opaque_types2.rs
@@ -4,13 +4,14 @@ type Foo = impl Sized;
 
 fn foo<const C: u32>() {}
 
-const C: Foo = 42;
+#[define_opaque(Foo)]
+const fn baz() -> Foo {
+    42
+}
 
-fn bar()
-where
-    Foo:,
-{
-    foo::<C>();
+#[define_opaque(Foo)]
+fn bar() {
+    foo::<{ baz() }>();
     //~^ ERROR: mismatched types
 }
 
diff --git a/tests/ui/const-generics/opaque_types2.stderr b/tests/ui/const-generics/opaque_types2.stderr
index 2fb1669b7bf..98d96c3ccee 100644
--- a/tests/ui/const-generics/opaque_types2.stderr
+++ b/tests/ui/const-generics/opaque_types2.stderr
@@ -1,11 +1,11 @@
 error[E0308]: mismatched types
-  --> $DIR/opaque_types2.rs:13:11
+  --> $DIR/opaque_types2.rs:14:13
    |
 LL | type Foo = impl Sized;
    |            ---------- the found opaque type
 ...
-LL |     foo::<C>();
-   |           ^ expected `u32`, found opaque type
+LL |     foo::<{ baz() }>();
+   |             ^^^^^ expected `u32`, found opaque type
    |
    = note:     expected type `u32`
            found opaque type `Foo`
diff --git a/tests/ui/consts/const-eval/ice-unhandled-type-122191.rs b/tests/ui/consts/const-eval/ice-unhandled-type-122191.rs
index a92b99976e2..75bd6f7a123 100644
--- a/tests/ui/consts/const-eval/ice-unhandled-type-122191.rs
+++ b/tests/ui/consts/const-eval/ice-unhandled-type-122191.rs
@@ -3,14 +3,20 @@ type Foo = impl Send;
 
 struct A;
 
-const VALUE: Foo = value();
-//~^ ERROR cannot find function `value` in this scope
+#[define_opaque(Foo)]
+//~^ ERROR unstable library feature
+const fn foo() -> Foo {
+    value()
+    //~^ ERROR cannot find function `value` in this scope
+}
+
+const VALUE: Foo = foo();
 
 fn test() {
     match VALUE {
         0 | 0 => {}
-//~^ ERROR mismatched types
-//~| ERROR mismatched types
+        //~^ ERROR mismatched types
+        //~| ERROR mismatched types
         _ => (),
     }
 }
diff --git a/tests/ui/consts/const-eval/ice-unhandled-type-122191.stderr b/tests/ui/consts/const-eval/ice-unhandled-type-122191.stderr
index daf0ccaa776..bcb6a80a8f2 100644
--- a/tests/ui/consts/const-eval/ice-unhandled-type-122191.stderr
+++ b/tests/ui/consts/const-eval/ice-unhandled-type-122191.stderr
@@ -1,3 +1,13 @@
+error[E0658]: use of unstable library feature `type_alias_impl_trait`: `type_alias_impl_trait` has open design concerns
+  --> $DIR/ice-unhandled-type-122191.rs:6:3
+   |
+LL | #[define_opaque(Foo)]
+   |   ^^^^^^^^^^^^^
+   |
+   = note: see issue #63063 <https://github.com/rust-lang/rust/issues/63063> for more information
+   = help: add `#![feature(type_alias_impl_trait)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
 error[E0658]: `impl Trait` in type aliases is unstable
   --> $DIR/ice-unhandled-type-122191.rs:1:12
    |
@@ -9,13 +19,16 @@ LL | type Foo = impl Send;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0425]: cannot find function `value` in this scope
-  --> $DIR/ice-unhandled-type-122191.rs:6:20
+  --> $DIR/ice-unhandled-type-122191.rs:9:5
    |
-LL | const VALUE: Foo = value();
-   |                    ^^^^^ not found in this scope
+LL |     value()
+   |     ^^^^^ help: a constant with a similar name exists: `VALUE`
+...
+LL | const VALUE: Foo = foo();
+   | ------------------------- similarly named constant `VALUE` defined here
 
 error[E0308]: mismatched types
-  --> $DIR/ice-unhandled-type-122191.rs:11:9
+  --> $DIR/ice-unhandled-type-122191.rs:17:9
    |
 LL | type Foo = impl Send;
    |            --------- the expected opaque type
@@ -27,14 +40,14 @@ LL |         0 | 0 => {}
    |
    = note: expected opaque type `Foo`
                      found type `{integer}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/ice-unhandled-type-122191.rs:9:4
+note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
+  --> $DIR/ice-unhandled-type-122191.rs:15:4
    |
 LL | fn test() {
    |    ^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/ice-unhandled-type-122191.rs:11:13
+  --> $DIR/ice-unhandled-type-122191.rs:17:13
    |
 LL | type Foo = impl Send;
    |            --------- the expected opaque type
@@ -46,13 +59,13 @@ LL |         0 | 0 => {}
    |
    = note: expected opaque type `Foo`
                      found type `{integer}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/ice-unhandled-type-122191.rs:9:4
+note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
+  --> $DIR/ice-unhandled-type-122191.rs:15:4
    |
 LL | fn test() {
    |    ^^^^
 
-error: aborting due to 4 previous errors
+error: aborting due to 5 previous errors
 
 Some errors have detailed explanations: E0308, E0425, E0658.
 For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/consts/const-promoted-opaque.atomic.stderr b/tests/ui/consts/const-promoted-opaque.atomic.stderr
index b9d5cbf801a..9c0c969d586 100644
--- a/tests/ui/consts/const-promoted-opaque.atomic.stderr
+++ b/tests/ui/consts/const-promoted-opaque.atomic.stderr
@@ -1,5 +1,5 @@
-error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time
-  --> $DIR/const-promoted-opaque.rs:28:26
+error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
+  --> $DIR/const-promoted-opaque.rs:32:26
    |
 LL |     let _: &'static _ = &FOO;
    |                          ^^^ the destructor for this type cannot be evaluated in constants
@@ -8,13 +8,13 @@ LL | };
    | - value is dropped here
 
 error[E0492]: constants cannot refer to interior mutable data
-  --> $DIR/const-promoted-opaque.rs:32:19
+  --> $DIR/const-promoted-opaque.rs:36:19
    |
 LL | const BAZ: &Foo = &FOO;
    |                   ^^^^ this borrow of an interior mutable value may end up in the final value
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-promoted-opaque.rs:36:26
+  --> $DIR/const-promoted-opaque.rs:40:26
    |
 LL |     let _: &'static _ = &FOO;
    |            ----------    ^^^ creates a temporary value which is freed while still in use
diff --git a/tests/ui/consts/const-promoted-opaque.rs b/tests/ui/consts/const-promoted-opaque.rs
index bb33e92778a..188dacd1003 100644
--- a/tests/ui/consts/const-promoted-opaque.rs
+++ b/tests/ui/consts/const-promoted-opaque.rs
@@ -8,25 +8,29 @@
 //! hidden type of the opaque type. Thus we ended up relying on the
 //! result of our analysis to compute the result of our analysis.
 
-//@[unit] check-pass
+pub type Foo = impl Sized;
 
-mod helper {
-    pub type Foo = impl Sized;
+#[cfg(string)]
+#[define_opaque(Foo)]
+const fn foo() -> Foo {
+    String::new()
+}
 
-    #[cfg(string)]
-    pub const FOO: Foo = String::new();
+#[cfg(atomic)]
+#[define_opaque(Foo)]
+const fn foo() -> Foo {
+    std::sync::atomic::AtomicU8::new(42)
+}
 
-    #[cfg(atomic)]
-    pub const FOO: Foo = std::sync::atomic::AtomicU8::new(42);
+#[cfg(unit)]
+#[define_opaque(Foo)]
+const fn foo() -> Foo {}
 
-    #[cfg(unit)]
-    pub const FOO: Foo = ();
-}
-use helper::*;
+const FOO: Foo = foo();
 
 const BAR: () = {
     let _: &'static _ = &FOO;
-    //[string,atomic]~^ ERROR: destructor of `helper::Foo` cannot be evaluated at compile-time
+    //[string,atomic,unit]~^ ERROR: destructor of `Foo` cannot be evaluated at compile-time
 };
 
 const BAZ: &Foo = &FOO;
@@ -34,5 +38,5 @@ const BAZ: &Foo = &FOO;
 
 fn main() {
     let _: &'static _ = &FOO;
-    //[string,atomic]~^ ERROR: temporary value dropped while borrowed
+    //[string,atomic,unit]~^ ERROR: temporary value dropped while borrowed
 }
diff --git a/tests/ui/consts/const-promoted-opaque.string.stderr b/tests/ui/consts/const-promoted-opaque.string.stderr
index 33e5f426448..847a466f21c 100644
--- a/tests/ui/consts/const-promoted-opaque.string.stderr
+++ b/tests/ui/consts/const-promoted-opaque.string.stderr
@@ -1,5 +1,5 @@
-error[E0493]: destructor of `helper::Foo` cannot be evaluated at compile-time
-  --> $DIR/const-promoted-opaque.rs:28:26
+error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
+  --> $DIR/const-promoted-opaque.rs:32:26
    |
 LL |     let _: &'static _ = &FOO;
    |                          ^^^ the destructor for this type cannot be evaluated in constants
@@ -8,7 +8,7 @@ LL | };
    | - value is dropped here
 
 error[E0716]: temporary value dropped while borrowed
-  --> $DIR/const-promoted-opaque.rs:36:26
+  --> $DIR/const-promoted-opaque.rs:40:26
    |
 LL |     let _: &'static _ = &FOO;
    |            ----------    ^^^ creates a temporary value which is freed while still in use
diff --git a/tests/ui/consts/const-promoted-opaque.unit.stderr b/tests/ui/consts/const-promoted-opaque.unit.stderr
new file mode 100644
index 00000000000..847a466f21c
--- /dev/null
+++ b/tests/ui/consts/const-promoted-opaque.unit.stderr
@@ -0,0 +1,24 @@
+error[E0493]: destructor of `Foo` cannot be evaluated at compile-time
+  --> $DIR/const-promoted-opaque.rs:32:26
+   |
+LL |     let _: &'static _ = &FOO;
+   |                          ^^^ the destructor for this type cannot be evaluated in constants
+LL |
+LL | };
+   | - value is dropped here
+
+error[E0716]: temporary value dropped while borrowed
+  --> $DIR/const-promoted-opaque.rs:40:26
+   |
+LL |     let _: &'static _ = &FOO;
+   |            ----------    ^^^ creates a temporary value which is freed while still in use
+   |            |
+   |            type annotation requires that borrow lasts for `'static`
+LL |
+LL | }
+   | - temporary value is freed at the end of this statement
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0493, E0716.
+For more information about an error, try `rustc --explain E0493`.
diff --git a/tests/ui/consts/large_const_alloc.rs b/tests/ui/consts/large_const_alloc.rs
index 14edc1bb696..3573a018630 100644
--- a/tests/ui/consts/large_const_alloc.rs
+++ b/tests/ui/consts/large_const_alloc.rs
@@ -2,6 +2,9 @@
 // on 32bit and 16bit platforms it is plausible that the maximum allocation size will succeed
 // FIXME (#135952) In some cases on AArch64 Linux the diagnostic does not trigger
 //@ ignore-aarch64-unknown-linux-gnu
+// AIX will allow the allocation to go through, and get SIGKILL when zero initializing
+// the overcommitted page.
+//@ ignore-aix
 
 const FOO: () = {
     // 128 TiB, unlikely anyone has that much RAM
diff --git a/tests/ui/consts/large_const_alloc.stderr b/tests/ui/consts/large_const_alloc.stderr
index fa7d5977a95..f3f3de7af63 100644
--- a/tests/ui/consts/large_const_alloc.stderr
+++ b/tests/ui/consts/large_const_alloc.stderr
@@ -1,11 +1,11 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/large_const_alloc.rs:8:13
+  --> $DIR/large_const_alloc.rs:11:13
    |
 LL |     let x = [0_u8; (1 << 47) - 1];
    |             ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
 
 error[E0080]: could not evaluate static initializer
-  --> $DIR/large_const_alloc.rs:13:13
+  --> $DIR/large_const_alloc.rs:16:13
    |
 LL |     let x = [0_u8; (1 << 47) - 1];
    |             ^^^^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
index 53618e2e86a..75765596fa1 100644
--- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.rs
@@ -5,6 +5,9 @@
 //@ only-64bit
 // FIXME (#135952) In some cases on AArch64 Linux the diagnostic does not trigger
 //@ ignore-aarch64-unknown-linux-gnu
+// AIX will allow the allocation to go through, and get SIGKILL when zero initializing
+// the overcommitted page.
+//@ ignore-aix
 
 pub struct Data([u8; (1 << 47) - 1]);
 const _: &'static Data = &Data([0; (1 << 47) - 1]);
diff --git a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
index aac805dbd8c..02180c1e4c6 100644
--- a/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
+++ b/tests/ui/consts/promoted_running_out_of_memory_issue-130687.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/promoted_running_out_of_memory_issue-130687.rs:10:32
+  --> $DIR/promoted_running_out_of_memory_issue-130687.rs:13:32
    |
 LL | const _: &'static Data = &Data([0; (1 << 47) - 1]);
    |                                ^^^^^^^^^^^^^^^^^^ tried to allocate more memory than available to compiler
diff --git a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs
index 795e021ceb0..f333f3462c7 100644
--- a/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs
+++ b/tests/ui/consts/required-consts/collect-in-dead-fn-behind-opaque-type.rs
@@ -20,6 +20,7 @@ mod m {
         }
     }
 
+    #[define_opaque(NotCalledFn)]
     fn mk_not_called() -> NotCalledFn {
         not_called::<i32>
     }
diff --git a/tests/ui/coroutine/layout-error.rs b/tests/ui/coroutine/layout-error.rs
index 3e26cf17d29..6cf32134025 100644
--- a/tests/ui/coroutine/layout-error.rs
+++ b/tests/ui/coroutine/layout-error.rs
@@ -16,22 +16,20 @@ impl<F: Future> Task<F> {
     }
 }
 
-mod helper {
-    use super::*;
-    pub type F = impl Future;
-    fn foo()
-    where
-        F:,
-    {
-        async fn cb() {
-            let a = Foo; //~ ERROR cannot find value `Foo` in this scope
-        }
-
-        Task::spawn(&POOL, || cb());
+pub type F = impl Future;
+#[define_opaque(F)]
+fn foo()
+where
+    F:,
+{
+    async fn cb() {
+        let a = Foo; //~ ERROR cannot find value `Foo` in this scope
     }
+
+    Task::spawn(&POOL, || cb());
 }
 
 // Check that statics are inhabited computes they layout.
-static POOL: Task<helper::F> = Task::new();
+static POOL: Task<F> = Task::new();
 
 fn main() {}
diff --git a/tests/ui/coroutine/layout-error.stderr b/tests/ui/coroutine/layout-error.stderr
index ceadb62c999..91e35216435 100644
--- a/tests/ui/coroutine/layout-error.stderr
+++ b/tests/ui/coroutine/layout-error.stderr
@@ -1,8 +1,8 @@
 error[E0425]: cannot find value `Foo` in this scope
-  --> $DIR/layout-error.rs:27:21
+  --> $DIR/layout-error.rs:26:17
    |
-LL |             let a = Foo;
-   |                     ^^^ not found in this scope
+LL |         let a = Foo;
+   |                 ^^^ not found in this scope
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coroutine/metadata-sufficient-for-layout.rs b/tests/ui/coroutine/metadata-sufficient-for-layout.rs
index 9c3a7e4378e..b7d8575c761 100644
--- a/tests/ui/coroutine/metadata-sufficient-for-layout.rs
+++ b/tests/ui/coroutine/metadata-sufficient-for-layout.rs
@@ -15,6 +15,7 @@ mod helper {
     use std::ops::Coroutine;
     pub type F = impl Coroutine<(), Yield = (), Return = ()>;
 
+    #[define_opaque(F)]
     fn f() -> F {
         metadata_sufficient_for_layout::g()
     }
diff --git a/tests/ui/drop/drop_elaboration_with_errors.rs b/tests/ui/drop/drop_elaboration_with_errors.rs
index 35d05e6cf64..6b686e49d45 100644
--- a/tests/ui/drop/drop_elaboration_with_errors.rs
+++ b/tests/ui/drop/drop_elaboration_with_errors.rs
@@ -10,6 +10,7 @@ struct Foo {
 
 type Tait = impl Sized;
 
+#[define_opaque(Tait)]
 fn ice_cold(beverage: Tait) {
     let Foo { field } = beverage;
     _ = field;
diff --git a/tests/ui/drop/drop_elaboration_with_errors.stderr b/tests/ui/drop/drop_elaboration_with_errors.stderr
index bec229631e1..ea2c9b949e4 100644
--- a/tests/ui/drop/drop_elaboration_with_errors.stderr
+++ b/tests/ui/drop/drop_elaboration_with_errors.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/drop_elaboration_with_errors.rs:19:5
+  --> $DIR/drop_elaboration_with_errors.rs:20:5
    |
 LL | fn main() {
    |          - expected `()` because of default return type
diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs
index 5d607d82ea1..cc23c2c5055 100644
--- a/tests/ui/dyn-keyword/dyn-2021-edition-error.rs
+++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.rs
@@ -7,6 +7,12 @@ fn function(x: &SomeTrait, y: Box<SomeTrait>) {
     //~^ ERROR expected a type, found a trait
 }
 
+// Regression test for <https://github.com/rust-lang/rust/issues/138211>.
+extern "C" {
+    fn foo() -> *const SomeTrait;
+    //~^ ERROR expected a type, found a trait
+}
+
 trait SomeTrait {}
 
 fn main() {}
diff --git a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
index 8c4b809e76b..b1d6385bde9 100644
--- a/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
+++ b/tests/ui/dyn-keyword/dyn-2021-edition-error.stderr
@@ -30,6 +30,17 @@ LL | fn function(x: &SomeTrait, y: Box<dyn SomeTrait>) {
    |                                   +++
 
 error[E0782]: expected a type, found a trait
+  --> $DIR/dyn-2021-edition-error.rs:12:24
+   |
+LL |     fn foo() -> *const SomeTrait;
+   |                        ^^^^^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL |     fn foo() -> *const dyn SomeTrait;
+   |                        +++
+
+error[E0782]: expected a type, found a trait
   --> $DIR/dyn-2021-edition-error.rs:6:14
    |
 LL |     let _x: &SomeTrait = todo!();
@@ -40,6 +51,6 @@ help: you can add the `dyn` keyword if you want a trait object
 LL |     let _x: &dyn SomeTrait = todo!();
    |              +++
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0782`.
diff --git a/tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.rs b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.rs
index 9963b5be4f2..4d573b90d60 100644
--- a/tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.rs
+++ b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.rs
@@ -13,7 +13,6 @@ struct Foo2 {
     //~^ ERROR expected a type, found a trait
 }
 
-
 enum Enum1 {
     A(Trait),
     //~^ ERROR expected a type, found a trait
@@ -26,5 +25,17 @@ enum Enum2 {
     //~^ ERROR expected a type, found a trait
 }
 
+// Regression test for <https://github.com/rust-lang/rust/issues/138229>.
+pub struct InWhereClause
+where
+    Trait:, {}
+//~^ ERROR expected a type, found a trait
+
+struct HasGenerics<T> {
+    f: Trait,
+    //~^ ERROR expected a type, found a trait
+    t: T,
+}
+
 
 fn main() {}
diff --git a/tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.stderr b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr
index 433196919ca..9584147bbc7 100644
--- a/tests/ui/suggestions/suggest-struct-or-union-add-generic-impl-trait.stderr
+++ b/tests/ui/dyn-keyword/suggest-struct-or-union-add-generic-impl-trait.stderr
@@ -22,7 +22,7 @@ LL |     b: dyn Trait,
    |        +++
 
 error[E0782]: expected a type, found a trait
-  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:18:7
+  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:17:7
    |
 LL |     A(Trait),
    |       ^^^^^
@@ -34,7 +34,7 @@ LL ~     A(T),
    |
 
 error[E0782]: expected a type, found a trait
-  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:25:7
+  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:24:7
    |
 LL |     B(Trait),
    |       ^^^^^
@@ -46,6 +46,29 @@ LL |     A(u32),
 LL ~     B(T),
    |
 
-error: aborting due to 4 previous errors
+error[E0782]: expected a type, found a trait
+  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:35:8
+   |
+LL |     f: Trait,
+   |        ^^^^^
+   |
+help: you might be missing a type parameter
+   |
+LL ~ struct HasGenerics<T, U: Trait> {
+LL ~     f: U,
+   |
+
+error[E0782]: expected a type, found a trait
+  --> $DIR/suggest-struct-or-union-add-generic-impl-trait.rs:31:5
+   |
+LL |     Trait:, {}
+   |     ^^^^^
+   |
+help: you can add the `dyn` keyword if you want a trait object
+   |
+LL |     dyn Trait:, {}
+   |     +++
+
+error: aborting due to 6 previous errors
 
 For more information about this error, try `rustc --explain E0782`.
diff --git a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
index d0be240e07b..4e6be341ef0 100644
--- a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
+++ b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.rs
@@ -4,7 +4,11 @@ pub mod foo {
     type MainFn = impl Fn();
 
     fn bar() {}
-    pub const BAR: MainFn = bar;
+    #[define_opaque(MainFn)]
+    const fn def() -> MainFn {
+        bar
+    }
+    pub const BAR: MainFn = def();
 }
 
 use foo::BAR as main; //~ ERROR `main` function not found in crate
diff --git a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
index 50e4cd7d39f..375b3a53030 100644
--- a/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
+++ b/tests/ui/entry-point/imported_main_const_fn_item_type_forbidden.stderr
@@ -1,5 +1,5 @@
 error[E0601]: `main` function not found in crate `imported_main_const_fn_item_type_forbidden`
-  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:10:22
+  --> $DIR/imported_main_const_fn_item_type_forbidden.rs:14:22
    |
 LL | use foo::BAR as main;
    |     ---------------- ^ consider adding a `main` function to `$DIR/imported_main_const_fn_item_type_forbidden.rs`
diff --git a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
index 6d17f5e837d..ec70a20844a 100644
--- a/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
+++ b/tests/ui/feature-gates/feature-gate-type_alias_impl_trait.rs
@@ -5,27 +5,32 @@ use std::fmt::Debug;
 type Foo = impl Debug;
 
 struct Bar(Foo);
+#[define_opaque(Foo)]
 fn define() -> Bar {
     Bar(42)
 }
 
 type Foo2 = impl Debug;
 
-fn define2(_: Foo2) {
+#[define_opaque(Foo2)]
+fn define2() {
     let x = || -> Foo2 { 42 };
 }
 
 type Foo3 = impl Debug;
 
+#[define_opaque(Foo3)]
 fn define3(x: Foo3) {
     let y: i32 = x;
 }
-fn define3_1(_: Foo3) {
+#[define_opaque(Foo3)]
+fn define3_1() {
     define3(42)
 }
 
 type Foo4 = impl Debug;
 
+#[define_opaque(Foo4)]
 fn define4(_: Foo4) {
     let y: Foo4 = 42;
 }
diff --git a/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr b/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr
index bc8edd847cc..30e36acb871 100644
--- a/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr
+++ b/tests/ui/feature-gates/feature-gate-unqualified-local-imports.stderr
@@ -5,6 +5,7 @@ LL | #![allow(unqualified_local_imports)]
    |          ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: the `unqualified_local_imports` lint is unstable
+   = note: see issue #138299 <https://github.com/rust-lang/rust/issues/138299> for more information
    = help: add `#![feature(unqualified_local_imports)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
    = note: `#[warn(unknown_lints)]` on by default
diff --git a/tests/ui/fn/fn_def_opaque_coercion.rs b/tests/ui/fn/fn_def_opaque_coercion.rs
index 0a8810cf4f8..8235878c59d 100644
--- a/tests/ui/fn/fn_def_opaque_coercion.rs
+++ b/tests/ui/fn/fn_def_opaque_coercion.rs
@@ -11,6 +11,7 @@ fn foo<T>(t: T) -> T {
 
 type F = impl Sized;
 
+#[define_opaque(F)]
 fn f(a: F) {
     let mut x = foo::<F>;
     x = foo::<()>;
@@ -20,6 +21,7 @@ fn f(a: F) {
 
 type G = impl Sized;
 
+#[define_opaque(G)]
 fn g(a: G) {
     let x = foo::<()>;
     let _: () = x(a);
@@ -27,6 +29,7 @@ fn g(a: G) {
 
 type H = impl Sized;
 
+#[define_opaque(H)]
 fn h(a: H) {
     let x = foo::<H>;
     let _: H = x(());
@@ -34,6 +37,7 @@ fn h(a: H) {
 
 type I = impl Sized;
 
+#[define_opaque(I)]
 fn i(a: I) {
     let mut x = foo::<()>;
     x = foo::<I>;
@@ -43,6 +47,7 @@ fn i(a: I) {
 
 type J = impl Sized;
 
+#[define_opaque(J)]
 fn j(a: J) {
     let x = match true {
         true => foo::<J>,
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs
index 5250e3a3d93..e090b7039b8 100644
--- a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs
+++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.rs
@@ -13,6 +13,7 @@ fn bar<T>(t: T) -> T {
 
 type F = impl Sized;
 
+#[define_opaque(F)]
 fn f(a: F) {
     let mut x = bar::<F>;
     x = foo::<()>; //~ ERROR: mismatched types
@@ -22,6 +23,7 @@ fn f(a: F) {
 
 type I = impl Sized;
 
+#[define_opaque(I)]
 fn i(a: I) {
     let mut x = bar::<()>;
     x = foo::<I>; //~ ERROR: mismatched types
@@ -31,6 +33,7 @@ fn i(a: I) {
 
 type J = impl Sized;
 
+#[define_opaque(J)]
 fn j(a: J) {
     let x = match true {
         true => bar::<J>,
diff --git a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
index 5000601e90f..4a0991d0eb3 100644
--- a/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
+++ b/tests/ui/fn/fn_def_opaque_coercion_to_fn_ptr.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:18:9
+  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:19:9
    |
 LL | type F = impl Sized;
    |          ---------- the expected opaque type
@@ -13,7 +13,7 @@ LL |     x = foo::<()>;
               found fn item `fn(()) -> () {foo::<()>}`
 
 error[E0308]: mismatched types
-  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:27:9
+  --> $DIR/fn_def_opaque_coercion_to_fn_ptr.rs:29:9
    |
 LL | fn foo<T>(t: T) -> T {
    | -------------------- function `foo` defined here
diff --git a/tests/ui/generic-associated-types/issue-87258_b.rs b/tests/ui/generic-associated-types/issue-87258_b.rs
index 7b7610b21c7..84c7182cdcb 100644
--- a/tests/ui/generic-associated-types/issue-87258_b.rs
+++ b/tests/ui/generic-associated-types/issue-87258_b.rs
@@ -18,6 +18,7 @@ type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
 
 impl<'c, S: Trait2> Trait2 for &'c mut S {
     type FooFuture<'a> = Helper<'c, 'a, S>;
+    #[define_opaque(Helper)]
     fn foo<'a>() -> Self::FooFuture<'a> {
         Struct(unimplemented!())
     }
diff --git a/tests/ui/generic-associated-types/issue-87258_b.stderr b/tests/ui/generic-associated-types/issue-87258_b.stderr
index 73f984dcfb8..906ce1f50da 100644
--- a/tests/ui/generic-associated-types/issue-87258_b.stderr
+++ b/tests/ui/generic-associated-types/issue-87258_b.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
 LL | type Helper<'xenon, 'yttrium, KABOOM: Trait2> = impl Trait1;
    |                                                 ^^^^^^^^^^^
    |
-   = note: `Helper` must be used in combination with a concrete type within the same module
+   = note: `Helper` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/generic-associated-types/issue-88287.rs b/tests/ui/generic-associated-types/issue-88287.rs
index 5d64ad8eeae..ce0b9827d11 100644
--- a/tests/ui/generic-associated-types/issue-88287.rs
+++ b/tests/ui/generic-associated-types/issue-88287.rs
@@ -30,6 +30,7 @@ where
         A: SearchableResource<B> + ?Sized + 'f,
         Self: 'f;
 
+    #[define_opaque(SearchFutureTy)]
     fn search<'c>(&'c self, _client: &'c ()) -> Self::Future<'c, Self, Criteria> {
         async move { todo!() }
         //~^ ERROR: the size for values of type `A` cannot be known at compilation time
diff --git a/tests/ui/generic-associated-types/issue-88287.stderr b/tests/ui/generic-associated-types/issue-88287.stderr
index 54ecc5cfcd8..71cd6677e63 100644
--- a/tests/ui/generic-associated-types/issue-88287.stderr
+++ b/tests/ui/generic-associated-types/issue-88287.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `A` cannot be known at compilation time
-  --> $DIR/issue-88287.rs:34:9
+  --> $DIR/issue-88287.rs:35:9
    |
 LL | type SearchFutureTy<'f, A, B: 'f>
    |                         - this type parameter needs to be `Sized`
diff --git a/tests/ui/generic-associated-types/issue-90014-tait.stderr b/tests/ui/generic-associated-types/issue-90014-tait.stderr
index 09c2903ab02..fffe5b93e5a 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait.stderr
+++ b/tests/ui/generic-associated-types/issue-90014-tait.stderr
@@ -1,3 +1,11 @@
+error: unconstrained opaque type
+  --> $DIR/issue-90014-tait.rs:15:20
+   |
+LL |     type Fut<'a> = impl Future<Output = ()>;
+   |                    ^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Fut` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
   --> $DIR/issue-90014-tait.rs:18:9
    |
@@ -11,12 +19,7 @@ LL |         async { () }
    |
    = note: expected opaque type `Foo<'_>::Fut<'a>`
             found `async` block `{async block@$DIR/issue-90014-tait.rs:18:9: 18:14}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-90014-tait.rs:17:8
-   |
-LL |     fn make_fut<'a>(&'a self) -> Self::Fut<'a> {
-   |        ^^^^^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.rs b/tests/ui/generic-associated-types/issue-90014-tait2.rs
index 3f7a9ff63c3..472a0d500c8 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait2.rs
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.rs
@@ -20,6 +20,7 @@ impl<'x, T: 'x> Trait<'x> for (T,) {
 }
 
 impl Foo<'_> {
+    #[define_opaque(Fut)]
     fn make_fut(&self) -> Box<dyn for<'a> Trait<'a, Thing = Fut<'a>>> {
         Box::new((async { () },))
         //~^ ERROR expected generic lifetime parameter, found `'a`
diff --git a/tests/ui/generic-associated-types/issue-90014-tait2.stderr b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
index aa427d42649..bf944aac797 100644
--- a/tests/ui/generic-associated-types/issue-90014-tait2.stderr
+++ b/tests/ui/generic-associated-types/issue-90014-tait2.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/issue-90014-tait2.rs:24:9
+  --> $DIR/issue-90014-tait2.rs:25:9
    |
 LL | type Fut<'a> = impl Future<Output = ()>;
    |          -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
index 57cbe169118..34617448a69 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.old.stderr
@@ -1,18 +1,18 @@
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:16:4
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:17:4
    |
 LL | fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
    |    ^^^^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/norm-before-method-resolution-opaque-type.rs:14:12
    |
 LL | type Foo = impl Sized;
    |            ^^^^^^^^^^
 
 error[E0507]: cannot move out of `*x` which is behind a shared reference
-  --> $DIR/norm-before-method-resolution-opaque-type.rs:22:13
+  --> $DIR/norm-before-method-resolution-opaque-type.rs:23:13
    |
 LL |     let x = *x;
    |             ^^ move occurs because `*x` has type `<X as Trait<'_>>::Out<Foo>`, which does not implement the `Copy` trait
diff --git a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
index 43207d89276..bb663c82abb 100644
--- a/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
+++ b/tests/ui/higher-ranked/trait-bounds/normalize-under-binder/norm-before-method-resolution-opaque-type.rs
@@ -13,6 +13,7 @@ impl<'a, T> Trait<'a> for T {
 
 type Foo = impl Sized;
 
+#[define_opaque(Foo)]
 fn weird_bound<X>(x: &<X as Trait<'static>>::Out<Foo>) -> X
 //[old]~^ ERROR: item does not constrain
 where
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs
index 65e90c1ca53..f703269a438 100644
--- a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.rs
@@ -8,31 +8,29 @@ impl<T> Captures<'_> for T {}
 pub struct MyTy<'a, 'b>(Option<*mut &'a &'b ()>);
 unsafe impl Send for MyTy<'_, 'static> {}
 
-pub mod step1 {
-    use super::*;
-    pub type Step1<'a, 'b: 'a> = impl Sized + Captures<'b> + 'a;
-    pub fn step1<'a, 'b: 'a>() -> Step1<'a, 'b> {
-        MyTy::<'a, 'b>(None)
-    }
+pub type Step1<'a, 'b: 'a> = impl Sized + Captures<'b> + 'a;
+#[define_opaque(Step1)]
+pub fn step1<'a, 'b: 'a>() -> Step1<'a, 'b> {
+    MyTy::<'a, 'b>(None)
 }
 
-pub mod step2 {
-    pub type Step2<'a> = impl Send + 'a;
-
-    // Although `Step2` is WF at the definition site, it's not WF in its
-    // declaration site (above). We check this in `check_opaque_meets_bounds`,
-    // which must remain sound.
-    pub fn step2<'a, 'b: 'a>() -> Step2<'a>
-        where crate::step1::Step1<'a, 'b>: Send
-    {
-        crate::step1::step1::<'a, 'b>()
-        //~^ ERROR hidden type for `Step2<'a>` captures lifetime that does not appear in bounds
-    }
+pub type Step2<'a> = impl Send + 'a;
+
+// Although `Step2` is WF at the definition site, it's not WF in its
+// declaration site (above). We check this in `check_opaque_meets_bounds`,
+// which must remain sound.
+#[define_opaque(Step2)]
+pub fn step2<'a, 'b: 'a>() -> Step2<'a>
+where
+    Step1<'a, 'b>: Send,
+{
+    step1::<'a, 'b>()
+    //~^ ERROR hidden type for `Step2<'a>` captures lifetime that does not appear in bounds
 }
 
 fn step3<'a, 'b>() {
     fn is_send<T: Send>() {}
-    is_send::<crate::step2::Step2::<'a>>();
+    is_send::<Step2<'a>>();
 }
 
 fn main() {}
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr
index 58d7f9959d3..ce797ccf40c 100644
--- a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness-2.stderr
@@ -1,14 +1,14 @@
 error[E0700]: hidden type for `Step2<'a>` captures lifetime that does not appear in bounds
-  --> $DIR/tait-hidden-erased-unsoundness-2.rs:28:9
+  --> $DIR/tait-hidden-erased-unsoundness-2.rs:27:5
    |
-LL |     pub type Step2<'a> = impl Send + 'a;
-   |                          -------------- opaque type defined here
+LL | pub type Step2<'a> = impl Send + 'a;
+   |                      -------------- opaque type defined here
 ...
-LL |     pub fn step2<'a, 'b: 'a>() -> Step2<'a>
-   |                      -- hidden type `Step1<'a, 'b>` captures the lifetime `'b` as defined here
+LL | pub fn step2<'a, 'b: 'a>() -> Step2<'a>
+   |                  -- hidden type `Step1<'a, 'b>` captures the lifetime `'b` as defined here
 ...
-LL |         crate::step1::step1::<'a, 'b>()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL |     step1::<'a, 'b>()
+   |     ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs
index 40efd941e33..ba22f16003c 100644
--- a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.rs
@@ -12,16 +12,15 @@ fn step1<'a, 'b: 'a>() -> impl Sized + Captures<'b> + 'a {
     MyTy::<'a, 'b>(None)
 }
 
-mod tait {
-    type Tait<'a> = impl Sized + 'a;
-    pub(super) fn step2<'a, 'b: 'a>() -> Tait<'a> {
-        super::step1::<'a, 'b>()
-        //~^ ERROR hidden type for `Tait<'a>` captures lifetime that does not appear in bounds
-    }
+type Tait<'a> = impl Sized + 'a;
+#[define_opaque(Tait)]
+fn step2<'a, 'b: 'a>() -> Tait<'a> {
+    step1::<'a, 'b>()
+    //~^ ERROR hidden type for `Tait<'a>` captures lifetime that does not appear in bounds
 }
 
 fn step3<'a, 'b: 'a>() -> impl Send + 'a {
-    tait::step2::<'a, 'b>()
+    step2::<'a, 'b>()
     // This should not be Send unless `'b: 'static`
 }
 
diff --git a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr
index 6c9b8cf2427..ed1afd64507 100644
--- a/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr
+++ b/tests/ui/impl-trait/alias-liveness/tait-hidden-erased-unsoundness.stderr
@@ -1,12 +1,13 @@
 error[E0700]: hidden type for `Tait<'a>` captures lifetime that does not appear in bounds
-  --> $DIR/tait-hidden-erased-unsoundness.rs:18:9
+  --> $DIR/tait-hidden-erased-unsoundness.rs:18:5
    |
-LL |     type Tait<'a> = impl Sized + 'a;
-   |                     --------------- opaque type defined here
-LL |     pub(super) fn step2<'a, 'b: 'a>() -> Tait<'a> {
-   |                             -- hidden type `impl Captures<'b> + 'a` captures the lifetime `'b` as defined here
-LL |         super::step1::<'a, 'b>()
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+LL | type Tait<'a> = impl Sized + 'a;
+   |                 --------------- opaque type defined here
+LL | #[define_opaque(Tait)]
+LL | fn step2<'a, 'b: 'a>() -> Tait<'a> {
+   |              -- hidden type `impl Captures<'b> + 'a` captures the lifetime `'b` as defined here
+LL |     step1::<'a, 'b>()
+   |     ^^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/associated-type-undefine.rs b/tests/ui/impl-trait/associated-type-undefine.rs
index c8f07021fbf..895525960fc 100644
--- a/tests/ui/impl-trait/associated-type-undefine.rs
+++ b/tests/ui/impl-trait/associated-type-undefine.rs
@@ -16,6 +16,7 @@ impl Foo for u32 {
 
 impl Foo for () {
     type Bar = impl Sized;
+    //~^ ERROR: unconstrained opaque type
     type Gat<T: Foo> = <T as Foo>::Bar;
     // Because we encounter `Gat<u32>` first, we never walk into another `Gat`
     // again, thus missing the opaque type that we could be defining.
diff --git a/tests/ui/impl-trait/associated-type-undefine.stderr b/tests/ui/impl-trait/associated-type-undefine.stderr
index 5d9d525eb93..e567f1bcdf6 100644
--- a/tests/ui/impl-trait/associated-type-undefine.stderr
+++ b/tests/ui/impl-trait/associated-type-undefine.stderr
@@ -1,5 +1,13 @@
+error: unconstrained opaque type
+  --> $DIR/associated-type-undefine.rs:18:16
+   |
+LL |     type Bar = impl Sized;
+   |                ^^^^^^^^^^
+   |
+   = note: `Bar` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/associated-type-undefine.rs:23:14
+  --> $DIR/associated-type-undefine.rs:24:14
    |
 LL |     type Bar = impl Sized;
    |                ---------- the expected opaque type
@@ -9,12 +17,7 @@ LL |         ((), ())
    |
    = note: expected opaque type `<() as Foo>::Bar`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/associated-type-undefine.rs:22:8
-   |
-LL |     fn foo(self) -> (<Self as Foo>::Gat<u32>, <Self as Foo>::Gat<Self>) {
-   |        ^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/impl-trait/async_scope_creep.rs b/tests/ui/impl-trait/async_scope_creep.rs
index 0fb355c5233..449f090a2e4 100644
--- a/tests/ui/impl-trait/async_scope_creep.rs
+++ b/tests/ui/impl-trait/async_scope_creep.rs
@@ -22,11 +22,13 @@ impl Pending {
     }
 
     #[cfg(tait)]
+    #[define_opaque(OpeningReadFuture)]
     fn read_fut(&mut self) -> OpeningReadFuture<'_> {
         self.read()
     }
 
     #[cfg(rpit)]
+    #[define_opaque(PendingReader)]
     fn read_fut(
         &mut self,
     ) -> impl std::future::Future<Output = Result<PendingReader<'_>, CantOpen>> {
diff --git a/tests/ui/impl-trait/auto-trait-coherence.rs b/tests/ui/impl-trait/auto-trait-coherence.rs
index 0d7fef21cc9..fdb981ea406 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.rs
+++ b/tests/ui/impl-trait/auto-trait-coherence.rs
@@ -5,6 +5,7 @@
 trait OpaqueTrait {}
 impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
+#[define_opaque(OpaqueType)]
 fn mk_opaque() -> OpaqueType {
     ()
 }
diff --git a/tests/ui/impl-trait/auto-trait-coherence.stderr b/tests/ui/impl-trait/auto-trait-coherence.stderr
index e0f4c857717..cfeccc3d766 100644
--- a/tests/ui/impl-trait/auto-trait-coherence.stderr
+++ b/tests/ui/impl-trait/auto-trait-coherence.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
-  --> $DIR/auto-trait-coherence.rs:21:1
+  --> $DIR/auto-trait-coherence.rs:22:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
diff --git a/tests/ui/impl-trait/bound-normalization-pass.rs b/tests/ui/impl-trait/bound-normalization-pass.rs
index 801187b6f5e..77bc0206830 100644
--- a/tests/ui/impl-trait/bound-normalization-pass.rs
+++ b/tests/ui/impl-trait/bound-normalization-pass.rs
@@ -77,6 +77,7 @@ mod opaque_types {
 
     type Ex = impl Trait<Out = <() as Implemented>::Assoc>;
 
+    #[define_opaque(Ex)]
     fn define() -> Ex {
         ()
     }
diff --git a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
index e8c1fcdd213..54d68afc31f 100644
--- a/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
+++ b/tests/ui/impl-trait/coherence-treats-tait-ambig.rs
@@ -5,7 +5,8 @@ type T = impl Sized;
 struct Foo;
 
 impl Into<T> for Foo {
-//~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo`
+    //~^ ERROR conflicting implementations of trait `Into<_>` for type `Foo`
+    #[define_opaque(T)]
     fn into(self) -> T {
         Foo
     }
diff --git a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
index 4e452994f72..28b6697f4bc 100644
--- a/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
+++ b/tests/ui/impl-trait/deduce-signature-from-supertrait.rs
@@ -8,7 +8,8 @@ impl<T: Fn(i32)> SuperExpectation for T {}
 
 type Foo = impl SuperExpectation;
 
-fn bop(_: Foo) {
+#[define_opaque(Foo)]
+fn bop() {
     let _: Foo = |x| {
         let _ = x.to_string();
     };
diff --git a/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs b/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs
index af623dc7cd9..e8be2082d7c 100644
--- a/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs
+++ b/tests/ui/impl-trait/future-no-bound-vars-ice-112347.rs
@@ -7,15 +7,12 @@
 
 use std::future::Future;
 
-mod foo {
-    use std::future::Future;
-    pub type Fut<'a> = impl Future<Output = ()> + 'a;
+pub type Fut<'a> = impl Future<Output = ()> + 'a;
 
-    fn foo<'a>(_: &()) -> Fut<'_> {
-        async {}
-    }
+#[define_opaque(Fut)]
+fn foo<'a>(_: &()) -> Fut<'_> {
+    async {}
 }
-use foo::*;
 
 trait Test {
     fn hello();
diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr b/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr
index 01c5a553dc5..dca0a7b0a1a 100644
--- a/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr
+++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.default.stderr
@@ -13,7 +13,7 @@ LL |     Thunk::new(|mut cont: /* Type */| {
    |                         ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/hidden-type-is-opaque-2.rs:20:17
+  --> $DIR/hidden-type-is-opaque-2.rs:21:17
    |
 LL |     Thunk::new(|mut cont| {
    |                 ^^^^^^^^
diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr b/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr
index 01c5a553dc5..dca0a7b0a1a 100644
--- a/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr
+++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.next.stderr
@@ -13,7 +13,7 @@ LL |     Thunk::new(|mut cont: /* Type */| {
    |                         ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/hidden-type-is-opaque-2.rs:20:17
+  --> $DIR/hidden-type-is-opaque-2.rs:21:17
    |
 LL |     Thunk::new(|mut cont| {
    |                 ^^^^^^^^
diff --git a/tests/ui/impl-trait/hidden-type-is-opaque-2.rs b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs
index 78ac8363ba9..7725a04c358 100644
--- a/tests/ui/impl-trait/hidden-type-is-opaque-2.rs
+++ b/tests/ui/impl-trait/hidden-type-is-opaque-2.rs
@@ -16,6 +16,7 @@ fn reify_as() -> Thunk<impl FnOnce(Continuation) -> Continuation> {
 
 type Tait = impl FnOnce(Continuation) -> Continuation;
 
+#[define_opaque(Tait)]
 fn reify_as_tait() -> Thunk<Tait> {
     Thunk::new(|mut cont| {
         //~^ ERROR type annotations needed
diff --git a/tests/ui/impl-trait/hidden-type-is-opaque.rs b/tests/ui/impl-trait/hidden-type-is-opaque.rs
index 3111a21e209..aa9ea2a8a26 100644
--- a/tests/ui/impl-trait/hidden-type-is-opaque.rs
+++ b/tests/ui/impl-trait/hidden-type-is-opaque.rs
@@ -10,6 +10,7 @@ fn reify_as() -> Thunk<impl ContFn> {
 
 type Tait = impl ContFn;
 
+#[define_opaque(Tait)]
 fn reify_as_tait() -> Thunk<Tait> {
     Thunk::new(|mut cont| {
         cont.reify_as();
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
index 146a3d21068..c76415d8114 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.current.stderr
@@ -1,5 +1,5 @@
 error[E0407]: method `line_stream` is not a member of trait `X`
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
@@ -17,15 +17,23 @@ LL |     type LineStream<'c, 'd> = impl Stream;
    |                     |
    |                     found 0 type parameters
 
+error: unconstrained opaque type
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:31
+   |
+LL |     type LineStream<'c, 'd> = impl Stream;
+   |                               ^^^^^^^^^^^
+   |
+   = note: `LineStream` must be used in combination with a concrete type within the same impl
+
 error[E0277]: `()` is not a future
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `()` is not a future
    |
    = help: the trait `Future` is not implemented for `()`
 
-error: aborting due to 3 previous errors
+error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0049, E0277, E0407.
 For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
index ce64a022214..4d72490ff95 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.next.stderr
@@ -1,5 +1,5 @@
 error[E0407]: method `line_stream` is not a member of trait `X`
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ not a member of trait `X`
@@ -17,25 +17,33 @@ LL |     type LineStream<'c, 'd> = impl Stream;
    |                     |
    |                     found 0 type parameters
 
+error: unconstrained opaque type
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:25:31
+   |
+LL |     type LineStream<'c, 'd> = impl Stream;
+   |                               ^^^^^^^^^^^
+   |
+   = note: `LineStream` must be used in combination with a concrete type within the same impl
+
 error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> == ()`
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:43
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:43
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
 
 error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:73
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:73
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |                                                                         ^^ types differ
 
 error[E0271]: type mismatch resolving `<Y as X>::LineStreamFut<'a, Repr> normalizes-to _`
-  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:28:5
+  --> $DIR/ice-unexpected-param-type-whensubstituting-in-region-112823.rs:29:5
    |
 LL |     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ types differ
 
-error: aborting due to 5 previous errors
+error: aborting due to 6 previous errors
 
 Some errors have detailed explanations: E0049, E0271, E0407.
 For more information about an error, try `rustc --explain E0049`.
diff --git a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
index cb32723b22d..a5a37dbb210 100644
--- a/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
+++ b/tests/ui/impl-trait/ice-unexpected-param-type-whensubstituting-in-region-112823.rs
@@ -24,6 +24,7 @@ struct Y;
 impl X for Y {
     type LineStream<'c, 'd> = impl Stream;
     //~^ ERROR type `LineStream` has 0 type parameters but its trait declaration has 1 type parameter
+    //~| ERROR: unconstrained opaque type
     type LineStreamFut<'a, Repr> = impl Future<Output = Self::LineStream<'a, Repr>>;
     fn line_stream<'a, Repr>(&'a self) -> Self::LineStreamFut<'a, Repr> {}
     //~^ method `line_stream` is not a member of trait `X`
diff --git a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
index 8351175099c..c9e657b87d5 100644
--- a/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
+++ b/tests/ui/impl-trait/in-assoc-type-unconstrained.stderr
@@ -36,11 +36,6 @@ LL |         fn method() -> Self::Ty;
    |                        ^^^^^^^^
    = note: expected signature `fn() -> <() as compare_method::Trait>::Ty`
               found signature `fn() -> ()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type-unconstrained.rs:22:12
-   |
-LL |         fn method() -> () {}
-   |            ^^^^^^
 help: change the output type to match the trait
    |
 LL -         fn method() -> () {}
diff --git a/tests/ui/impl-trait/in-assoc-type.stderr b/tests/ui/impl-trait/in-assoc-type.stderr
index d5b543ea953..5a8cc40d027 100644
--- a/tests/ui/impl-trait/in-assoc-type.stderr
+++ b/tests/ui/impl-trait/in-assoc-type.stderr
@@ -11,11 +11,6 @@ LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
    |
    = note: expected opaque type `<() as Foo<()>>::Bar`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/in-assoc-type.rs:20:8
-   |
-LL |     fn foo(&self) -> <Self as Foo<()>>::Bar {}
-   |        ^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/issue-108591.rs b/tests/ui/impl-trait/issue-108591.rs
index caf08024568..db1c73831ee 100644
--- a/tests/ui/impl-trait/issue-108591.rs
+++ b/tests/ui/impl-trait/issue-108591.rs
@@ -15,6 +15,7 @@ impl MyTy<'_> {
 
 type Opaque2 = impl Sized;
 type Opaque<'a> = Opaque2;
+#[define_opaque(Opaque)]
 fn define<'a>() -> Opaque<'a> {}
 
 fn test<'a>() {
diff --git a/tests/ui/impl-trait/issue-108592.rs b/tests/ui/impl-trait/issue-108592.rs
index 7db2e31549c..facb8be9d23 100644
--- a/tests/ui/impl-trait/issue-108592.rs
+++ b/tests/ui/impl-trait/issue-108592.rs
@@ -11,13 +11,10 @@ fn test_closure() {
     closure(&opaque());
 }
 
-mod helper {
-    pub type Opaque2 = impl Sized;
-    pub type Opaque<'a> = Opaque2;
-    fn define<'a>() -> Opaque<'a> {}
-}
-
-use helper::*;
+pub type Opaque2 = impl Sized;
+pub type Opaque<'a> = Opaque2;
+#[define_opaque(Opaque)]
+fn define<'a>() -> Opaque<'a> {}
 
 fn test_tait(_: &Opaque<'_>) {
     None::<&'static Opaque<'_>>;
diff --git a/tests/ui/impl-trait/issue-99642-2.rs b/tests/ui/impl-trait/issue-99642-2.rs
index acbf3e3e2a0..d8d367a5d35 100644
--- a/tests/ui/impl-trait/issue-99642-2.rs
+++ b/tests/ui/impl-trait/issue-99642-2.rs
@@ -2,7 +2,8 @@
 
 #![feature(type_alias_impl_trait)]
 type Opq = impl Sized;
+#[define_opaque(Opq)]
 fn test() -> impl Iterator<Item = Opq> {
     Box::new(0..) as Box<dyn Iterator<Item = _>>
 }
-fn main(){}
+fn main() {}
diff --git a/tests/ui/impl-trait/issues/issue-53457.rs b/tests/ui/impl-trait/issues/issue-53457.rs
index bb248ef7177..a47c7655058 100644
--- a/tests/ui/impl-trait/issues/issue-53457.rs
+++ b/tests/ui/impl-trait/issues/issue-53457.rs
@@ -7,6 +7,7 @@ fn bar<F: Fn(&i32) + Clone>(f: F) -> F {
     f
 }
 
+#[define_opaque(X)]
 fn foo() -> X {
     bar(|_| ())
 }
diff --git a/tests/ui/impl-trait/issues/issue-70877.rs b/tests/ui/impl-trait/issues/issue-70877.rs
index 6ced0bbba8b..0f0a1b5187d 100644
--- a/tests/ui/impl-trait/issues/issue-70877.rs
+++ b/tests/ui/impl-trait/issues/issue-70877.rs
@@ -15,27 +15,27 @@ impl Iterator for Bar {
     }
 }
 
-mod ret {
-    pub type FooRet = impl std::fmt::Debug;
-    pub fn quux(st: super::FooArg) -> FooRet {
-        Some(st.to_string())
-    }
+pub type FooRet = impl std::fmt::Debug;
+#[define_opaque(FooRet)]
+pub fn quux(st: FooArg) -> FooRet {
+    Some(st.to_string())
 }
-use ret::*;
-mod foo {
-    pub type Foo = impl Iterator<Item = super::FooItem>;
-    pub fn ham() -> Foo {
-        super::Bar(1)
-    }
-    pub fn oof(_: Foo) -> impl std::fmt::Debug {
-        //~^ ERROR: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-        let mut bar = ham();
-        let func = bar.next().unwrap();
-        return func(&"oof");
-    }
+pub type Foo = impl Iterator<Item = FooItem>;
+#[define_opaque(Foo)]
+pub fn ham() -> Foo {
+    //~^ ERROR: item does not constrain `FooRet::{opaque#0}`
+    Bar(1)
+}
+#[define_opaque(Foo)]
+pub fn oof() -> impl std::fmt::Debug {
+    //~^ ERROR: item does not constrain `FooRet::{opaque#0}`
+    //~| ERROR: item does not constrain `Foo::{opaque#0}`
+    let mut bar = ham();
+    let func = bar.next().unwrap();
+    return func(&"oof");
+    //~^ ERROR: opaque type's hidden type cannot be another opaque type
 }
-use foo::*;
 
 fn main() {
-    let _ = oof(ham());
+    let _ = oof();
 }
diff --git a/tests/ui/impl-trait/issues/issue-70877.stderr b/tests/ui/impl-trait/issues/issue-70877.stderr
index 4b23a02aaee..b2f37c8af9e 100644
--- a/tests/ui/impl-trait/issues/issue-70877.stderr
+++ b/tests/ui/impl-trait/issues/issue-70877.stderr
@@ -1,15 +1,58 @@
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-70877.rs:30:12
+error: item does not constrain `FooRet::{opaque#0}`
+  --> $DIR/issue-70877.rs:25:8
    |
-LL |     pub fn oof(_: Foo) -> impl std::fmt::Debug {
-   |            ^^^
+LL | pub fn ham() -> Foo {
+   |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-70877.rs:26:20
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-70877.rs:18:19
    |
-LL |     pub type Foo = impl Iterator<Item = super::FooItem>;
-   |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | pub type FooRet = impl std::fmt::Debug;
+   |                   ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+error: item does not constrain `FooRet::{opaque#0}`
+  --> $DIR/issue-70877.rs:30:8
+   |
+LL | pub fn oof() -> impl std::fmt::Debug {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-70877.rs:18:19
+   |
+LL | pub type FooRet = impl std::fmt::Debug;
+   |                   ^^^^^^^^^^^^^^^^^^^^
+
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/issue-70877.rs:30:8
+   |
+LL | pub fn oof() -> impl std::fmt::Debug {
+   |        ^^^
+   |
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-70877.rs:23:16
+   |
+LL | pub type Foo = impl Iterator<Item = FooItem>;
+   |                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: opaque type's hidden type cannot be another opaque type from the same scope
+  --> $DIR/issue-70877.rs:35:12
+   |
+LL |     return func(&"oof");
+   |            ^^^^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
+   |
+note: opaque type whose hidden type is being assigned
+  --> $DIR/issue-70877.rs:30:17
+   |
+LL | pub fn oof() -> impl std::fmt::Debug {
+   |                 ^^^^^^^^^^^^^^^^^^^^
+note: opaque type being used as hidden type
+  --> $DIR/issue-70877.rs:18:19
+   |
+LL | pub type FooRet = impl std::fmt::Debug;
+   |                   ^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-74282.rs b/tests/ui/impl-trait/issues/issue-74282.rs
index 51bd5f67ed5..eb14a76a069 100644
--- a/tests/ui/impl-trait/issues/issue-74282.rs
+++ b/tests/ui/impl-trait/issues/issue-74282.rs
@@ -3,7 +3,8 @@
 type Closure = impl Fn() -> u64;
 struct Anonymous(Closure);
 
-fn bop(_: Closure) {
+#[define_opaque(Closure)]
+fn bop() {
     let y = || -> Closure { || 3 };
     Anonymous(|| {
         //~^ ERROR mismatched types
diff --git a/tests/ui/impl-trait/issues/issue-74282.stderr b/tests/ui/impl-trait/issues/issue-74282.stderr
index f8e85f7ae00..7a49041cace 100644
--- a/tests/ui/impl-trait/issues/issue-74282.stderr
+++ b/tests/ui/impl-trait/issues/issue-74282.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-74282.rs:8:15
+  --> $DIR/issue-74282.rs:9:15
    |
 LL |   type Closure = impl Fn() -> u64;
    |                  ---------------- the expected opaque type
@@ -14,7 +14,7 @@ LL | |     })
    | |_____^ expected opaque type, found closure
    |
    = note: expected opaque type `Closure`
-                  found closure `{closure@$DIR/issue-74282.rs:8:15: 8:17}`
+                  found closure `{closure@$DIR/issue-74282.rs:9:15: 9:17}`
    = note: no two closures, even if identical, have the same type
    = help: consider boxing your closure and/or using it as a trait object
 note: tuple struct defined here
@@ -24,7 +24,7 @@ LL | struct Anonymous(Closure);
    |        ^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/issue-74282.rs:8:5
+  --> $DIR/issue-74282.rs:9:5
    |
 LL | /     Anonymous(|| {
 LL | |
@@ -38,8 +38,8 @@ LL |     });
    |       +
 help: try adding a return type
    |
-LL | fn bop(_: Closure) -> Anonymous {
-   |                    ++++++++++++
+LL | fn bop() -> Anonymous {
+   |          ++++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/impl-trait/issues/issue-77987.rs b/tests/ui/impl-trait/issues/issue-77987.rs
index a7e7b067d5f..f134224071f 100644
--- a/tests/ui/impl-trait/issues/issue-77987.rs
+++ b/tests/ui/impl-trait/issues/issue-77987.rs
@@ -5,17 +5,16 @@
 pub trait Foo<T> {}
 impl<T, U> Foo<T> for U {}
 
-mod scope {
-    pub type Scope = impl super::Foo<()>;
+pub type Scope = impl Foo<()>;
 
-    #[allow(unused)]
-    fn infer_scope() -> Scope {
-        ()
-    }
+#[allow(unused)]
+#[define_opaque(Scope)]
+fn infer_scope() -> Scope {
+    ()
 }
 
 #[allow(unused)]
-fn ice() -> impl Foo<scope::Scope> {
+fn ice() -> impl Foo<Scope> {
     loop {}
 }
 
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.rs b/tests/ui/impl-trait/issues/issue-78722-2.rs
index e811620c03b..ef4d26b6975 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.rs
+++ b/tests/ui/impl-trait/issues/issue-78722-2.rs
@@ -8,6 +8,7 @@ type F = impl core::future::Future<Output = u8>;
 
 struct Bug {
     V1: [(); {
+        #[define_opaque(F)]
         fn concrete_use() -> F {
             //~^ ERROR future that resolves to `u8`, but it resolves to `()`
             async {}
diff --git a/tests/ui/impl-trait/issues/issue-78722-2.stderr b/tests/ui/impl-trait/issues/issue-78722-2.stderr
index 27b4b712830..ede830bf72c 100644
--- a/tests/ui/impl-trait/issues/issue-78722-2.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722-2.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-78722-2.rs:16:20
+  --> $DIR/issue-78722-2.rs:17:20
    |
 LL | type F = impl core::future::Future<Output = u8>;
    |          -------------------------------------- the expected future
@@ -10,10 +10,10 @@ LL |         let f: F = async { 1 };
    |                expected due to this
    |
    = note: expected opaque type `F`
-            found `async` block `{async block@$DIR/issue-78722-2.rs:16:20: 16:25}`
+            found `async` block `{async block@$DIR/issue-78722-2.rs:17:20: 17:25}`
 
-error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:13:13: 13:18}` to be a future that resolves to `u8`, but it resolves to `()`
-  --> $DIR/issue-78722-2.rs:11:30
+error[E0271]: expected `{async block@$DIR/issue-78722-2.rs:14:13: 14:18}` to be a future that resolves to `u8`, but it resolves to `()`
+  --> $DIR/issue-78722-2.rs:12:30
    |
 LL |         fn concrete_use() -> F {
    |                              ^ expected `u8`, found `()`
diff --git a/tests/ui/impl-trait/issues/issue-78722.rs b/tests/ui/impl-trait/issues/issue-78722.rs
index 5518c2cf12a..374cd564b8e 100644
--- a/tests/ui/impl-trait/issues/issue-78722.rs
+++ b/tests/ui/impl-trait/issues/issue-78722.rs
@@ -5,6 +5,7 @@
 struct Bug {
     V1: [(); {
         type F = impl core::future::Future<Output = u8>;
+        #[define_opaque(F)]
         fn concrete_use() -> F {
             //~^ ERROR to be a future that resolves to `u8`, but it resolves to `()`
             async {}
diff --git a/tests/ui/impl-trait/issues/issue-78722.stderr b/tests/ui/impl-trait/issues/issue-78722.stderr
index 109bda0c5cd..84c7dfb0338 100644
--- a/tests/ui/impl-trait/issues/issue-78722.stderr
+++ b/tests/ui/impl-trait/issues/issue-78722.stderr
@@ -1,5 +1,5 @@
 error[E0658]: `async` blocks are not allowed in constants
-  --> $DIR/issue-78722.rs:12:20
+  --> $DIR/issue-78722.rs:13:20
    |
 LL |         let f: F = async { 1 };
    |                    ^^^^^^^^^^^
@@ -8,8 +8,8 @@ LL |         let f: F = async { 1 };
    = help: add `#![feature(const_async_blocks)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0271]: expected `{async block@$DIR/issue-78722.rs:10:13: 10:18}` to be a future that resolves to `u8`, but it resolves to `()`
-  --> $DIR/issue-78722.rs:8:30
+error[E0271]: expected `{async block@$DIR/issue-78722.rs:11:13: 11:18}` to be a future that resolves to `u8`, but it resolves to `()`
+  --> $DIR/issue-78722.rs:9:30
    |
 LL |         fn concrete_use() -> F {
    |                              ^ expected `u8`, found `()`
diff --git a/tests/ui/impl-trait/issues/issue-86201.rs b/tests/ui/impl-trait/issues/issue-86201.rs
index cde0b861160..19c68f7697b 100644
--- a/tests/ui/impl-trait/issues/issue-86201.rs
+++ b/tests/ui/impl-trait/issues/issue-86201.rs
@@ -4,10 +4,13 @@
 //@ check-pass
 
 type FunType = impl Fn<()>;
-static STATIC_FN: FunType = some_fn;
+#[define_opaque(FunType)]
+fn foo() -> FunType {
+    some_fn
+}
 
 fn some_fn() {}
 
 fn main() {
-    let _: <FunType as FnOnce<()>>::Output = STATIC_FN();
+    let _: <FunType as FnOnce<()>>::Output = foo()();
 }
diff --git a/tests/ui/impl-trait/issues/issue-86800.rs b/tests/ui/impl-trait/issues/issue-86800.rs
index ff1d273ae48..c1176255f24 100644
--- a/tests/ui/impl-trait/issues/issue-86800.rs
+++ b/tests/ui/impl-trait/issues/issue-86800.rs
@@ -4,43 +4,41 @@
 
 use std::future::Future;
 
-struct Connection {
-}
+struct Connection {}
 
-trait Transaction {
-}
+trait Transaction {}
 
 struct TestTransaction<'conn> {
-    conn: &'conn Connection
+    conn: &'conn Connection,
 }
 
-impl<'conn> Transaction for TestTransaction<'conn> {
-}
+impl<'conn> Transaction for TestTransaction<'conn> {}
 
-struct Context {
-}
+struct Context {}
 
 type TransactionResult<O> = Result<O, ()>;
 
 type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
 
+#[define_opaque(TransactionFuture)]
 fn execute_transaction_fut<'f, F, O>(
     //~^ ERROR: item does not constrain
     f: F,
 ) -> impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
 where
-    F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f
+    F: FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O> + 'f,
 {
     f
     //~^ ERROR expected generic lifetime parameter, found `'_`
 }
 
 impl Context {
+    #[define_opaque(TransactionFuture)]
     async fn do_transaction<O>(
         //~^ ERROR: item does not constrain
-        &self, f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>
-    ) -> TransactionResult<O>
-    {
+        &self,
+        f: impl FnOnce(&mut dyn Transaction) -> TransactionFuture<'_, O>,
+    ) -> TransactionResult<O> {
         //~^ ERROR expected generic lifetime parameter, found `'_`
         //~| ERROR: item does not constrain
         let mut conn = Connection {};
diff --git a/tests/ui/impl-trait/issues/issue-86800.stderr b/tests/ui/impl-trait/issues/issue-86800.stderr
index fd9b8e7ac99..11e23d97d72 100644
--- a/tests/ui/impl-trait/issues/issue-86800.stderr
+++ b/tests/ui/impl-trait/issues/issue-86800.stderr
@@ -1,33 +1,34 @@
-error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:27:4
+error: item does not constrain `TransactionFuture::{opaque#0}`
+  --> $DIR/issue-86800.rs:24:4
    |
 LL | fn execute_transaction_fut<'f, F, O>(
    |    ^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-86800.rs:25:34
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-86800.rs:21:34
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:39:14
+error: item does not constrain `TransactionFuture::{opaque#0}`
+  --> $DIR/issue-86800.rs:37:14
    |
 LL |     async fn do_transaction<O>(
    |              ^^^^^^^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-86800.rs:25:34
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-86800.rs:21:34
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `TransactionFuture::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-86800.rs:43:5
+error: item does not constrain `TransactionFuture::{opaque#0}`
+  --> $DIR/issue-86800.rs:41:31
    |
-LL | /     {
+LL |       ) -> TransactionResult<O> {
+   |  _______________________________^
 LL | |
 LL | |
 LL | |         let mut conn = Connection {};
@@ -36,15 +37,15 @@ LL | |         f(&mut transaction).await
 LL | |     }
    | |_____^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-86800.rs:25:34
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-86800.rs:21:34
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                                  ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:34:5
+  --> $DIR/issue-86800.rs:31:5
    |
 LL | type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                        --- this generic parameter must be used with a generic lifetime parameter
@@ -53,12 +54,13 @@ LL |     f
    |     ^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-86800.rs:43:5
+  --> $DIR/issue-86800.rs:41:31
    |
 LL |   type TransactionFuture<'__, O> = impl '__ + Future<Output = TransactionResult<O>>;
    |                          --- this generic parameter must be used with a generic lifetime parameter
 ...
-LL | /     {
+LL |       ) -> TransactionResult<O> {
+   |  _______________________________^
 LL | |
 LL | |
 LL | |         let mut conn = Connection {};
diff --git a/tests/ui/impl-trait/issues/issue-89312.rs b/tests/ui/impl-trait/issues/issue-89312.rs
index 3b0e976780b..35cba41dd4b 100644
--- a/tests/ui/impl-trait/issues/issue-89312.rs
+++ b/tests/ui/impl-trait/issues/issue-89312.rs
@@ -2,23 +2,21 @@
 
 //@ check-pass
 
-mod helper {
-    pub trait T {
-        type Item;
-    }
+pub trait T {
+    type Item;
+}
 
-    pub type Alias<'a> = impl T<Item = &'a ()>;
+pub type Alias<'a> = impl T<Item = &'a ()>;
 
-    struct S;
-    impl<'a> T for &'a S {
-        type Item = &'a ();
-    }
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
 
-    pub fn filter_positive<'a>() -> Alias<'a> {
-        &S
-    }
+#[define_opaque(Alias)]
+pub fn filter_positive<'a>() -> Alias<'a> {
+    &S
 }
-use helper::*;
 
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     fun(filter_positive());
diff --git a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
index b05579f2166..e19230b44b4 100644
--- a/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
+++ b/tests/ui/impl-trait/issues/issue-99348-impl-compatibility.rs
@@ -21,6 +21,7 @@ trait Bar {
     type Other;
 }
 
+#[define_opaque(Tait)]
 fn tait() -> Tait {}
 
 fn main() {}
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
index 2a2be6b7429..21ca558153d 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.rs
@@ -7,6 +7,7 @@ impl<T: Copy> Copy for CopyIfEq<T, T> {}
 
 type E<'a, 'b> = impl Sized;
 
+#[define_opaque(E)]
 fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
     let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
 
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
index b968592beff..712cbbecd74 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling-2.stderr
@@ -1,9 +1,9 @@
 error[E0700]: hidden type for `E<'b, 'c>` captures lifetime that does not appear in bounds
-  --> $DIR/error-handling-2.rs:22:5
+  --> $DIR/error-handling-2.rs:23:5
    |
 LL | type E<'a, 'b> = impl Sized;
    |                  ---------- opaque type defined here
-LL |
+...
 LL | fn foo<'a: 'b, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        -- hidden type `*mut &'a i32` captures the lifetime `'a` as defined here
 ...
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs b/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs
index 367e7f4e6ea..0f3b7506318 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.rs
@@ -7,6 +7,7 @@ impl<T: Copy> Copy for CopyIfEq<T, T> {}
 
 type E<'a, 'b> = impl Sized;
 
+#[define_opaque(E)]
 fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
     let v = CopyIfEq::<*mut _, *mut _>(&mut { x }, &mut y);
 
diff --git a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
index 945fb0fc618..3732307ca35 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
+++ b/tests/ui/impl-trait/multiple-lifetimes/error-handling.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/error-handling.rs:20:16
+  --> $DIR/error-handling.rs:21:16
    |
 LL | fn foo<'a, 'b, 'c>(x: &'static i32, mut y: &'a i32) -> E<'b, 'c> {
    |        --  -- lifetime `'b` defined here
diff --git a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs
index 6f90160866b..6a1cb61b8ba 100644
--- a/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs
+++ b/tests/ui/impl-trait/multiple-lifetimes/ordinary-bounds-pick-original-type-alias-impl-trait.rs
@@ -10,6 +10,7 @@ impl<T> Trait<'_, '_> for T {}
 
 type Foo<'a, 'b> = impl Trait<'a, 'b>;
 
+#[define_opaque(Foo)]
 fn upper_bounds<'a, 'b>(a: &'a u8, b: &'b u8) -> Foo<'a, 'b> {
     // In this simple case, you have a hidden type `(&'0 u8, &'1 u8)` and constraints like
     //
diff --git a/tests/ui/impl-trait/negative-reasoning.rs b/tests/ui/impl-trait/negative-reasoning.rs
index 0474dc0beda..0d4a1ba75d8 100644
--- a/tests/ui/impl-trait/negative-reasoning.rs
+++ b/tests/ui/impl-trait/negative-reasoning.rs
@@ -5,6 +5,7 @@
 trait OpaqueTrait {}
 impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
+#[define_opaque(OpaqueType)]
 fn mk_opaque() -> OpaqueType {
     ()
 }
diff --git a/tests/ui/impl-trait/negative-reasoning.stderr b/tests/ui/impl-trait/negative-reasoning.stderr
index 631784c817b..2918be5135c 100644
--- a/tests/ui/impl-trait/negative-reasoning.stderr
+++ b/tests/ui/impl-trait/negative-reasoning.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `AnotherTrait` for type `D<_>`
-  --> $DIR/negative-reasoning.rs:19:1
+  --> $DIR/negative-reasoning.rs:20:1
    |
 LL | impl<T: std::fmt::Debug> AnotherTrait for T {}
    | ------------------------------------------- first implementation here
diff --git a/tests/ui/impl-trait/nested-return-type2-tait.rs b/tests/ui/impl-trait/nested-return-type2-tait.rs
index 7cb98cfe060..aa871df9d9c 100644
--- a/tests/ui/impl-trait/nested-return-type2-tait.rs
+++ b/tests/ui/impl-trait/nested-return-type2-tait.rs
@@ -25,10 +25,10 @@ type Sendable = impl Send;
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, but if its hidden type does.
+#[define_opaque(Sendable)]
 fn foo() -> impl Trait<Assoc = Sendable> {
     //~^ WARN opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
     || 42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-return-type2-tait.stderr b/tests/ui/impl-trait/nested-return-type2-tait.stderr
index 4383e8ab3a0..8105990eac4 100644
--- a/tests/ui/impl-trait/nested-return-type2-tait.stderr
+++ b/tests/ui/impl-trait/nested-return-type2-tait.stderr
@@ -1,5 +1,5 @@
 warning: opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
-  --> $DIR/nested-return-type2-tait.rs:28:24
+  --> $DIR/nested-return-type2-tait.rs:29:24
    |
 LL |     type Assoc: Duh;
    |                 --- this associated type bound is unsatisfied for `Sendable`
diff --git a/tests/ui/impl-trait/nested-return-type2-tait2.rs b/tests/ui/impl-trait/nested-return-type2-tait2.rs
index 574602079d4..bd89dad7dfd 100644
--- a/tests/ui/impl-trait/nested-return-type2-tait2.rs
+++ b/tests/ui/impl-trait/nested-return-type2-tait2.rs
@@ -26,9 +26,9 @@ type Traitable = impl Trait<Assoc = Sendable>;
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does. So we error out.
+#[define_opaque(Traitable)]
 fn foo() -> Traitable {
     || 42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-return-type2-tait3.rs b/tests/ui/impl-trait/nested-return-type2-tait3.rs
index e3429731782..83bf441181a 100644
--- a/tests/ui/impl-trait/nested-return-type2-tait3.rs
+++ b/tests/ui/impl-trait/nested-return-type2-tait3.rs
@@ -25,9 +25,9 @@ type Traitable = impl Trait<Assoc = impl Send>;
 // the hidden type. We already have obligations registered on the inference
 // var to make it uphold the `: Duh` bound on `Trait::Assoc`. The opaque
 // type does not implement `Duh`, even if its hidden type does. So we error out.
+#[define_opaque(Traitable)]
 fn foo() -> Traitable {
     || 42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-return-type3-tait.rs b/tests/ui/impl-trait/nested-return-type3-tait.rs
index 05759fb2697..fb2e4d87543 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait.rs
+++ b/tests/ui/impl-trait/nested-return-type3-tait.rs
@@ -16,10 +16,10 @@ impl<F: Duh> Trait for F {
 
 type Sendable = impl Send;
 
+#[define_opaque(Sendable)]
 fn foo() -> impl Trait<Assoc = Sendable> {
     //~^ WARN opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
     42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-return-type3-tait.stderr b/tests/ui/impl-trait/nested-return-type3-tait.stderr
index d32944a0d72..bb1f524b992 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait.stderr
+++ b/tests/ui/impl-trait/nested-return-type3-tait.stderr
@@ -1,5 +1,5 @@
 warning: opaque type `impl Trait<Assoc = Sendable>` does not satisfy its associated type bounds
-  --> $DIR/nested-return-type3-tait.rs:19:24
+  --> $DIR/nested-return-type3-tait.rs:20:24
    |
 LL |     type Assoc: Duh;
    |                 --- this associated type bound is unsatisfied for `Sendable`
diff --git a/tests/ui/impl-trait/nested-return-type3-tait2.rs b/tests/ui/impl-trait/nested-return-type3-tait2.rs
index 927fa8d596b..f3fda61e920 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait2.rs
+++ b/tests/ui/impl-trait/nested-return-type3-tait2.rs
@@ -18,9 +18,9 @@ type Sendable = impl Send;
 type Traitable = impl Trait<Assoc = Sendable>;
 //~^ WARN opaque type `Traitable` does not satisfy its associated type bounds
 
+#[define_opaque(Traitable)]
 fn foo() -> Traitable {
     42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/nested-return-type3-tait3.rs b/tests/ui/impl-trait/nested-return-type3-tait3.rs
index 5b3b2d2e198..d2acee9cafd 100644
--- a/tests/ui/impl-trait/nested-return-type3-tait3.rs
+++ b/tests/ui/impl-trait/nested-return-type3-tait3.rs
@@ -17,9 +17,9 @@ impl<F: Duh> Trait for F {
 type Traitable = impl Trait<Assoc = impl Send>;
 //~^ WARN opaque type `Traitable` does not satisfy its associated type bounds
 
+#[define_opaque(Traitable)]
 fn foo() -> Traitable {
     42
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/impl-trait/normalize-tait-in-const.stderr b/tests/ui/impl-trait/normalize-tait-in-const.stderr
index c6cd1b139c5..d4ba9a31170 100644
--- a/tests/ui/impl-trait/normalize-tait-in-const.stderr
+++ b/tests/ui/impl-trait/normalize-tait-in-const.stderr
@@ -17,6 +17,14 @@ note: `Fn` can't be used with `~const` because it isn't annotated with `#[const_
   --> $SRC_DIR/core/src/ops/function.rs:LL:COL
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error: unconstrained opaque type
+  --> $DIR/normalize-tait-in-const.rs:14:26
+   |
+LL |     pub type Alias<'a> = impl T<Item = &'a ()>;
+   |                          ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Alias` must be used in combination with a concrete type within the same crate
+
 error[E0015]: cannot call non-const closure in constant functions
   --> $DIR/normalize-tait-in-const.rs:28:5
    |
@@ -25,6 +33,26 @@ LL |     fun(filter_positive());
    |
    = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
 
-error: aborting due to 3 previous errors
+error[E0308]: mismatched types
+  --> $DIR/normalize-tait-in-const.rs:22:9
+   |
+LL |     pub type Alias<'a> = impl T<Item = &'a ()>;
+   |                          --------------------- the expected opaque type
+...
+LL |     pub const fn filter_positive<'a>() -> &'a Alias<'a> {
+   |                                           ------------- expected `&'a foo::Alias<'a>` because of return type
+LL |         &&S
+   |         ^^^ expected `&Alias<'_>`, found `&&S`
+   |
+   = note: expected reference `&'a foo::Alias<'a>`
+              found reference `&&S`
+note: this item must have a `#[define_opaque(foo::Alias)]` attribute to be able to define hidden types
+  --> $DIR/normalize-tait-in-const.rs:21:18
+   |
+LL |     pub const fn filter_positive<'a>() -> &'a Alias<'a> {
+   |                  ^^^^^^^^^^^^^^^
+
+error: aborting due to 5 previous errors
 
-For more information about this error, try `rustc --explain E0015`.
+Some errors have detailed explanations: E0015, E0308.
+For more information about an error, try `rustc --explain E0015`.
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
index 0b29af5df5b..662c7ee2ecf 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle-2.rs
@@ -2,14 +2,12 @@
 
 //@ check-pass
 
-mod foo {
-    pub type Foo = impl PartialEq<(Foo, i32)>;
+pub type Foo = impl PartialEq<(Foo, i32)>;
 
-    fn foo() -> Foo {
-        super::Bar
-    }
+#[define_opaque(Foo)]
+fn foo() -> Foo {
+    Bar
 }
-use foo::Foo;
 
 struct Bar;
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
index 3f41c5984b4..5b9c40ecede 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.rs
@@ -6,6 +6,7 @@ mod a {
     struct Bar;
 
     impl PartialEq<(Bar, i32)> for Bar {
+        #[define_opaque(Foo)]
         fn eq(&self, _other: &(Foo, i32)) -> bool {
             //~^ ERROR: `eq` has an incompatible type for trait
             //~| ERROR: item does not constrain `a::Foo::{opaque#0}`
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
index 767bd312407..7f642fa1bed 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr
@@ -1,5 +1,5 @@
 error[E0053]: method `eq` has an incompatible type for trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:9:30
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:30
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                -------------------------- the found opaque type
@@ -15,21 +15,21 @@ LL -         fn eq(&self, _other: &(Foo, i32)) -> bool {
 LL +         fn eq(&self, _other: &(a::Bar, i32)) -> bool {
    |
 
-error: item does not constrain `a::Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:9:12
+error: item does not constrain `a::Foo::{opaque#0}`
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:10:12
    |
 LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |            ^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:4:16
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0053]: method `eq` has an incompatible type for trait
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:30
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:25:30
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                -------------------------- the expected opaque type
@@ -39,8 +39,8 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |
    = note: expected signature `fn(&b::Bar, &(b::Foo, _)) -> _`
               found signature `fn(&b::Bar, &(b::Bar, _)) -> _`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:24:12
+note: this item must have a `#[define_opaque(b::Foo)]` attribute to be able to define hidden types
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:25:12
    |
 LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |            ^^
@@ -51,12 +51,12 @@ LL +         fn eq(&self, _other: &(b::Foo, i32)) -> bool {
    |
 
 error: unconstrained opaque type
-  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
+  --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:19:16
    |
 LL |     type Foo = impl PartialEq<(Foo, i32)>;
    |                ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Foo` must be used in combination with a concrete type within the same module
+   = note: `Foo` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
index aab10be2de2..372a095192b 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.rs
@@ -10,6 +10,7 @@ impl PartialEq<(Bar, i32)> for Bar {
     }
 }
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     //~^ ERROR can't compare `Bar` with `(Foo, i32)`
     Bar
diff --git a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
index bc810c0f88f..a9a5483caa9 100644
--- a/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
+++ b/tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `Bar` with `(Foo, i32)`
-  --> $DIR/recursive-type-alias-impl-trait-declaration.rs:13:13
+  --> $DIR/recursive-type-alias-impl-trait-declaration.rs:14:13
    |
 LL | fn foo() -> Foo {
    |             ^^^ no implementation for `Bar == (Foo, i32)`
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
index bf194f997b4..8845b3ff2c8 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other.current.stderr
@@ -1,5 +1,5 @@
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other.rs:17:5
+  --> $DIR/two_tait_defining_each_other.rs:18:5
    |
 LL |     x // A's hidden type is `Bar`, because all the hidden types of `B` are compared with each other
    |     ^ one of the two opaque types used here has to be outside its defining scope
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other.rs b/tests/ui/impl-trait/two_tait_defining_each_other.rs
index ebfe7f674be..d3038688eee 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other.rs
@@ -10,6 +10,7 @@ type B = impl Foo;
 
 trait Foo {}
 
+#[define_opaque(A, B)]
 fn muh(x: A) -> B {
     if false {
         return Bar; // B's hidden type is Bar
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
index 7d02a0606fc..0711af1cad4 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.current.stderr
@@ -1,18 +1,18 @@
-error: item does not constrain `A::{opaque#0}`, but has it in its signature
-  --> $DIR/two_tait_defining_each_other2.rs:11:4
+error: item does not constrain `A::{opaque#0}`
+  --> $DIR/two_tait_defining_each_other2.rs:12:4
    |
 LL | fn muh(x: A) -> B {
    |    ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/two_tait_defining_each_other2.rs:6:10
    |
 LL | type A = impl Foo;
    |          ^^^^^^^^
 
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other2.rs:14:5
+  --> $DIR/two_tait_defining_each_other2.rs:15:5
    |
 LL |     x // B's hidden type is A (opaquely)
    |     ^ one of the two opaque types used here has to be outside its defining scope
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
index 5316160125b..1a4c0f5f7ee 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.next.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `_ == A`
-  --> $DIR/two_tait_defining_each_other2.rs:11:8
+  --> $DIR/two_tait_defining_each_other2.rs:12:8
    |
 LL | fn muh(x: A) -> B {
    |        ^ cannot satisfy `_ == A`
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other2.rs b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
index 1681b019418..a3223b07a7e 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other2.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other2.rs
@@ -8,6 +8,7 @@ type B = impl Foo;
 
 trait Foo {}
 
+#[define_opaque(A, B)]
 fn muh(x: A) -> B {
     //[current]~^ ERROR: item does not constrain `A::{opaque#0}`
     //[next]~^^ ERROR: cannot satisfy `_ == A`
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
index fa353a77536..7b0003ff59b 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
+++ b/tests/ui/impl-trait/two_tait_defining_each_other3.current.stderr
@@ -1,5 +1,5 @@
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/two_tait_defining_each_other3.rs:14:16
+  --> $DIR/two_tait_defining_each_other3.rs:15:16
    |
 LL |         return x;  // B's hidden type is A (opaquely)
    |                ^ one of the two opaque types used here has to be outside its defining scope
diff --git a/tests/ui/impl-trait/two_tait_defining_each_other3.rs b/tests/ui/impl-trait/two_tait_defining_each_other3.rs
index 33695d8ed80..ec3cd58a3a5 100644
--- a/tests/ui/impl-trait/two_tait_defining_each_other3.rs
+++ b/tests/ui/impl-trait/two_tait_defining_each_other3.rs
@@ -9,6 +9,7 @@ type B = impl Foo;
 
 trait Foo {}
 
+#[define_opaque(A, B)]
 fn muh(x: A) -> B {
     if false {
         return x;  // B's hidden type is A (opaquely)
diff --git a/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs
index 4879d2db40b..77b2407e304 100644
--- a/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs
+++ b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.rs
@@ -9,6 +9,7 @@ fn main() {
     //~^ ERROR: item does not constrain
     type Existential = impl Debug;
 
+    #[define_opaque(Existential)]
     fn f() -> Existential {}
     println!("{:?}", f());
 }
diff --git a/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.stderr b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.stderr
index 7744fa2f2ae..0877b4b71be 100644
--- a/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.stderr
+++ b/tests/ui/impl-trait/type-alias-impl-trait-in-fn-body.stderr
@@ -1,11 +1,11 @@
-error: item does not constrain `Existential::{opaque#0}`, but has it in its signature
+error: item does not constrain `Existential::{opaque#0}`
   --> $DIR/type-alias-impl-trait-in-fn-body.rs:8:4
    |
 LL | fn main() {
    |    ^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/type-alias-impl-trait-in-fn-body.rs:10:24
    |
 LL |     type Existential = impl Debug;
diff --git a/tests/ui/impl-trait/where-allowed.rs b/tests/ui/impl-trait/where-allowed.rs
index 3f435f0f443..1c3c66c537f 100644
--- a/tests/ui/impl-trait/where-allowed.rs
+++ b/tests/ui/impl-trait/where-allowed.rs
@@ -157,6 +157,7 @@ extern "C" fn in_extern_fn_return() -> impl Debug {
 
 type InTypeAlias<R> = impl Debug;
 //~^ ERROR `impl Trait` in type aliases is unstable
+//~| ERROR unconstrained opaque type
 
 type InReturnInTypeAlias<R> = fn() -> impl Debug;
 //~^ ERROR `impl Trait` is not allowed in `fn` pointer
diff --git a/tests/ui/impl-trait/where-allowed.stderr b/tests/ui/impl-trait/where-allowed.stderr
index ebce9b7e445..052ae5a9931 100644
--- a/tests/ui/impl-trait/where-allowed.stderr
+++ b/tests/ui/impl-trait/where-allowed.stderr
@@ -37,7 +37,7 @@ LL | type InTypeAlias<R> = impl Debug;
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: `impl Trait` in type aliases is unstable
-  --> $DIR/where-allowed.rs:161:39
+  --> $DIR/where-allowed.rs:162:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
@@ -199,7 +199,7 @@ LL |     fn in_foreign_return() -> impl Debug;
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in `fn` pointer return types
-  --> $DIR/where-allowed.rs:161:39
+  --> $DIR/where-allowed.rs:162:39
    |
 LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    |                                       ^^^^^^^^^^
@@ -207,7 +207,7 @@ LL | type InReturnInTypeAlias<R> = fn() -> impl Debug;
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in traits
-  --> $DIR/where-allowed.rs:166:16
+  --> $DIR/where-allowed.rs:167:16
    |
 LL | impl PartialEq<impl Debug> for () {
    |                ^^^^^^^^^^
@@ -215,7 +215,7 @@ LL | impl PartialEq<impl Debug> for () {
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in impl headers
-  --> $DIR/where-allowed.rs:171:24
+  --> $DIR/where-allowed.rs:172:24
    |
 LL | impl PartialEq<()> for impl Debug {
    |                        ^^^^^^^^^^
@@ -223,7 +223,7 @@ LL | impl PartialEq<()> for impl Debug {
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in impl headers
-  --> $DIR/where-allowed.rs:176:6
+  --> $DIR/where-allowed.rs:177:6
    |
 LL | impl impl Debug {
    |      ^^^^^^^^^^
@@ -231,7 +231,7 @@ LL | impl impl Debug {
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in impl headers
-  --> $DIR/where-allowed.rs:182:24
+  --> $DIR/where-allowed.rs:183:24
    |
 LL | impl InInherentImplAdt<impl Debug> {
    |                        ^^^^^^^^^^
@@ -239,7 +239,7 @@ LL | impl InInherentImplAdt<impl Debug> {
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in bounds
-  --> $DIR/where-allowed.rs:188:11
+  --> $DIR/where-allowed.rs:189:11
    |
 LL |     where impl Debug: Debug
    |           ^^^^^^^^^^
@@ -247,7 +247,7 @@ LL |     where impl Debug: Debug
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in bounds
-  --> $DIR/where-allowed.rs:195:15
+  --> $DIR/where-allowed.rs:196:15
    |
 LL |     where Vec<impl Debug>: Debug
    |               ^^^^^^^^^^
@@ -255,7 +255,7 @@ LL |     where Vec<impl Debug>: Debug
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in bounds
-  --> $DIR/where-allowed.rs:202:24
+  --> $DIR/where-allowed.rs:203:24
    |
 LL |     where T: PartialEq<impl Debug>
    |                        ^^^^^^^^^^
@@ -263,7 +263,7 @@ LL |     where T: PartialEq<impl Debug>
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in the parameters of `Fn` trait bounds
-  --> $DIR/where-allowed.rs:209:17
+  --> $DIR/where-allowed.rs:210:17
    |
 LL |     where T: Fn(impl Debug)
    |                 ^^^^^^^^^^
@@ -271,7 +271,7 @@ LL |     where T: Fn(impl Debug)
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in the return type of `Fn` trait bounds
-  --> $DIR/where-allowed.rs:216:22
+  --> $DIR/where-allowed.rs:217:22
    |
 LL |     where T: Fn() -> impl Debug
    |                      ^^^^^^^^^^
@@ -279,7 +279,7 @@ LL |     where T: Fn() -> impl Debug
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:222:40
+  --> $DIR/where-allowed.rs:223:40
    |
 LL | struct InStructGenericParamDefault<T = impl Debug>(T);
    |                                        ^^^^^^^^^^
@@ -287,7 +287,7 @@ LL | struct InStructGenericParamDefault<T = impl Debug>(T);
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:226:36
+  --> $DIR/where-allowed.rs:227:36
    |
 LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
    |                                    ^^^^^^^^^^
@@ -295,7 +295,7 @@ LL | enum InEnumGenericParamDefault<T = impl Debug> { Variant(T) }
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:230:38
+  --> $DIR/where-allowed.rs:231:38
    |
 LL | trait InTraitGenericParamDefault<T = impl Debug> {}
    |                                      ^^^^^^^^^^
@@ -303,7 +303,7 @@ LL | trait InTraitGenericParamDefault<T = impl Debug> {}
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:234:41
+  --> $DIR/where-allowed.rs:235:41
    |
 LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
    |                                         ^^^^^^^^^^
@@ -311,7 +311,7 @@ LL | type InTypeAliasGenericParamDefault<T = impl Debug> = T;
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:238:11
+  --> $DIR/where-allowed.rs:239:11
    |
 LL | impl <T = impl Debug> T {}
    |           ^^^^^^^^^^
@@ -319,7 +319,7 @@ LL | impl <T = impl Debug> T {}
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in generic parameter defaults
-  --> $DIR/where-allowed.rs:245:40
+  --> $DIR/where-allowed.rs:246:40
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                        ^^^^^^^^^^
@@ -327,7 +327,7 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = note: `impl Trait` is only allowed in arguments and return types of functions and methods
 
 error[E0562]: `impl Trait` is not allowed in the type of variable bindings
-  --> $DIR/where-allowed.rs:251:29
+  --> $DIR/where-allowed.rs:252:29
    |
 LL |     let _in_local_variable: impl Fn() = || {};
    |                             ^^^^^^^^^
@@ -338,7 +338,7 @@ LL |     let _in_local_variable: impl Fn() = || {};
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0562]: `impl Trait` is not allowed in closure return types
-  --> $DIR/where-allowed.rs:253:46
+  --> $DIR/where-allowed.rs:254:46
    |
 LL |     let _in_return_in_local_variable = || -> impl Fn() { || {} };
    |                                              ^^^^^^^^^
@@ -369,7 +369,7 @@ LL +     fn in_trait_impl_return() -> <() as DummyTrait>::Out { () }
    |
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:245:36
+  --> $DIR/where-allowed.rs:246:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^^^^^^^^^^^^^^
@@ -379,7 +379,7 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    = note: `#[deny(invalid_type_param_default)]` on by default
 
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:238:7
+  --> $DIR/where-allowed.rs:239:7
    |
 LL | impl <T = impl Debug> T {}
    |       ^^^^^^^^^^^^^^
@@ -408,7 +408,7 @@ LL | fn in_impl_Fn_return_in_return() -> &'static impl Fn() -> impl Debug { pani
              where Args: Tuple, F: Fn<Args>, A: Allocator, F: ?Sized;
 
 error[E0118]: no nominal type found for inherent implementation
-  --> $DIR/where-allowed.rs:238:1
+  --> $DIR/where-allowed.rs:239:1
    |
 LL | impl <T = impl Debug> T {}
    | ^^^^^^^^^^^^^^^^^^^^^^^ impl requires a nominal type
@@ -423,13 +423,21 @@ LL |     type Out = impl Debug;
    |
    = note: `Out` must be used in combination with a concrete type within the same impl
 
-error: aborting due to 49 previous errors
+error: unconstrained opaque type
+  --> $DIR/where-allowed.rs:158:23
+   |
+LL | type InTypeAlias<R> = impl Debug;
+   |                       ^^^^^^^^^^
+   |
+   = note: `InTypeAlias` must be used in combination with a concrete type within the same crate
+
+error: aborting due to 50 previous errors
 
 Some errors have detailed explanations: E0053, E0118, E0283, E0562, E0658, E0666.
 For more information about an error, try `rustc --explain E0053`.
 Future incompatibility report: Future breakage diagnostic:
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:245:36
+  --> $DIR/where-allowed.rs:246:36
    |
 LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
    |                                    ^^^^^^^^^^^^^^
@@ -440,7 +448,7 @@ LL | fn in_method_generic_param_default<T = impl Debug>(_: T) {}
 
 Future breakage diagnostic:
 error: defaults for type parameters are only allowed in `struct`, `enum`, `type`, or `trait` definitions
-  --> $DIR/where-allowed.rs:238:7
+  --> $DIR/where-allowed.rs:239:7
    |
 LL | impl <T = impl Debug> T {}
    |       ^^^^^^^^^^^^^^
diff --git a/tests/ui/implied-bounds/dyn-erasure-tait.rs b/tests/ui/implied-bounds/dyn-erasure-tait.rs
index 4766d221d67..1744e529393 100644
--- a/tests/ui/implied-bounds/dyn-erasure-tait.rs
+++ b/tests/ui/implied-bounds/dyn-erasure-tait.rs
@@ -14,6 +14,7 @@ type T<'lt> = &'lt str;
 
 type F<'a, 'b> = impl 'static + Fn(T<'a>) -> T<'b>;
 
+#[define_opaque(F)]
 fn helper<'a, 'b>(_: [&'b &'a (); 0]) -> F<'a, 'b> {
     |x: T<'a>| -> T<'b> { x } // this should *not* be `: 'static`
 }
diff --git a/tests/ui/layout/debug.rs b/tests/ui/layout/debug.rs
index b87a1d2031d..90e3c58dad7 100644
--- a/tests/ui/layout/debug.rs
+++ b/tests/ui/layout/debug.rs
@@ -18,6 +18,7 @@ type Test = Result<i32, i32>; //~ ERROR: layout_of
 
 #[rustc_layout(debug)]
 type T = impl std::fmt::Debug; //~ ERROR: layout_of
+#[define_opaque(T)]
 fn f() -> T {
     0i32
 }
diff --git a/tests/ui/layout/debug.stderr b/tests/ui/layout/debug.stderr
index 80b35ff6ad4..abaa16cdefa 100644
--- a/tests/ui/layout/debug.stderr
+++ b/tests/ui/layout/debug.stderr
@@ -1,5 +1,5 @@
 error: unions cannot have zero fields
-  --> $DIR/debug.rs:83:1
+  --> $DIR/debug.rs:84:1
    |
 LL | union EmptyUnion {}
    | ^^^^^^^^^^^^^^^^^^^
@@ -372,7 +372,7 @@ error: layout_of(V) = Layout {
            unadjusted_abi_align: Align(2 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:26:1
+  --> $DIR/debug.rs:27:1
    |
 LL | pub union V {
    | ^^^^^^^^^^^
@@ -398,7 +398,7 @@ error: layout_of(W) = Layout {
            unadjusted_abi_align: Align(2 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:32:1
+  --> $DIR/debug.rs:33:1
    |
 LL | pub union W {
    | ^^^^^^^^^^^
@@ -424,7 +424,7 @@ error: layout_of(Y) = Layout {
            unadjusted_abi_align: Align(2 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:38:1
+  --> $DIR/debug.rs:39:1
    |
 LL | pub union Y {
    | ^^^^^^^^^^^
@@ -450,7 +450,7 @@ error: layout_of(P1) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:45:1
+  --> $DIR/debug.rs:46:1
    |
 LL | union P1 { x: u32 }
    | ^^^^^^^^
@@ -476,7 +476,7 @@ error: layout_of(P2) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:49:1
+  --> $DIR/debug.rs:50:1
    |
 LL | union P2 { x: (u32, u32) }
    | ^^^^^^^^
@@ -502,7 +502,7 @@ error: layout_of(P3) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:57:1
+  --> $DIR/debug.rs:58:1
    |
 LL | union P3 { x: F32x4 }
    | ^^^^^^^^
@@ -528,7 +528,7 @@ error: layout_of(P4) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:61:1
+  --> $DIR/debug.rs:62:1
    |
 LL | union P4 { x: E }
    | ^^^^^^^^
@@ -559,7 +559,7 @@ error: layout_of(P5) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:65:1
+  --> $DIR/debug.rs:66:1
    |
 LL | union P5 { zst: [u16; 0], byte: u8 }
    | ^^^^^^^^
@@ -590,19 +590,19 @@ error: layout_of(MaybeUninit<u8>) = Layout {
            unadjusted_abi_align: Align(1 bytes),
            randomization_seed: $SEED,
        }
-  --> $DIR/debug.rs:68:1
+  --> $DIR/debug.rs:69:1
    |
 LL | type X = std::mem::MaybeUninit<u8>;
    | ^^^^^^
 
 error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
-  --> $DIR/debug.rs:71:1
+  --> $DIR/debug.rs:72:1
    |
 LL | const C: () = ();
    | ^^^^^^^^^^^
 
 error[E0277]: the size for values of type `str` cannot be known at compilation time
-  --> $DIR/debug.rs:79:19
+  --> $DIR/debug.rs:80:19
    |
 LL | type Impossible = (str, str);
    |                   ^^^^^^^^^^ doesn't have a size known at compile-time
@@ -611,19 +611,19 @@ LL | type Impossible = (str, str);
    = note: only the last element of a tuple may have a dynamically sized type
 
 error: the type has an unknown layout
-  --> $DIR/debug.rs:83:1
+  --> $DIR/debug.rs:84:1
    |
 LL | union EmptyUnion {}
    | ^^^^^^^^^^^^^^^^
 
 error: the type `T` does not have a fixed layout
-  --> $DIR/debug.rs:89:1
+  --> $DIR/debug.rs:90:1
    |
 LL | type TooGeneric<T> = T;
    | ^^^^^^^^^^^^^^^^^^
 
 error: `#[rustc_layout]` can only be applied to `struct`/`enum`/`union` declarations and type aliases
-  --> $DIR/debug.rs:75:5
+  --> $DIR/debug.rs:76:5
    |
 LL |     const C: () = ();
    |     ^^^^^^^^^^^
diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.rs b/tests/ui/lazy-type-alias-impl-trait/branches.rs
index 95239e2e341..30f9c08a27f 100644
--- a/tests/ui/lazy-type-alias-impl-trait/branches.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/branches.rs
@@ -2,16 +2,14 @@
 
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
-    if b {
-        vec![42_i32]
-    } else {
-        std::iter::empty().collect()
-    }
+    if b { vec![42_i32] } else { std::iter::empty().collect() }
 }
 
 type Bar = impl std::fmt::Debug;
 
+#[define_opaque(Bar)]
 fn bar(b: bool) -> Bar {
     let x: Bar = if b {
         vec![42_i32]
diff --git a/tests/ui/lazy-type-alias-impl-trait/branches.stderr b/tests/ui/lazy-type-alias-impl-trait/branches.stderr
index 9e937622775..0cc727bc3de 100644
--- a/tests/ui/lazy-type-alias-impl-trait/branches.stderr
+++ b/tests/ui/lazy-type-alias-impl-trait/branches.stderr
@@ -1,5 +1,5 @@
 error[E0277]: a value of type `Bar` cannot be built from an iterator over elements of type `_`
-  --> $DIR/branches.rs:19:28
+  --> $DIR/branches.rs:17:28
    |
 LL |         std::iter::empty().collect()
    |                            ^^^^^^^ value of type `Bar` cannot be built from `std::iter::Iterator<Item=_>`
diff --git a/tests/ui/lazy-type-alias-impl-trait/branches2.rs b/tests/ui/lazy-type-alias-impl-trait/branches2.rs
index 467400f1c24..35b76845c85 100644
--- a/tests/ui/lazy-type-alias-impl-trait/branches2.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/branches2.rs
@@ -4,20 +4,13 @@
 
 type Foo = impl std::iter::FromIterator<i32> + PartialEq<Vec<i32>> + std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
-    if b {
-        vec![42_i32]
-    } else {
-        std::iter::empty().collect()
-    }
+    if b { vec![42_i32] } else { std::iter::empty().collect() }
 }
 
 fn bar(b: bool) -> impl PartialEq<Vec<i32>> + std::fmt::Debug {
-    if b {
-        vec![42_i32]
-    } else {
-        std::iter::empty().collect()
-    }
+    if b { vec![42_i32] } else { std::iter::empty().collect() }
 }
 
 fn main() {
diff --git a/tests/ui/lazy-type-alias-impl-trait/branches3.rs b/tests/ui/lazy-type-alias-impl-trait/branches3.rs
index 30c0af8a5dc..cff7a0b437f 100644
--- a/tests/ui/lazy-type-alias-impl-trait/branches3.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/branches3.rs
@@ -3,6 +3,7 @@
 type Foo = impl for<'a> FnOnce(&'a str) -> usize;
 type Bar = impl FnOnce(&'static str) -> usize;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     if true {
         |s| s.len() //~ ERROR type annotations needed
@@ -10,6 +11,8 @@ fn foo() -> Foo {
         panic!()
     }
 }
+
+#[define_opaque(Bar)]
 fn bar() -> Bar {
     if true {
         |s| s.len() //~ ERROR type annotations needed
diff --git a/tests/ui/lazy-type-alias-impl-trait/branches3.stderr b/tests/ui/lazy-type-alias-impl-trait/branches3.stderr
index fe2631f9474..117d189867b 100644
--- a/tests/ui/lazy-type-alias-impl-trait/branches3.stderr
+++ b/tests/ui/lazy-type-alias-impl-trait/branches3.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/branches3.rs:8:10
+  --> $DIR/branches3.rs:9:10
    |
 LL |         |s| s.len()
    |          ^  - type must be known at this point
@@ -10,7 +10,7 @@ LL |         |s: /* Type */| s.len()
    |           ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/branches3.rs:15:10
+  --> $DIR/branches3.rs:18:10
    |
 LL |         |s| s.len()
    |          ^  - type must be known at this point
@@ -21,7 +21,7 @@ LL |         |s: /* Type */| s.len()
    |           ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/branches3.rs:23:10
+  --> $DIR/branches3.rs:26:10
    |
 LL |         |s| s.len()
    |          ^  - type must be known at this point
@@ -32,7 +32,7 @@ LL |         |s: /* Type */| s.len()
    |           ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/branches3.rs:30:10
+  --> $DIR/branches3.rs:33:10
    |
 LL |         |s| s.len()
    |          ^  - type must be known at this point
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion.rs b/tests/ui/lazy-type-alias-impl-trait/recursion.rs
index 51933560599..33dbf8d0280 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion.rs
@@ -4,9 +4,10 @@
 
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
     if b {
-        return 42
+        return 42;
     }
     let x: u32 = foo(false);
     99
@@ -14,7 +15,7 @@ fn foo(b: bool) -> Foo {
 
 fn bar(b: bool) -> impl std::fmt::Debug {
     if b {
-        return 42
+        return 42;
     }
     let x: u32 = bar(false);
     99
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion2.rs b/tests/ui/lazy-type-alias-impl-trait/recursion2.rs
index e14da32e116..b28a95c53f4 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion2.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion2.rs
@@ -4,6 +4,7 @@
 
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
     if b {
         return vec![];
@@ -14,7 +15,7 @@ fn foo(b: bool) -> Foo {
 
 fn bar(b: bool) -> impl std::fmt::Debug {
     if b {
-        return vec![]
+        return vec![];
     }
     let x: Vec<i32> = bar(false);
     std::iter::empty().collect()
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.rs b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs
index 7f1cedae068..0b15484f7ef 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion3.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.rs
@@ -2,9 +2,10 @@
 
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
     if b {
-        return 42
+        return 42;
     }
     let x: u32 = foo(false) + 42; //~ ERROR cannot add
     99
@@ -12,7 +13,7 @@ fn foo(b: bool) -> Foo {
 
 fn bar(b: bool) -> impl std::fmt::Debug {
     if b {
-        return 42
+        return 42;
     }
     let x: u32 = bar(false) + 42; //~ ERROR cannot add
     99
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr b/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr
index e1d5cafedc8..0cbedfb69f8 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion3.stderr
@@ -1,5 +1,5 @@
 error[E0369]: cannot add `{integer}` to `Foo`
-  --> $DIR/recursion3.rs:9:29
+  --> $DIR/recursion3.rs:10:29
    |
 LL |     let x: u32 = foo(false) + 42;
    |                  ---------- ^ -- {integer}
@@ -7,7 +7,7 @@ LL |     let x: u32 = foo(false) + 42;
    |                  Foo
 
 error[E0369]: cannot add `{integer}` to `impl Debug`
-  --> $DIR/recursion3.rs:17:29
+  --> $DIR/recursion3.rs:18:29
    |
 LL |     let x: u32 = bar(false) + 42;
    |                  ---------- ^ -- {integer}
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion4.rs b/tests/ui/lazy-type-alias-impl-trait/recursion4.rs
index 57dd7fb067c..892e72e2335 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion4.rs
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion4.rs
@@ -2,6 +2,7 @@
 
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
     if b {
         return vec![];
diff --git a/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr b/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr
index d8ac39a4f27..b04bf6b9987 100644
--- a/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr
+++ b/tests/ui/lazy-type-alias-impl-trait/recursion4.stderr
@@ -1,5 +1,5 @@
 error[E0277]: a value of type `Foo` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:10:28
+  --> $DIR/recursion4.rs:11:28
    |
 LL |     x = std::iter::empty().collect();
    |                            ^^^^^^^ value of type `Foo` cannot be built from `std::iter::Iterator<Item=_>`
@@ -9,7 +9,7 @@ note: required by a bound in `collect`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
 error[E0277]: a value of type `impl Debug` cannot be built from an iterator over elements of type `_`
-  --> $DIR/recursion4.rs:19:28
+  --> $DIR/recursion4.rs:20:28
    |
 LL |     x = std::iter::empty().collect();
    |                            ^^^^^^^ value of type `impl Debug` cannot be built from `std::iter::Iterator<Item=_>`
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
index 192b5eebdaa..4f1d339bc99 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.next.stderr
@@ -1,8 +1,8 @@
-error[E0275]: overflow evaluating the requirement `Loop == _`
+error[E0271]: type mismatch resolving `Loop normalizes-to _`
   --> $DIR/inherent-impls-overflow.rs:10:6
    |
 LL | impl Loop {}
-   |      ^^^^
+   |      ^^^^ types differ
 
 error: type parameter `T` is only used recursively
   --> $DIR/inherent-impls-overflow.rs:14:24
@@ -36,4 +36,5 @@ LL | impl Poly0<()> {}
 
 error: aborting due to 4 previous errors
 
-For more information about this error, try `rustc --explain E0275`.
+Some errors have detailed explanations: E0271, E0275.
+For more information about an error, try `rustc --explain E0271`.
diff --git a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
index 1397695a3fe..0d5ec7d1530 100644
--- a/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
+++ b/tests/ui/lazy-type-alias/inherent-impls-overflow.rs
@@ -9,7 +9,7 @@ type Loop = Loop; //[current]~ ERROR overflow normalizing the type alias `Loop`
 
 impl Loop {}
 //[current]~^ ERROR overflow normalizing the type alias `Loop`
-//[next]~^^ ERROR overflow evaluating the requirement `Loop == _`
+//[next]~^^ ERROR type mismatch resolving `Loop normalizes-to _`
 
 type Poly0<T> = Poly1<(T,)>;
 //[current]~^ ERROR overflow normalizing the type alias `Poly0<(((((((...,),),),),),),)>`
diff --git a/tests/ui/linking/no-gc-encapsulation-symbols.rs b/tests/ui/linking/no-gc-encapsulation-symbols.rs
new file mode 100644
index 00000000000..36d69969199
--- /dev/null
+++ b/tests/ui/linking/no-gc-encapsulation-symbols.rs
@@ -0,0 +1,25 @@
+// This test checks that encapsulation symbols are not garbage collected by the linker.
+// LLD will remove them by default, so this test checks that we pass `-znostart-stop-gc` to LLD
+// to avoid that behavior. Without that flag, the test should fail.
+// This test is inspired by the behavior of the linkme crate.
+//
+//@ build-pass
+//@ only-x86_64-unknown-linux-gnu
+
+unsafe extern "Rust" {
+    // The __start_ section name is magical for the linker,
+    // It will put link sections named EXTERNFNS after it.
+    #[link_name = "__start_EXTERNFNS"]
+    static SECTION_START: fn();
+}
+
+#[used]
+#[unsafe(link_section = "EXTERNFNS")]
+static EXTERN_FN_LOCAL: fn() = extern_fn;
+
+fn extern_fn() {}
+
+fn main() {
+    // We need to reference the SECTION_START symbol to avoid it being garbage collected
+    let slice = unsafe { SECTION_START };
+}
diff --git a/tests/ui/lint/invalid_from_utf8.rs b/tests/ui/lint/invalid_from_utf8.rs
index 87a906761c0..cbc1d8e9045 100644
--- a/tests/ui/lint/invalid_from_utf8.rs
+++ b/tests/ui/lint/invalid_from_utf8.rs
@@ -128,18 +128,21 @@ pub fn from_utf8() {
 }
 
 pub fn from_utf8_with_indirections() {
-    let mut a = [99, 108, 130, 105, 112, 112, 121];
-    std::str::from_utf8_mut(&mut a);
-    //~^ WARN calls to `std::str::from_utf8_mut`
-    str::from_utf8_mut(&mut a);
-    //~^ WARN calls to `str::from_utf8_mut`
-    let mut b = &mut a;
-    let mut c = b;
-    std::str::from_utf8_mut(c);
-    //~^ WARN calls to `std::str::from_utf8_mut`
-    str::from_utf8_mut(c);
-    //~^ WARN calls to `str::from_utf8_mut`
-    let mut c = &[99, 108, 130, 105, 112, 112, 121];
+    // NOTE: We used to lint on the patterns below, but due to the
+    // binding being mutable it could be changed between the
+    // declaration and the call and that would have created a
+    // false-positive, so until we can reliably avoid those false
+    // postive we don't lint on them. Example of FP below.
+    //
+    // let mut a = [99, 108, 130, 105, 112, 112, 121];
+    // std::str::from_utf8_mut(&mut a);
+    // str::from_utf8_mut(&mut a);
+    // let mut b = &mut a;
+    // let mut c = b;
+    // std::str::from_utf8_mut(c);
+    // str::from_utf8_mut(c);
+
+    let c = &[99, 108, 130, 105, 112, 112, 121];
     std::str::from_utf8(c);
     //~^ WARN calls to `std::str::from_utf8`
     str::from_utf8(c);
@@ -164,6 +167,20 @@ pub fn from_utf8_with_indirections() {
     //~^ WARN calls to `std::str::from_utf8`
     str::from_utf8(INVALID_4);
     //~^ WARN calls to `str::from_utf8`
+
+    let mut a = [99, 108, 130, 105, 112, 112, 121]; // invalid
+    loop {
+        a = [99, 108, 130, 105, 112, 112, 121]; // still invalid, but too complex
+        break;
+    }
+    std::str::from_utf8_mut(&mut a);
+
+    let mut a = [99, 108, 130, 105, 112, 112]; // invalid
+    loop {
+        a = *b"clippy"; // valid
+        break;
+    }
+    std::str::from_utf8_mut(&mut a);
 }
 
 fn main() {}
diff --git a/tests/ui/lint/invalid_from_utf8.stderr b/tests/ui/lint/invalid_from_utf8.stderr
index 3cd4d227fc2..26bee5c4038 100644
--- a/tests/ui/lint/invalid_from_utf8.stderr
+++ b/tests/ui/lint/invalid_from_utf8.stderr
@@ -202,60 +202,25 @@ LL |         str::from_utf8(concat_bytes!(b"cl", b"\x82ippy"));
    |                        |
    |                        the literal was valid UTF-8 up to the 2 bytes
 
-warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:132:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-LL |     std::str::from_utf8_mut(&mut a);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:134:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     str::from_utf8_mut(&mut a);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `std::str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:138:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     std::str::from_utf8_mut(c);
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-warning: calls to `str::from_utf8_mut` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:140:5
-   |
-LL |     let mut a = [99, 108, 130, 105, 112, 112, 121];
-   |                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
-...
-LL |     str::from_utf8_mut(c);
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:143:5
+  --> $DIR/invalid_from_utf8.rs:146:5
    |
-LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
-   |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
+LL |     let c = &[99, 108, 130, 105, 112, 112, 121];
+   |              ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
 LL |     std::str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:145:5
+  --> $DIR/invalid_from_utf8.rs:148:5
    |
-LL |     let mut c = &[99, 108, 130, 105, 112, 112, 121];
-   |                  ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
+LL |     let c = &[99, 108, 130, 105, 112, 112, 121];
+   |              ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
 ...
 LL |     str::from_utf8(c);
    |     ^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:148:5
+  --> $DIR/invalid_from_utf8.rs:151:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -263,7 +228,7 @@ LL |     std::str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:150:5
+  --> $DIR/invalid_from_utf8.rs:153:5
    |
 LL |     const INVALID_1: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -272,7 +237,7 @@ LL |     str::from_utf8(&INVALID_1);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:153:5
+  --> $DIR/invalid_from_utf8.rs:156:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -280,7 +245,7 @@ LL |     std::str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:155:5
+  --> $DIR/invalid_from_utf8.rs:158:5
    |
 LL |     static INVALID_2: [u8; 7] = [99, 108, 130, 105, 112, 112, 121];
    |                                 ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -289,7 +254,7 @@ LL |     str::from_utf8(&INVALID_2);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:158:5
+  --> $DIR/invalid_from_utf8.rs:161:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -297,7 +262,7 @@ LL |     std::str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:160:5
+  --> $DIR/invalid_from_utf8.rs:163:5
    |
 LL |     const INVALID_3: &'static [u8; 7] = &[99, 108, 130, 105, 112, 112, 121];
    |                                          ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -306,7 +271,7 @@ LL |     str::from_utf8(INVALID_3);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `std::str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:163:5
+  --> $DIR/invalid_from_utf8.rs:166:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -314,7 +279,7 @@ LL |     std::str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: calls to `str::from_utf8` with an invalid literal always return an error
-  --> $DIR/invalid_from_utf8.rs:165:5
+  --> $DIR/invalid_from_utf8.rs:168:5
    |
 LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 121] };
    |                                            ---------------------------------- the literal was valid UTF-8 up to the 2 bytes
@@ -322,5 +287,5 @@ LL |     const INVALID_4: &'static [u8; 7] = { &[99, 108, 130, 105, 112, 112, 12
 LL |     str::from_utf8(INVALID_4);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-warning: 38 warnings emitted
+warning: 34 warnings emitted
 
diff --git a/tests/ui/lint/issue-99387.rs b/tests/ui/lint/issue-99387.rs
index 6f082239456..b40d31384be 100644
--- a/tests/ui/lint/issue-99387.rs
+++ b/tests/ui/lint/issue-99387.rs
@@ -6,6 +6,7 @@
 
 pub type Successors<'a> = impl Iterator<Item = &'a ()>;
 
+#[define_opaque(Successors)]
 pub fn f<'a>() -> Successors<'a> {
     None.into_iter()
 }
diff --git a/tests/ui/lint/issue-99387.stderr b/tests/ui/lint/issue-99387.stderr
index 4eee4f36392..0d9ded23c78 100644
--- a/tests/ui/lint/issue-99387.stderr
+++ b/tests/ui/lint/issue-99387.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-99387.rs:22:5
+  --> $DIR/issue-99387.rs:23:5
    |
 LL | pub type Successors<'a> = impl Iterator<Item = &'a ()>;
    |                           ---------------------------- the expected opaque type
@@ -11,8 +11,8 @@ LL |     None.into_iter()
    |
    = note: expected opaque type `Successors<'a>`
                    found struct `std::option::IntoIter<_>`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-99387.rs:21:8
+note: this item must have a `#[define_opaque(Successors)]` attribute to be able to define hidden types
+  --> $DIR/issue-99387.rs:22:8
    |
 LL | pub fn ohno<'a>() -> <&'a () as Tr>::Item {
    |        ^^^^
diff --git a/tests/ui/lint/let_underscore/issue-119697-extra-let.rs b/tests/ui/lint/let_underscore/issue-119697-extra-let.rs
index 84abb933911..9782b3191fd 100644
--- a/tests/ui/lint/let_underscore/issue-119697-extra-let.rs
+++ b/tests/ui/lint/let_underscore/issue-119697-extra-let.rs
@@ -8,6 +8,7 @@ pub struct Foo {
 
 pub type Tait = impl Sized;
 
+#[define_opaque(Tait)]
 pub fn ice_cold(beverage: Tait) {
     // Must destructure at least one field of `Foo`
     let Foo { field } = beverage;
@@ -17,5 +18,4 @@ pub fn ice_cold(beverage: Tait) {
     let _ = field; //~ ERROR non-binding let on a type that has a destructor
 }
 
-
 pub fn main() {}
diff --git a/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr b/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr
index 3ff57ab441d..8d5deadd46e 100644
--- a/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr
+++ b/tests/ui/lint/let_underscore/issue-119697-extra-let.stderr
@@ -1,5 +1,5 @@
 error: non-binding let on a type that has a destructor
-  --> $DIR/issue-119697-extra-let.rs:15:5
+  --> $DIR/issue-119697-extra-let.rs:16:5
    |
 LL |     _ = field;
    |     ^^^^^^^^^
@@ -21,7 +21,7 @@ LL +     drop(field);
    |
 
 error: non-binding let on a type that has a destructor
-  --> $DIR/issue-119697-extra-let.rs:17:5
+  --> $DIR/issue-119697-extra-let.rs:18:5
    |
 LL |     let _ = field;
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/lint/lint-ctypes-73249-2.rs b/tests/ui/lint/lint-ctypes-73249-2.rs
index f30377d6c16..31af0e3d381 100644
--- a/tests/ui/lint/lint-ctypes-73249-2.rs
+++ b/tests/ui/lint/lint-ctypes-73249-2.rs
@@ -7,6 +7,7 @@ impl Baz for () {}
 
 type Qux = impl Baz;
 
+#[define_opaque(Qux)]
 fn assign() -> Qux {}
 
 trait Foo {
diff --git a/tests/ui/lint/lint-ctypes-73249-2.stderr b/tests/ui/lint/lint-ctypes-73249-2.stderr
index ef30a406969..2d0dfe94f09 100644
--- a/tests/ui/lint/lint-ctypes-73249-2.stderr
+++ b/tests/ui/lint/lint-ctypes-73249-2.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73249-2.rs:26:21
+  --> $DIR/lint-ctypes-73249-2.rs:27:21
    |
 LL |     fn lint_me() -> A<()>;
    |                     ^^^^^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes-73249-3.rs b/tests/ui/lint/lint-ctypes-73249-3.rs
index ef8ab7e03d2..8bdf536bf77 100644
--- a/tests/ui/lint/lint-ctypes-73249-3.rs
+++ b/tests/ui/lint/lint-ctypes-73249-3.rs
@@ -7,6 +7,7 @@ impl Baz for u32 {}
 
 type Qux = impl Baz;
 
+#[define_opaque(Qux)]
 fn assign() -> Qux {
     3
 }
diff --git a/tests/ui/lint/lint-ctypes-73249-3.stderr b/tests/ui/lint/lint-ctypes-73249-3.stderr
index e5607ba72e9..e1a313a2906 100644
--- a/tests/ui/lint/lint-ctypes-73249-3.stderr
+++ b/tests/ui/lint/lint-ctypes-73249-3.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73249-3.rs:20:25
+  --> $DIR/lint-ctypes-73249-3.rs:21:25
    |
 LL |     pub fn lint_me() -> A;
    |                         ^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes-73249-5.rs b/tests/ui/lint/lint-ctypes-73249-5.rs
index 083fb6c5fb1..cc6da59950d 100644
--- a/tests/ui/lint/lint-ctypes-73249-5.rs
+++ b/tests/ui/lint/lint-ctypes-73249-5.rs
@@ -7,6 +7,7 @@ impl Baz for u32 {}
 
 type Qux = impl Baz;
 
+#[define_opaque(Qux)]
 fn assign() -> Qux {
     3
 }
diff --git a/tests/ui/lint/lint-ctypes-73249-5.stderr b/tests/ui/lint/lint-ctypes-73249-5.stderr
index fcb106c485d..c4fa955de05 100644
--- a/tests/ui/lint/lint-ctypes-73249-5.stderr
+++ b/tests/ui/lint/lint-ctypes-73249-5.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73249-5.rs:20:25
+  --> $DIR/lint-ctypes-73249-5.rs:21:25
    |
 LL |     pub fn lint_me() -> A;
    |                         ^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes-73251-1.rs b/tests/ui/lint/lint-ctypes-73251-1.rs
index fc11f23a104..07ae05be69f 100644
--- a/tests/ui/lint/lint-ctypes-73251-1.rs
+++ b/tests/ui/lint/lint-ctypes-73251-1.rs
@@ -15,6 +15,7 @@ impl Foo for u32 {
     type Assoc = Qux;
 }
 
+#[define_opaque(Qux)]
 fn assign() -> Qux {
     1
 }
diff --git a/tests/ui/lint/lint-ctypes-73251-1.stderr b/tests/ui/lint/lint-ctypes-73251-1.stderr
index a3b3ebaac30..675a9de51cd 100644
--- a/tests/ui/lint/lint-ctypes-73251-1.stderr
+++ b/tests/ui/lint/lint-ctypes-73251-1.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `Qux`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73251-1.rs:23:21
+  --> $DIR/lint-ctypes-73251-1.rs:24:21
    |
 LL |     fn lint_me() -> <u32 as Foo>::Assoc;
    |                     ^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes-73251-2.rs b/tests/ui/lint/lint-ctypes-73251-2.rs
index fbe0a58f3b5..c47118672e0 100644
--- a/tests/ui/lint/lint-ctypes-73251-2.rs
+++ b/tests/ui/lint/lint-ctypes-73251-2.rs
@@ -24,10 +24,12 @@ type AliasA = impl TraitA<Assoc = u32>;
 
 type AliasB = impl TraitB<Assoc = AliasA>;
 
+#[define_opaque(AliasA)]
 fn use_of_a() -> AliasA {
     3
 }
 
+#[define_opaque(AliasB)]
 fn use_of_b() -> AliasB {
     3
 }
diff --git a/tests/ui/lint/lint-ctypes-73251-2.stderr b/tests/ui/lint/lint-ctypes-73251-2.stderr
index 40a9cd00c50..634950b29ed 100644
--- a/tests/ui/lint/lint-ctypes-73251-2.stderr
+++ b/tests/ui/lint/lint-ctypes-73251-2.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `AliasA`, which is not FFI-safe
-  --> $DIR/lint-ctypes-73251-2.rs:36:21
+  --> $DIR/lint-ctypes-73251-2.rs:38:21
    |
 LL |     fn lint_me() -> <AliasB as TraitB>::Assoc;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/lint/lint-ctypes-73251.rs b/tests/ui/lint/lint-ctypes-73251.rs
index 68eeb67deea..15c1dfcaabf 100644
--- a/tests/ui/lint/lint-ctypes-73251.rs
+++ b/tests/ui/lint/lint-ctypes-73251.rs
@@ -13,6 +13,7 @@ impl Foo for () {
 
 type Bar = impl Foo<Assoc = u32>;
 
+#[define_opaque(Bar)]
 fn assign() -> Bar {}
 
 extern "C" {
diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs
index c83bca4a4c5..dee77cf4873 100644
--- a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs
+++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.rs
@@ -25,10 +25,12 @@ type AliasA = impl TraitA<Assoc = u32>;
 
 type AliasB = impl TraitB;
 
+#[define_opaque(AliasA)]
 fn use_of_a() -> AliasA {
     3
 }
 
+#[define_opaque(AliasB)]
 fn use_of_b() -> AliasB {
     3
 }
diff --git a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr
index 9efc187833f..020eac4febb 100644
--- a/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr
+++ b/tests/ui/lint/opaque-ty-ffi-normalization-cycle.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `AliasB`, which is not FFI-safe
-  --> $DIR/opaque-ty-ffi-normalization-cycle.rs:37:21
+  --> $DIR/opaque-ty-ffi-normalization-cycle.rs:39:21
    |
 LL |     fn lint_me() -> <AliasB as TraitB>::Assoc;
    |                     ^^^^^^^^^^^^^^^^^^^^^^^^^ not FFI-safe
diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.rs b/tests/ui/lint/opaque-ty-ffi-unsafe.rs
index 5faeac9ed4c..97016267fa8 100644
--- a/tests/ui/lint/opaque-ty-ffi-unsafe.rs
+++ b/tests/ui/lint/opaque-ty-ffi-unsafe.rs
@@ -3,6 +3,7 @@
 
 type A = impl Fn();
 
+#[define_opaque(A)]
 pub(crate) fn ret_closure() -> A {
     || {}
 }
diff --git a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
index 7f5d1792bf1..5c52f702671 100644
--- a/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
+++ b/tests/ui/lint/opaque-ty-ffi-unsafe.stderr
@@ -1,5 +1,5 @@
 error: `extern` block uses type `A`, which is not FFI-safe
-  --> $DIR/opaque-ty-ffi-unsafe.rs:11:24
+  --> $DIR/opaque-ty-ffi-unsafe.rs:12:24
    |
 LL |     pub(crate) fn a(_: A);
    |                        ^ not FFI-safe
diff --git a/tests/ui/methods/opaque_param_in_ufc.rs b/tests/ui/methods/opaque_param_in_ufc.rs
index b170e6805f6..3b0c8b778ff 100644
--- a/tests/ui/methods/opaque_param_in_ufc.rs
+++ b/tests/ui/methods/opaque_param_in_ufc.rs
@@ -11,11 +11,13 @@ impl Foo<u32> {
 
 type Bar = impl Sized;
 
+#[define_opaque(Bar)]
 fn bar() -> Bar {
     42_u32
 }
 
 impl Foo<Bar> {
+    #[define_opaque(Bar)]
     fn foo() -> Bar {
         Self::method();
         Foo::<Bar>::method();
diff --git a/tests/ui/mir/issue-75053.rs b/tests/ui/mir/issue-75053.rs
index 38684f3548f..9b247fa5434 100644
--- a/tests/ui/mir/issue-75053.rs
+++ b/tests/ui/mir/issue-75053.rs
@@ -13,13 +13,11 @@ trait MyFrom<T>: Sized {
     fn my_from(value: T) -> Result<Self, Self::Error>;
 }
 
-mod f {
-    pub trait F {}
-    impl F for () {}
-    pub type DummyT<T> = impl F;
-    fn _dummy_t<T>() -> DummyT<T> {}
-}
-use f::*;
+pub trait F {}
+impl F for () {}
+pub type DummyT<T> = impl F;
+#[define_opaque(DummyT)]
+fn _dummy_t<T>() -> DummyT<T> {}
 
 struct Phantom1<T>(PhantomData<T>);
 struct Phantom2<T>(PhantomData<T>);
diff --git a/tests/ui/mir/issue-75053.stderr b/tests/ui/mir/issue-75053.stderr
index a464d3266f4..91032bc3797 100644
--- a/tests/ui/mir/issue-75053.stderr
+++ b/tests/ui/mir/issue-75053.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-75053.rs:49:1
+  --> $DIR/issue-75053.rs:47:1
    |
 LL | fn main() {
    | ^^^^^^^^^
diff --git a/tests/ui/never_type/impl_trait_fallback2.rs b/tests/ui/never_type/impl_trait_fallback2.rs
index 12c187b9e82..399bd72561b 100644
--- a/tests/ui/never_type/impl_trait_fallback2.rs
+++ b/tests/ui/never_type/impl_trait_fallback2.rs
@@ -12,11 +12,13 @@ fn should_ret_unit() -> impl T {
 
 type Foo = impl T;
 
+#[define_opaque(Foo)]
 fn a() -> Foo {
     //~^ ERROR `(): T` is not satisfied
     panic!()
 }
 
+#[define_opaque(Foo)]
 fn b() -> Foo {
     42
 }
diff --git a/tests/ui/never_type/impl_trait_fallback2.stderr b/tests/ui/never_type/impl_trait_fallback2.stderr
index 4c32dce465b..0f197aa5cc6 100644
--- a/tests/ui/never_type/impl_trait_fallback2.stderr
+++ b/tests/ui/never_type/impl_trait_fallback2.stderr
@@ -10,7 +10,7 @@ LL |     panic!()
    = help: the trait `T` is implemented for `i32`
 
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/impl_trait_fallback2.rs:15:11
+  --> $DIR/impl_trait_fallback2.rs:16:11
    |
 LL | fn a() -> Foo {
    |           ^^^ the trait `T` is not implemented for `()`
diff --git a/tests/ui/never_type/impl_trait_fallback3.rs b/tests/ui/never_type/impl_trait_fallback3.rs
index ed645b82394..3740aad73f0 100644
--- a/tests/ui/never_type/impl_trait_fallback3.rs
+++ b/tests/ui/never_type/impl_trait_fallback3.rs
@@ -8,6 +8,7 @@ trait T {
 
 type Foo = impl T;
 
+#[define_opaque(Foo)]
 fn a() -> Foo {
     //~^ ERROR the trait bound `(): T` is not satisfied
     // This is not a defining use, it doesn't actually constrain the opaque type.
diff --git a/tests/ui/never_type/impl_trait_fallback3.stderr b/tests/ui/never_type/impl_trait_fallback3.stderr
index fde8d0896dd..11425a74953 100644
--- a/tests/ui/never_type/impl_trait_fallback3.stderr
+++ b/tests/ui/never_type/impl_trait_fallback3.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): T` is not satisfied
-  --> $DIR/impl_trait_fallback3.rs:11:11
+  --> $DIR/impl_trait_fallback3.rs:12:11
    |
 LL | fn a() -> Foo {
    |           ^^^ the trait `T` is not implemented for `()`
diff --git a/tests/ui/never_type/impl_trait_fallback4.rs b/tests/ui/never_type/impl_trait_fallback4.rs
index fe62773fa02..2fa3d0028be 100644
--- a/tests/ui/never_type/impl_trait_fallback4.rs
+++ b/tests/ui/never_type/impl_trait_fallback4.rs
@@ -15,6 +15,7 @@ fn foo() -> impl T {
     panic!()
 }
 
+#[define_opaque(Foo)]
 fn a() -> Foo {
     foo()
 }
diff --git a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr
index d9710c6e6a2..9357a86c415 100644
--- a/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr
+++ b/tests/ui/patchable-function-entry/patchable-function-entry-attribute.stderr
@@ -20,7 +20,7 @@ error: unexpected parameter name
   --> $DIR/patchable-function-entry-attribute.rs:13:46
    |
 LL | #[patchable_function_entry(prefix_nops = 10, something = 0)]
-   |                                              ^^^^^^^^^^^^^ expected prefix_nops or entry_nops
+   |                                              ^^^^^^^^^^^^^ expected `prefix_nops` or `entry_nops`
 
 error: must specify at least one parameter
   --> $DIR/patchable-function-entry-attribute.rs:16:1
diff --git a/tests/ui/pattern/usefulness/impl-trait.rs b/tests/ui/pattern/usefulness/impl-trait.rs
index 16560a09267..47cee17b579 100644
--- a/tests/ui/pattern/usefulness/impl-trait.rs
+++ b/tests/ui/pattern/usefulness/impl-trait.rs
@@ -25,6 +25,7 @@ fn friend_of_return_never_rpit(x: Void) {
 }
 
 type T = impl Copy;
+#[define_opaque(T)]
 fn return_never_tait(x: Void) -> T {
     if false {
         match return_never_tait(x) {
@@ -88,6 +89,7 @@ fn inner_tuple() {
 }
 
 type U = impl Copy;
+#[define_opaque(U)]
 fn unify_never(x: Void, u: U) -> U {
     if false {
         match u {
@@ -98,6 +100,7 @@ fn unify_never(x: Void, u: U) -> U {
 }
 
 type V = impl Copy;
+#[define_opaque(V)]
 fn infer_in_match(x: Option<V>) {
     match x {
         None => {}
@@ -116,6 +119,7 @@ struct Rec<'a> {
     n: u32,
     w: Option<&'a W>,
 }
+#[define_opaque(W)]
 fn recursive_opaque() -> W {
     if false {
         match recursive_opaque() {
@@ -130,6 +134,7 @@ fn recursive_opaque() -> W {
 
 type X = impl Copy;
 struct SecretelyVoid(X);
+#[define_opaque(X)]
 fn nested_empty_opaque(x: Void) -> X {
     if false {
         let opaque_void = nested_empty_opaque(x);
@@ -143,6 +148,7 @@ fn nested_empty_opaque(x: Void) -> X {
 
 type Y = (impl Copy, impl Copy);
 struct SecretelyDoubleVoid(Y);
+#[define_opaque(Y)]
 fn super_nested_empty_opaque(x: Void) -> Y {
     if false {
         let opaque_void = super_nested_empty_opaque(x);
diff --git a/tests/ui/pattern/usefulness/impl-trait.stderr b/tests/ui/pattern/usefulness/impl-trait.stderr
index c3e1c267b61..62045151968 100644
--- a/tests/ui/pattern/usefulness/impl-trait.stderr
+++ b/tests/ui/pattern/usefulness/impl-trait.stderr
@@ -15,7 +15,7 @@ LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:31:13
+  --> $DIR/impl-trait.rs:32:13
    |
 LL |             _ => {}
    |             ^------
@@ -25,22 +25,8 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
-error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
-  --> $DIR/impl-trait.rs:23:11
-   |
-LL |     match return_never_rpit(x) {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the matched value is of type `impl Copy`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-   |
-LL ~     match return_never_rpit(x) {
-LL +         _ => todo!(),
-LL ~     }
-   |
-
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:45:13
+  --> $DIR/impl-trait.rs:46:13
    |
 LL |             Some(_) => {}
    |             ^^^^^^^------
@@ -51,7 +37,7 @@ LL |             Some(_) => {}
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:49:13
+  --> $DIR/impl-trait.rs:50:13
    |
 LL |             None => {}
    |             ---- matches all the relevant values
@@ -59,7 +45,7 @@ LL |             _ => {}
    |             ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:59:13
+  --> $DIR/impl-trait.rs:60:13
    |
 LL |             Some(_) => {}
    |             ^^^^^^^------
@@ -70,7 +56,7 @@ LL |             Some(_) => {}
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:63:13
+  --> $DIR/impl-trait.rs:64:13
    |
 LL |             None => {}
    |             ---- matches all the relevant values
@@ -78,7 +64,7 @@ LL |             _ => {}
    |             ^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:76:9
+  --> $DIR/impl-trait.rs:77:9
    |
 LL |         _ => {}
    |         ^------
@@ -89,7 +75,7 @@ LL |         _ => {}
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:86:9
+  --> $DIR/impl-trait.rs:87:9
    |
 LL |         _ => {}
    |         - matches any value
@@ -97,7 +83,7 @@ LL |         Some((a, b)) => {}
    |         ^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:94:13
+  --> $DIR/impl-trait.rs:96:13
    |
 LL |             _ => {}
    |             ^------
@@ -107,22 +93,8 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
-error[E0004]: non-exhaustive patterns: type `T` is non-empty
-  --> $DIR/impl-trait.rs:37:11
-   |
-LL |     match return_never_tait(x) {}
-   |           ^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: the matched value is of type `T`
-help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
-   |
-LL ~     match return_never_tait(x) {
-LL +         _ => todo!(),
-LL ~     }
-   |
-
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:105:9
+  --> $DIR/impl-trait.rs:108:9
    |
 LL |         Some((a, b)) => {}
    |         ------------ matches all the relevant values
@@ -130,7 +102,7 @@ LL |         Some((mut x, mut y)) => {
    |         ^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:124:13
+  --> $DIR/impl-trait.rs:128:13
    |
 LL |             _ => {}
    |             - matches any value
@@ -138,7 +110,7 @@ LL |             Rec { n: 0, w: Some(Rec { n: 0, w: _ }) } => {}
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ no value can reach this
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:138:13
+  --> $DIR/impl-trait.rs:143:13
    |
 LL |             _ => {}
    |             ^------
@@ -149,7 +121,7 @@ LL |             _ => {}
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
 error: unreachable pattern
-  --> $DIR/impl-trait.rs:151:13
+  --> $DIR/impl-trait.rs:157:13
    |
 LL |             _ => {}
    |             ^------
@@ -159,6 +131,34 @@ LL |             _ => {}
    |
    = note: to learn more about uninhabited types, see https://doc.rust-lang.org/nomicon/exotic-sizes.html#empty-types
 
+error[E0004]: non-exhaustive patterns: type `impl Copy` is non-empty
+  --> $DIR/impl-trait.rs:23:11
+   |
+LL |     match return_never_rpit(x) {}
+   |           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `impl Copy`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match return_never_rpit(x) {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `T` is non-empty
+  --> $DIR/impl-trait.rs:38:11
+   |
+LL |     match return_never_tait(x) {}
+   |           ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `T`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match return_never_tait(x) {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
 error: aborting due to 15 previous errors
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs b/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs
index fd0e07fb9b4..743ca650fdd 100644
--- a/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs
+++ b/tests/ui/privacy/private-in-public-type-alias-impl-trait.rs
@@ -8,6 +8,7 @@ pub type Pub = impl Default;
 #[derive(Default)]
 struct Priv;
 
+#[define_opaque(Pub)]
 fn check() -> Pub {
     Priv
 }
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
index 34b94f2e1c7..4cf2d1ac4a6 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.rs
@@ -12,6 +12,7 @@ impl<'a, T> Trait<'a> for T {
 mod basic_pass {
     use super::*;
     type Opq<'a> = impl Sized + 'a;
+    #[define_opaque(Opq)]
     fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
     //~^ ERROR: expected generic lifetime parameter, found `'a`
 }
@@ -27,6 +28,7 @@ mod capture_tait {
     type Opq0 = impl Sized;
     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
 }
@@ -36,6 +38,7 @@ mod capture_tait_complex_pass {
     type Opq0<'a> = impl Sized;
     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR: expected generic lifetime parameter, found `'a`
 }
@@ -46,6 +49,7 @@ mod capture_tait_complex_fail {
     type Opq0<'a> = impl Sized;
     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
 }
@@ -54,18 +58,18 @@ mod capture_tait_complex_fail {
 mod constrain_fail0 {
     use super::*;
     type Opq0<'a, 'b> = impl Sized;
+    #[define_opaque(Opq0)]
     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
-    //~^ ERROR non-defining opaque type use in defining scope
-    //~| ERROR: expected generic lifetime parameter, found `'a`
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
 }
 
 // non-defining use because generic lifetime is used multiple times.
 mod constrain_fail {
     use super::*;
     type Opq0<'a, 'b> = impl Sized;
+    #[define_opaque(Opq0)]
     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
-    //~^ ERROR non-defining opaque type use in defining scope
-    //~| ERROR: expected generic lifetime parameter, found `'a`
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
 }
 
 mod constrain_pass {
@@ -73,6 +77,7 @@ mod constrain_pass {
     type Opq0<'a, 'b> = impl Sized;
     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+    #[define_opaque(Opq2)]
     fn test() -> Opq2 {}
     //~^ ERROR: expected generic lifetime parameter, found `'a`
 }
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
index fb1e4cca3f4..3614fc8f45c 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-basic.stderr
@@ -1,13 +1,14 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:15:55
+  --> $DIR/higher-ranked-regions-basic.rs:16:55
    |
 LL |     type Opq<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
+LL |     #[define_opaque(Opq)]
 LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq<'a>> {}
    |                                                       ^^
 
 error[E0700]: hidden type for `impl Sized` captures lifetime that does not appear in bounds
-  --> $DIR/higher-ranked-regions-basic.rs:21:58
+  --> $DIR/higher-ranked-regions-basic.rs:22:58
    |
 LL |     fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
    |                           --                 ----------  ^^
@@ -16,86 +17,64 @@ LL |     fn test() -> impl for<'a> Trait<'a, Ty = impl Sized> {}
    |                           hidden type `&'a ()` captures the lifetime `'a` as defined here
 
 error[E0700]: hidden type for `capture_tait::Opq0` captures lifetime that does not appear in bounds
-  --> $DIR/higher-ranked-regions-basic.rs:30:23
+  --> $DIR/higher-ranked-regions-basic.rs:32:23
    |
 LL |     type Opq0 = impl Sized;
    |                 ---------- opaque type defined here
 LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0>;
    |                              -- hidden type `&'b ()` captures the lifetime `'b` as defined here
-LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+...
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:39:23
+  --> $DIR/higher-ranked-regions-basic.rs:42:23
    |
 LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'b>>; // <- Note 'b
    |               -- this generic parameter must be used with a generic lifetime parameter
-LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+...
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
 error[E0700]: hidden type for `capture_tait_complex_fail::Opq0<'a>` captures lifetime that does not appear in bounds
-  --> $DIR/higher-ranked-regions-basic.rs:49:23
+  --> $DIR/higher-ranked-regions-basic.rs:53:23
    |
 LL |     type Opq0<'a> = impl Sized;
    |                     ---------- opaque type defined here
 LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a>>; // <- Note 'a
    |                              -- hidden type `&'b ()` captures the lifetime `'b` as defined here
-LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+...
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/higher-ranked-regions-basic.rs:57:41
-   |
-LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
-   |                                         ^^^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/higher-ranked-regions-basic.rs:56:25
-   |
-LL |     type Opq0<'a, 'b> = impl Sized;
-   |                         ^^^^^^^^^^
-
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:57:65
+  --> $DIR/higher-ranked-regions-basic.rs:62:65
    |
 LL |     type Opq0<'a, 'b> = impl Sized;
    |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     #[define_opaque(Opq0)]
 LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'static>> {}
    |                                                                 ^^
 
-error: non-defining opaque type use in defining scope
-  --> $DIR/higher-ranked-regions-basic.rs:66:41
-   |
-LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
-   |                                         ^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
-   |
-note: for this opaque type
-  --> $DIR/higher-ranked-regions-basic.rs:65:25
-   |
-LL |     type Opq0<'a, 'b> = impl Sized;
-   |                         ^^^^^^^^^^
-
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:66:60
+  --> $DIR/higher-ranked-regions-basic.rs:71:60
    |
 LL |     type Opq0<'a, 'b> = impl Sized;
    |               -- this generic parameter must be used with a generic lifetime parameter
+LL |     #[define_opaque(Opq0)]
 LL |     fn test() -> impl for<'a> Trait<'a, Ty = Opq0<'a, 'a>> {}
    |                                                            ^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-basic.rs:76:23
+  --> $DIR/higher-ranked-regions-basic.rs:81:23
    |
 LL |     type Opq1<'a> = impl for<'b> Trait<'b, Ty = Opq0<'a, 'b>>;
    |               -- this generic parameter must be used with a generic lifetime parameter
-LL |     type Opq2 = impl for<'a> Trait<'a, Ty = Opq1<'a>>;
+...
 LL |     fn test() -> Opq2 {}
    |                       ^^
 
-error: aborting due to 10 previous errors
+error: aborting due to 8 previous errors
 
 Some errors have detailed explanations: E0700, E0792.
 For more information about an error, try `rustc --explain E0700`.
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs
index db5e5e05e54..e0b7909c240 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.rs
@@ -14,7 +14,10 @@ impl Trait for Struct {
     type Assoc<'a> = &'a u32;
 }
 
-const FOO: Foo = Struct;
-//~^ ERROR: expected generic lifetime parameter, found `'a`
+#[define_opaque(Foo)]
+fn foo() -> Foo {
+    Struct
+    //~^ ERROR: expected generic lifetime parameter, found `'a`
+}
 
 fn main() {}
diff --git a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr
index 9b361445f1e..b3edc942732 100644
--- a/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr
+++ b/tests/ui/rfcs/type-alias-impl-trait/higher-ranked-regions-gat.stderr
@@ -1,11 +1,11 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/higher-ranked-regions-gat.rs:17:18
+  --> $DIR/higher-ranked-regions-gat.rs:19:5
    |
 LL | pub type FooAssoc<'a> = impl Sized;
    |                   -- this generic parameter must be used with a generic lifetime parameter
 ...
-LL | const FOO: Foo = Struct;
-   |                  ^^^^^^
+LL |     Struct
+   |     ^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/self/arbitrary-self-opaque.rs b/tests/ui/self/arbitrary-self-opaque.rs
index c26ef658b69..b176a982e5f 100644
--- a/tests/ui/self/arbitrary-self-opaque.rs
+++ b/tests/ui/self/arbitrary-self-opaque.rs
@@ -4,6 +4,7 @@ struct Foo;
 type Bar = impl Sized;
 
 impl Foo {
+    #[define_opaque(Bar)]
     fn foo(self: Bar) {}
     //~^ ERROR: invalid `self` parameter type: `Bar`
     //~| ERROR: item does not constrain
diff --git a/tests/ui/self/arbitrary-self-opaque.stderr b/tests/ui/self/arbitrary-self-opaque.stderr
index c75165d9f8e..36ae3d6fd02 100644
--- a/tests/ui/self/arbitrary-self-opaque.stderr
+++ b/tests/ui/self/arbitrary-self-opaque.stderr
@@ -1,5 +1,5 @@
 error[E0307]: invalid `self` parameter type: `Bar`
-  --> $DIR/arbitrary-self-opaque.rs:7:18
+  --> $DIR/arbitrary-self-opaque.rs:8:18
    |
 LL |     fn foo(self: Bar) {}
    |                  ^^^
@@ -7,14 +7,14 @@ LL |     fn foo(self: Bar) {}
    = note: type of `self` must be `Self` or a type that dereferences to it
    = help: consider changing to `self`, `&self`, `&mut self`, `self: Box<Self>`, `self: Rc<Self>`, `self: Arc<Self>`, or `self: Pin<P>` (where P is one of the previous types except `Self`)
 
-error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/arbitrary-self-opaque.rs:7:8
+error: item does not constrain `Bar::{opaque#0}`
+  --> $DIR/arbitrary-self-opaque.rs:8:8
    |
 LL |     fn foo(self: Bar) {}
    |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/arbitrary-self-opaque.rs:4:12
    |
 LL | type Bar = impl Sized;
diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs
new file mode 100644
index 00000000000..55c070eb036
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-requires-supertrait-norm.rs
@@ -0,0 +1,38 @@
+//@ check-pass
+
+#![feature(derive_coerce_pointee)]
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+use std::marker::CoercePointee;
+use std::sync::Arc;
+
+trait MyTrait<T> {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct MyArc<T: ?Sized + MyTrait<u8>>(Arc<T>);
+
+impl<T: ?Sized + MyTrait<u8>> Deref for MyArc<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.0
+    }
+}
+
+trait Mirror {
+    type Assoc;
+}
+impl<T> Mirror for T {
+    type Assoc = T;
+}
+
+// This is variant on "tests/ui/self/dyn-dispatch-requires-supertrait.rs" but with
+// a supertrait that requires normalization to match the pred in the old solver.
+trait MyOtherTrait: MyTrait<<u8 as Mirror>::Assoc> {
+    fn foo(self: MyArc<Self>);
+}
+
+fn test(_: MyArc<dyn MyOtherTrait>) {}
+
+fn main() {}
diff --git a/tests/ui/self/dyn-dispatch-requires-supertrait.rs b/tests/ui/self/dyn-dispatch-requires-supertrait.rs
new file mode 100644
index 00000000000..f2661c406fe
--- /dev/null
+++ b/tests/ui/self/dyn-dispatch-requires-supertrait.rs
@@ -0,0 +1,38 @@
+//@ check-pass
+
+#![feature(derive_coerce_pointee)]
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+use std::marker::CoercePointee;
+use std::sync::Arc;
+
+trait MyTrait {}
+
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct MyArc<T>
+where
+    T: MyTrait + ?Sized,
+{
+    inner: Arc<T>
+}
+
+impl<T: MyTrait + ?Sized> Deref for MyArc<T> {
+    type Target = T;
+    fn deref(&self) -> &T {
+        &self.inner
+    }
+}
+
+// Proving that `MyArc<Self>` is dyn-dispatchable requires proving `MyArc<T>` implements
+// `DispatchFromDyn<MyArc<U>>`. The `DispatchFromDyn` impl that is generated from the
+// `CoercePointee` implementation requires the pointee impls `MyTrait`, but previously we
+// were only assuming the pointee impl'd `MyOtherTrait`. Elaboration comes to the rescue here.
+trait MyOtherTrait: MyTrait {
+    fn foo(self: MyArc<Self>);
+}
+
+fn test(_: MyArc<dyn MyOtherTrait>) {}
+
+fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl-on-opaque.rs b/tests/ui/specialization/min_specialization/impl-on-opaque.rs
index 7531dcaccf2..131ad8b9d65 100644
--- a/tests/ui/specialization/min_specialization/impl-on-opaque.rs
+++ b/tests/ui/specialization/min_specialization/impl-on-opaque.rs
@@ -26,6 +26,7 @@ impl SpecTrait<u32> for () {
     fn f() {}
 }
 
+#[define_opaque(Opaque)]
 fn foo() -> Opaque {}
 
 fn main() {}
diff --git a/tests/ui/specialization/min_specialization/impl-on-opaque2.rs b/tests/ui/specialization/min_specialization/impl-on-opaque2.rs
index 0cd8be84ed3..bcdb54c2b4f 100644
--- a/tests/ui/specialization/min_specialization/impl-on-opaque2.rs
+++ b/tests/ui/specialization/min_specialization/impl-on-opaque2.rs
@@ -23,6 +23,7 @@ impl SpecTrait<(), Opaque> for () {
     fn f() {}
 }
 
+#[define_opaque(Opaque)]
 fn foo() -> Opaque {}
 
 fn main() {}
diff --git a/tests/ui/traits/alias/issue-83613.rs b/tests/ui/traits/alias/issue-83613.rs
index 6f0012bf089..752c4b84546 100644
--- a/tests/ui/traits/alias/issue-83613.rs
+++ b/tests/ui/traits/alias/issue-83613.rs
@@ -2,6 +2,7 @@
 trait OpaqueTrait {}
 impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
+#[define_opaque(OpaqueType)]
 fn mk_opaque() -> OpaqueType {
     || 0
 }
diff --git a/tests/ui/traits/alias/issue-83613.stderr b/tests/ui/traits/alias/issue-83613.stderr
index 47181c3f33e..7d2bdd7e186 100644
--- a/tests/ui/traits/alias/issue-83613.stderr
+++ b/tests/ui/traits/alias/issue-83613.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `AnotherTrait`
-  --> $DIR/issue-83613.rs:10:1
+  --> $DIR/issue-83613.rs:11:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
diff --git a/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs
index cb9fe176ac9..92a0913dee2 100644
--- a/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs
+++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj-2.rs
@@ -12,7 +12,8 @@ fn mk<T>() -> T {
     todo!()
 }
 
-fn a(_: Tait) {
+#[define_opaque(Tait)]
+fn a() {
     let x: Tait = mk();
     let mut array = mk();
     let mut z = IntoIterator::into_iter(array);
diff --git a/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
index 8d92c88ae72..0e99ef87c89 100644
--- a/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
+++ b/tests/ui/traits/next-solver/alias-relate/tait-eq-proj.rs
@@ -28,7 +28,8 @@ goals together. Essentially:
 
 */
 
-fn a(_: Tait) {
+#[define_opaque(Tait)]
+fn a() {
     let _: Tait = IntoIterator::into_iter([0i32; 32]);
 }
 
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
index 3238f028362..28fd66cd169 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.rs
@@ -6,9 +6,11 @@
 trait Overflow {
     type Assoc;
 }
-impl<T> Overflow for T {
-    type Assoc = <T as Overflow>::Assoc;
-    //~^ ERROR: overflow
+impl<T> Overflow for T
+where
+    (T,): Overflow
+{
+    type Assoc = <(T,) as Overflow>::Assoc;
 }
 
 
diff --git a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
index 294fa0d7613..34a45e93630 100644
--- a/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
+++ b/tests/ui/traits/next-solver/coherence/trait_ref_is_knowable-norm-overflow.stderr
@@ -1,19 +1,15 @@
-error[E0275]: overflow evaluating the requirement `<T as Overflow>::Assoc == _`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:10:18
-   |
-LL |     type Assoc = <T as Overflow>::Assoc;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0119]: conflicting implementations of trait `Trait`
-  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:18:1
+  --> $DIR/trait_ref_is_knowable-norm-overflow.rs:20:1
    |
 LL | impl<T: Copy> Trait for T {}
    | ------------------------- first implementation here
 LL | struct LocalTy;
 LL | impl Trait for <LocalTy as Overflow>::Assoc {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
+   |
+   = note: overflow evaluating the requirement `_ == <LocalTy as Overflow>::Assoc`
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`trait_ref_is_knowable_norm_overflow`)
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
-Some errors have detailed explanations: E0119, E0275.
-For more information about an error, try `rustc --explain E0119`.
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs b/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs
new file mode 100644
index 00000000000..ec478aa02b7
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/cyclic-normalization-to-error-nalgebra.rs
@@ -0,0 +1,21 @@
+// Regression test for trait-system-refactor-initiative#114.
+//
+// We previously treated the cycle when trying to use the
+// `<R as DimMin<C>>::Output: DimMin` where-bound when
+// normalizing `<R as DimMin<C>>::Output` as ambiguous, causing
+// this to error.
+
+//@ check-pass
+//@ compile-flags: -Znext-solver
+//@ ignore-compare-mode-next-solver
+
+pub trait DimMin<D> {
+    type Output;
+}
+pub fn repro<R: DimMin<C>, C>()
+where
+    <R as DimMin<C>>::Output: DimMin<C, Output = <R as DimMin<C>>::Output>,
+{
+}
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs
new file mode 100644
index 00000000000..46dd6adf662
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.rs
@@ -0,0 +1,21 @@
+// If we treat known inductive cycles as errors, this test compiles
+// as normalizing `Overflow::Assoc<Overflow>` fails.
+//
+// As coherence already uses the new solver on stable, this change
+// would require an FCP.
+
+trait Trait {
+    type Assoc<T: Trait>;
+}
+
+struct Overflow;
+impl Trait for Overflow {
+    type Assoc<T: Trait> = <T as Trait>::Assoc<Overflow>;
+}
+
+trait Overlap<T, WfHack> {}
+impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
+impl<U> Overlap<u32, U> for Overflow {}
+//~^ ERROR conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
+
+fn main() {}
diff --git a/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr
new file mode 100644
index 00000000000..6605a28d547
--- /dev/null
+++ b/tests/ui/traits/next-solver/cycles/unproductive-in-coherence.stderr
@@ -0,0 +1,11 @@
+error[E0119]: conflicting implementations of trait `Overlap<<Overflow as Trait>::Assoc<Overflow>, _>` for type `Overflow`
+  --> $DIR/unproductive-in-coherence.rs:18:1
+   |
+LL | impl<T: Trait, U: Copy> Overlap<T::Assoc<T>, U> for T {}
+   | ----------------------------------------------------- first implementation here
+LL | impl<U> Overlap<u32, U> for Overflow {}
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Overflow`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0119`.
diff --git a/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs
index 904bc179495..38fcc561b32 100644
--- a/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-remap-tait-substs.rs
@@ -12,7 +12,8 @@ type Foo<T: Send, U> = impl NeedsSend<T>;
 trait NeedsSend<T> {}
 impl<T: Send> NeedsSend<T> for T {}
 
-fn define<A, B: Send>(a: A, b: B, _: Foo<B, A>) {
+#[define_opaque(Foo)]
+fn define<A, B: Send>(a: A, b: B) {
     let y: Option<Foo<B, A>> = Some(b);
 }
 
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
index 158fefd1538..736c8c10da9 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.is_send.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `Foo == _`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
    |
 LL |     needs_send::<Foo>();
    |                  ^^^ cannot satisfy `Foo == _`
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
index 158fefd1538..736c8c10da9 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.not_send.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `Foo == _`
-  --> $DIR/dont-type_of-tait-in-defining-scope.rs:15:18
+  --> $DIR/dont-type_of-tait-in-defining-scope.rs:16:18
    |
 LL |     needs_send::<Foo>();
    |                  ^^^ cannot satisfy `Foo == _`
diff --git a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
index 10b746cc989..2a08a3b2b94 100644
--- a/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
+++ b/tests/ui/traits/next-solver/opaques/dont-type_of-tait-in-defining-scope.rs
@@ -11,12 +11,14 @@ type Foo = impl Sized;
 
 fn needs_send<T: Send>() {}
 
+#[define_opaque(Foo)]
 fn test(_: Foo) {
     needs_send::<Foo>();
     //~^ ERROR type annotations needed: cannot satisfy `Foo == _`
 }
 
-fn defines(_: Foo) {
+#[define_opaque(Foo)]
+fn defines() {
     let _: Foo = ();
 }
 
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
index 9a28dc093c1..5625cb24d42 100644
--- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.current.stderr
@@ -4,31 +4,31 @@ error: unconstrained opaque type
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
    |
-   = note: `Tait1` must be used in combination with a concrete type within the same module
+   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
-  --> $DIR/no-define-in-wf-check.rs:27:18
+  --> $DIR/no-define-in-wf-check.rs:28:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
    |
-   = note: `Tait1` must be used in combination with a concrete type within the same module
+   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
-  --> $DIR/no-define-in-wf-check.rs:36:18
+  --> $DIR/no-define-in-wf-check.rs:38:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
    |
-   = note: `Tait1` must be used in combination with a concrete type within the same module
+   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
-  --> $DIR/no-define-in-wf-check.rs:47:18
+  --> $DIR/no-define-in-wf-check.rs:50:18
    |
 LL |     type Tait1 = impl Sized;
    |                  ^^^^^^^^^^
    |
-   = note: `Tait1` must be used in combination with a concrete type within the same module
+   = note: `Tait1` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
index dd6df097da1..31d07d89d8d 100644
--- a/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
+++ b/tests/ui/traits/next-solver/opaques/no-define-in-wf-check.rs
@@ -18,6 +18,7 @@ mod ex0 {
 mod ex1 {
     type Tait1 = impl Sized;
     //[current]~^ ERROR unconstrained opaque type
+    #[define_opaque(Tait1)]
     fn foo(x: Tait1) -> impl Sized {
         let () = x;
     }
@@ -27,6 +28,7 @@ mod ex2 {
     type Tait1 = impl Sized;
     //[current]~^ ERROR unconstrained opaque type
     type Tait2 = impl Sized;
+    #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
         let () = x;
     }
@@ -38,6 +40,7 @@ mod ex3 {
     trait Something<T> {}
     impl<T, U> Something<U> for T {}
     type Tait2 = impl Something<Tait1>;
+    #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
         let () = x;
     }
@@ -58,6 +61,7 @@ mod ex4 {
     //
     // ambiguity proving `(): Trait<Tait1>`.
     type Tait2 = impl Trait<(), Assoc = impl Trait<Tait1>>;
+    #[define_opaque(Tait1, Tait2)]
     fn foo(x: Tait1) -> Tait2 {
         let () = x;
     }
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
index 0f01a453b33..94a9484ecdc 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.rs
@@ -13,12 +13,7 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() {
     needs_bar::<T::Assoc1>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
-    //~| ERROR overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
+    //~^ ERROR the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
index 2b0e57966fe..6f5111a6193 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization-2.stderr
@@ -1,59 +1,19 @@
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
+error[E0277]: the trait bound `<T as Foo1>::Assoc1: Bar` is not satisfied
   --> $DIR/recursive-self-normalization-2.rs:15:17
    |
 LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Bar`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
+   |                 ^^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo1>::Assoc1`
    |
 note: required by a bound in `needs_bar`
   --> $DIR/recursive-self-normalization-2.rs:12:17
    |
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1: Sized`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
-   |
-note: required by an implicit `Sized` bound in `needs_bar`
-  --> $DIR/recursive-self-normalization-2.rs:12:14
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |              ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn needs_bar<S: Bar + ?Sized>() {}
-   |                     ++++++++
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:5
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:5
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |     ^^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo1>::Assoc1 == _`
-  --> $DIR/recursive-self-normalization-2.rs:15:17
-   |
-LL |     needs_bar::<T::Assoc1>();
-   |                 ^^^^^^^^^
+help: consider further restricting the associated type
    |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL | fn test<T: Foo1<Assoc1 = <T as Foo2>::Assoc2> + Foo2<Assoc2 = <T as Foo1>::Assoc1>>() where <T as Foo1>::Assoc1: Bar {
+   |                                                                                       ++++++++++++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
index f435b48737e..f441ac499f9 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.rs
@@ -9,12 +9,7 @@ fn needs_bar<S: Bar>() {}
 
 fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() {
     needs_bar::<T::Assoc>();
-    //~^ ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc == _`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
-    //~| ERROR overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
+    //~^ ERROR the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
 }
 
 fn main() {}
diff --git a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
index af8504dcaee..c5518234687 100644
--- a/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
+++ b/tests/ui/traits/next-solver/overflow/recursive-self-normalization.stderr
@@ -1,59 +1,19 @@
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
+error[E0277]: the trait bound `<T as Foo>::Assoc: Bar` is not satisfied
   --> $DIR/recursive-self-normalization.rs:11:17
    |
 LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Bar`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
+   |                 ^^^^^^^^ the trait `Bar` is not implemented for `<T as Foo>::Assoc`
    |
 note: required by a bound in `needs_bar`
   --> $DIR/recursive-self-normalization.rs:8:17
    |
 LL | fn needs_bar<S: Bar>() {}
    |                 ^^^ required by this bound in `needs_bar`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc: Sized`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
-   |
-note: required by an implicit `Sized` bound in `needs_bar`
-  --> $DIR/recursive-self-normalization.rs:8:14
-   |
-LL | fn needs_bar<S: Bar>() {}
-   |              ^ required by the implicit `Sized` requirement on this type parameter in `needs_bar`
-help: consider relaxing the implicit `Sized` restriction
-   |
-LL | fn needs_bar<S: Bar + ?Sized>() {}
-   |                     ++++++++
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:5
-   |
-LL |     needs_bar::<T::Assoc>();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:5
-   |
-LL |     needs_bar::<T::Assoc>();
-   |     ^^^^^^^^^^^^^^^^^^^^^
-   |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
-
-error[E0275]: overflow evaluating the requirement `<T as Foo>::Assoc == _`
-  --> $DIR/recursive-self-normalization.rs:11:17
-   |
-LL |     needs_bar::<T::Assoc>();
-   |                 ^^^^^^^^
+help: consider further restricting the associated type
    |
-   = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+LL | fn test<T: Foo<Assoc = <T as Foo>::Assoc>>() where <T as Foo>::Assoc: Bar {
+   |                                              ++++++++++++++++++++++++++++
 
-error: aborting due to 6 previous errors
+error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.rs b/tests/ui/traits/pointee-tail-is-generic-errors.rs
index 92a83f40b18..8ddac5b2f39 100644
--- a/tests/ui/traits/pointee-tail-is-generic-errors.rs
+++ b/tests/ui/traits/pointee-tail-is-generic-errors.rs
@@ -5,6 +5,7 @@
 
 type Opaque = impl std::fmt::Debug + ?Sized;
 
+#[define_opaque(Opaque)]
 fn opaque() -> &'static Opaque {
     &[1] as &[i32]
 }
diff --git a/tests/ui/traits/pointee-tail-is-generic-errors.stderr b/tests/ui/traits/pointee-tail-is-generic-errors.stderr
index 0c3d7060dd7..907f07026a4 100644
--- a/tests/ui/traits/pointee-tail-is-generic-errors.stderr
+++ b/tests/ui/traits/pointee-tail-is-generic-errors.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<T as Pointee>::Metadata == ()`
-  --> $DIR/pointee-tail-is-generic-errors.rs:13:15
+  --> $DIR/pointee-tail-is-generic-errors.rs:14:15
    |
 LL |     is_thin::<T>();
    |               ^ expected `()`, found associated type
@@ -9,13 +9,13 @@ LL |     is_thin::<T>();
    = help: consider constraining the associated type `<T as Pointee>::Metadata` to `()`
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 note: required by a bound in `is_thin`
-  --> $DIR/pointee-tail-is-generic-errors.rs:20:33
+  --> $DIR/pointee-tail-is-generic-errors.rs:21:33
    |
 LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
    |                                 ^^^^^^^^^^^^^ required by this bound in `is_thin`
 
 error[E0271]: type mismatch resolving `<Opaque as Pointee>::Metadata == ()`
-  --> $DIR/pointee-tail-is-generic-errors.rs:16:15
+  --> $DIR/pointee-tail-is-generic-errors.rs:17:15
    |
 LL | type Opaque = impl std::fmt::Debug + ?Sized;
    |               ----------------------------- the found opaque type
@@ -26,7 +26,7 @@ LL |     is_thin::<Opaque>();
    = note:    expected unit type `()`
            found associated type `<Opaque as Pointee>::Metadata`
 note: required by a bound in `is_thin`
-  --> $DIR/pointee-tail-is-generic-errors.rs:20:33
+  --> $DIR/pointee-tail-is-generic-errors.rs:21:33
    |
 LL | fn is_thin<T: std::ptr::Pointee<Metadata = ()> + ?Sized>() {}
    |                                 ^^^^^^^^^^^^^ required by this bound in `is_thin`
diff --git a/tests/ui/traits/pointee-tail-is-generic.rs b/tests/ui/traits/pointee-tail-is-generic.rs
index 14bdf0880c7..b41fb61e4a4 100644
--- a/tests/ui/traits/pointee-tail-is-generic.rs
+++ b/tests/ui/traits/pointee-tail-is-generic.rs
@@ -4,12 +4,11 @@
 #![feature(ptr_metadata)]
 #![feature(type_alias_impl_trait)]
 
-mod opaque {
-    pub type Opaque = impl std::future::Future;
+pub type Opaque = impl std::future::Future;
 
-    fn opaque() -> Opaque {
-        async {}
-    }
+#[define_opaque(Opaque)]
+fn opaque() -> Opaque {
+    async {}
 }
 
 fn a<T>() {
@@ -18,7 +17,7 @@ fn a<T>() {
     // tail of ADT (which is a type param) is known to be sized
     is_thin::<std::cell::Cell<T>>();
     // opaque type is known to be sized
-    is_thin::<opaque::Opaque>();
+    is_thin::<Opaque>();
 }
 
 fn a2<T: Iterator>() {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
index ab3817da28b..ed852ef986a 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
@@ -15,6 +15,7 @@ fn test_correct2<'a>(x: &dyn Foo<'a>) {
     let _ = x as &dyn Bar<'_, '_, Tait>;
 }
 
+#[define_opaque(Tait)]
 fn test_correct3<'a>(x: &dyn Foo<'a>, _: Tait) {
     let _ = x as &dyn Bar<'_, '_, ()>;
 }
diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
index 0548eda0468..3e36ce0dc72 100644
--- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
@@ -17,6 +17,7 @@ impl<T: ?Sized> Super for T {
 
 type Foo = impl Sized;
 
+#[define_opaque(Foo)]
 fn upcast(x: &dyn Sub<Assoc = Foo>) -> &dyn Super<Assoc = i32> {
     x
 }
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
index cdf9deecd51..7f51d1519db 100644
--- a/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
+++ b/tests/ui/transmutability/malformed-program-gracefulness/coherence-bikeshed-intrinsic-from.stderr
@@ -19,7 +19,7 @@ error: unconstrained opaque type
 LL | type OpaqueType = impl OpaqueTrait;
    |                   ^^^^^^^^^^^^^^^^
    |
-   = note: `OpaqueType` must be used in combination with a concrete type within the same module
+   = note: `OpaqueType` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/argument-types.rs b/tests/ui/type-alias-impl-trait/argument-types.rs
index 7382d4c78c7..ea87bcb3e45 100644
--- a/tests/ui/type-alias-impl-trait/argument-types.rs
+++ b/tests/ui/type-alias-impl-trait/argument-types.rs
@@ -2,20 +2,19 @@
 #![allow(dead_code)]
 //@ check-pass
 
-mod foo {
-    use std::fmt::Debug;
+use std::fmt::Debug;
 
-    pub type Foo = impl Debug;
+pub type Foo = impl Debug;
 
-    fn foo1(mut x: Foo) {
-        x = 22_u32;
-    }
+#[define_opaque(Foo)]
+fn foo1(mut x: Foo) {
+    x = 22_u32;
+}
 
-    pub fn foo_value() -> Foo {
-        11_u32
-    }
+#[define_opaque(Foo)]
+pub fn foo_value() -> Foo {
+    11_u32
 }
-use foo::*;
 
 fn foo2(mut x: Foo) {
     // no constraint on x
diff --git a/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
index 9dcbc75db3f..97c1c1b64cc 100644
--- a/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
+++ b/tests/ui/type-alias-impl-trait/assoc-projection-ice.rs
@@ -2,23 +2,21 @@
 
 //@ build-pass
 
-mod helper {
-    pub trait T {
-        type Item;
-    }
+pub trait T {
+    type Item;
+}
 
-    pub type Alias<'a> = impl T<Item = &'a ()>;
+pub type Alias<'a> = impl T<Item = &'a ()>;
 
-    struct S;
-    impl<'a> T for &'a S {
-        type Item = &'a ();
-    }
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
+}
 
-    pub fn filter_positive<'a>() -> Alias<'a> {
-        &S
-    }
+#[define_opaque(Alias)]
+pub fn filter_positive<'a>() -> Alias<'a> {
+    &S
 }
-use helper::*;
 
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     fun(filter_positive());
diff --git a/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs
index a1185cd5ba8..6761835be89 100644
--- a/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs
+++ b/tests/ui/type-alias-impl-trait/associated-type-alias-impl-trait.rs
@@ -15,9 +15,11 @@ type Helper = impl Bar;
 
 impl Foo for i32 {
     type Assoc = Helper;
+    #[define_opaque(Helper)]
     fn foo() -> Helper {
         Dummy
     }
+    #[define_opaque(Helper)]
     fn bar() -> Helper {
         Dummy
     }
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
index a03a146d041..cf385223ce4 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage.rs
@@ -3,16 +3,15 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-mod m {
-    pub(crate) type Foo = impl std::fmt::Debug;
+pub(crate) type Foo = impl std::fmt::Debug;
 
-    pub(crate) fn foo() -> Foo {
-        22_u32
-    }
+#[define_opaque(Foo)]
+pub(crate) fn foo() -> Foo {
+    22_u32
 }
 
 fn is_send<T: Send>(_: T) {}
 
 fn main() {
-    is_send(m::foo());
+    is_send(foo());
 }
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs
index fc89b0e870e..6132eef0db5 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.rs
@@ -1,16 +1,15 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-mod m {
-    use std::rc::Rc;
+use std::rc::Rc;
 
-    type Foo = impl std::fmt::Debug; //~ NOTE appears within the type
-    //~^ within this `Foo`
-    //~| expansion of desugaring
+type Foo = impl std::fmt::Debug; //~ NOTE appears within the type
+//~^ within this `Foo`
+//~| expansion of desugaring
 
-    pub fn foo() -> Foo {
-        Rc::new(22_u32)
-    }
+#[define_opaque(Foo)]
+pub fn foo() -> Foo {
+    Rc::new(22_u32)
 }
 
 fn is_send<T: Send>(_: T) {}
@@ -18,7 +17,7 @@ fn is_send<T: Send>(_: T) {}
 //~| required by a bound
 
 fn main() {
-    is_send(m::foo());
+    is_send(foo());
     //~^ ERROR: `Rc<u32>` cannot be sent between threads safely [E0277]
     //~| NOTE cannot be sent
     //~| NOTE required by a bound
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
index 2ed918eca17..d2db468b519 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage2.stderr
@@ -1,22 +1,22 @@
 error[E0277]: `Rc<u32>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leakage2.rs:21:13
+  --> $DIR/auto-trait-leakage2.rs:20:13
    |
-LL |     type Foo = impl std::fmt::Debug;
-   |                -------------------- within this `Foo`
+LL | type Foo = impl std::fmt::Debug;
+   |            -------------------- within this `Foo`
 ...
-LL |     is_send(m::foo());
-   |     ------- ^^^^^^^^ `Rc<u32>` cannot be sent between threads safely
+LL |     is_send(foo());
+   |     ------- ^^^^^ `Rc<u32>` cannot be sent between threads safely
    |     |
    |     required by a bound introduced by this call
    |
    = help: within `Foo`, the trait `Send` is not implemented for `Rc<u32>`
 note: required because it appears within the type `Foo`
-  --> $DIR/auto-trait-leakage2.rs:7:16
+  --> $DIR/auto-trait-leakage2.rs:6:12
    |
-LL |     type Foo = impl std::fmt::Debug;
-   |                ^^^^^^^^^^^^^^^^^^^^
+LL | type Foo = impl std::fmt::Debug;
+   |            ^^^^^^^^^^^^^^^^^^^^
 note: required by a bound in `is_send`
-  --> $DIR/auto-trait-leakage2.rs:16:15
+  --> $DIR/auto-trait-leakage2.rs:15:15
    |
 LL | fn is_send<T: Send>(_: T) {}
    |               ^^^^ required by this bound in `is_send`
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
index cad75cffe05..3e0bd3b6521 100644
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
+++ b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.rs
@@ -1,17 +1,17 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-// FIXME This should compile, but it currently doesn't
+//@ check-pass
 
 mod m {
     pub type Foo = impl std::fmt::Debug;
+    #[define_opaque(Foo)]
     pub fn foo() -> Foo {
         22_u32
     }
 
     pub fn bar() {
         is_send(foo());
-        //~^ ERROR: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}
     }
 
     fn is_send<T: Send>(_: T) {}
diff --git a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr b/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
deleted file mode 100644
index 6bdc76aab45..00000000000
--- a/tests/ui/type-alias-impl-trait/auto-trait-leakage3.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: cannot check whether the hidden type of `auto_trait_leakage3[211d]::m::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/auto-trait-leakage3.rs:13:17
-   |
-LL |         is_send(foo());
-   |         ------- ^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/auto-trait-leakage3.rs:7:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `is_send`
-  --> $DIR/auto-trait-leakage3.rs:17:19
-   |
-LL |     fn is_send<T: Send>(_: T) {}
-   |                   ^^^^ required by this bound in `is_send`
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
index e7bca2231de..c60fd0b6798 100644
--- a/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
+++ b/tests/ui/type-alias-impl-trait/auxiliary/cross_crate_ice.rs
@@ -5,6 +5,7 @@
 
 pub type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 pub fn foo() -> Foo {
     5
 }
diff --git a/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs
index 54a22510066..3c823d3e5d2 100644
--- a/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs
+++ b/tests/ui/type-alias-impl-trait/auxiliary/drop-shim-relates-opaque-aux.rs
@@ -3,6 +3,7 @@
 #![feature(type_alias_impl_trait)]
 
 type Tait = impl Sized;
+#[define_opaque(Tait)]
 fn _constrain() -> Tait {}
 
 struct WrapperWithDrop<T>(T);
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
index 4b2ee344aa3..b6870b16450 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.rs
@@ -8,9 +8,9 @@ pub enum UninhabitedVariants {
     Tuple(Alias),
     //~^ ERROR missing lifetime specifier
     //~| ERROR missing generics
-    //~| ERROR non-defining opaque type use in defining scope
 }
 
+#[define_opaque(Alias)]
 fn uwu(x: UninhabitedVariants) {
     //~^ ERROR item does not constrain
     match x {}
diff --git a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
index 38fbff9d59d..59909197e7b 100644
--- a/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
+++ b/tests/ui/type-alias-impl-trait/bad-tait-no-substs.stderr
@@ -26,26 +26,14 @@ help: add missing generic argument
 LL |     Tuple(Alias<U>),
    |                +++
 
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/bad-tait-no-substs.rs:8:11
-   |
-LL |     Tuple(Alias),
-   |           ^^^^^ argument `'_` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/bad-tait-no-substs.rs:5:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
-error: item does not constrain `Alias::{opaque#0}`, but has it in its signature
+error: item does not constrain `Alias::{opaque#0}`
   --> $DIR/bad-tait-no-substs.rs:14:4
    |
 LL | fn uwu(x: UninhabitedVariants) {
    |    ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/bad-tait-no-substs.rs:5:21
    |
 LL | type Alias<'a, U> = impl Trait<U>;
@@ -72,7 +60,7 @@ LL +         UninhabitedVariants::Tuple(_) => todo!(),
 LL ~     }
    |
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
-Some errors have detailed explanations: E0004, E0106, E0107, E0792.
+Some errors have detailed explanations: E0004, E0106, E0107.
 For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
index 3b83b2e544b..4dba8d7b230 100644
--- a/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/bivariant-duplicate-lifetime-unconstrained.rs
@@ -11,6 +11,7 @@
 
 type Opaque<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque)]
 fn test<'a>() -> Opaque<'a> {
     let _: () = test::<'a>();
 }
diff --git a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs
index df589473a84..e714aca812b 100644
--- a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs
+++ b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.rs
@@ -9,7 +9,7 @@ fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
 }
 
 pub fn main() {
-    //~^ ERROR item does not constrain `Opaque::{opaque#0}`, but has it in its signature
+    //~^ ERROR item does not constrain `Opaque::{opaque#0}`
     type Opaque = impl Sized;
     fn define() -> Opaque {
         let x: Opaque = dyn_hoops::<()>();
diff --git a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr
index 59d9ff86c6e..7219fda4772 100644
--- a/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr
+++ b/tests/ui/type-alias-impl-trait/bound-lifetime-through-dyn-trait.stderr
@@ -10,14 +10,14 @@ note: lifetime declared here
 LL | fn dyn_hoops<T: Sized>() -> dyn for<'a> Iterator<Item = impl Captures<'a>> {
    |                                     ^^
 
-error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
+error: item does not constrain `Opaque::{opaque#0}`
   --> $DIR/bound-lifetime-through-dyn-trait.rs:11:8
    |
 LL | pub fn main() {
    |        ^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/bound-lifetime-through-dyn-trait.rs:13:19
    |
 LL |     type Opaque = impl Sized;
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction.rs b/tests/ui/type-alias-impl-trait/bound_reduction.rs
index 74012e34e92..5966b5cc815 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction.rs
+++ b/tests/ui/type-alias-impl-trait/bound_reduction.rs
@@ -10,6 +10,7 @@ type Foo<V> = impl std::fmt::Debug;
 
 trait Trait<U> {}
 
+#[define_opaque(Foo)]
 fn foo_desugared<T: Trait<[u32; {
     #[no_mangle]
     static FOO: usize = 42;
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.rs b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
index 4e9f65d88a1..78288caffef 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.rs
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.rs
@@ -12,8 +12,8 @@ trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
+#[define_opaque(Foo)]
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-    //~^ ERROR non-defining opaque type use
     ()
     //~^ ERROR expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
 }
diff --git a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
index 14f9dbbdb4e..289826cc1d0 100644
--- a/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
+++ b/tests/ui/type-alias-impl-trait/bound_reduction2.stderr
@@ -1,15 +1,3 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/bound_reduction2.rs:15:46
-   |
-LL | fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T::Assoc> {
-   |                                              ^^^^^^^^^^^^^ argument `<T as TraitWithAssoc>::Assoc` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/bound_reduction2.rs:9:15
-   |
-LL | type Foo<V> = impl Trait<V>;
-   |               ^^^^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `<T as TraitWithAssoc>::Assoc`
   --> $DIR/bound_reduction2.rs:17:5
    |
@@ -19,6 +7,6 @@ LL | type Foo<V> = impl Trait<V>;
 LL |     ()
    |     ^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs
index 45f54266014..4151a6a5f12 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.rs
@@ -3,15 +3,13 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub type X<T> = impl Clone;
+pub type X<T> = impl Clone;
 
-    fn f<T: Clone>(t: T) -> X<T> {
-        t
-        //~^ ERROR the trait bound `T: Clone` is not satisfied
-    }
+#[define_opaque(X)]
+fn f<T: Clone>(t: T) -> X<T> {
+    t
+    //~^ ERROR the trait bound `T: Clone` is not satisfied
 }
-use foo::X;
 
 fn g<T>(o: Option<X<T>>) -> Option<X<T>> {
     o.clone()
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
index bbb32b2d604..21166631c3e 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked-2.stderr
@@ -1,23 +1,23 @@
 error[E0277]: the trait bound `T: Clone` is not satisfied
-  --> $DIR/bounds-are-checked-2.rs:10:9
+  --> $DIR/bounds-are-checked-2.rs:10:5
    |
-LL |         t
-   |         ^ the trait `Clone` is not implemented for `T`
+LL |     t
+   |     ^ the trait `Clone` is not implemented for `T`
    |
 note: required by a bound in an opaque type
-  --> $DIR/bounds-are-checked-2.rs:7:26
+  --> $DIR/bounds-are-checked-2.rs:6:22
    |
-LL |     pub type X<T> = impl Clone;
-   |                          ^^^^^
+LL | pub type X<T> = impl Clone;
+   |                      ^^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/bounds-are-checked-2.rs:9:5
+  --> $DIR/bounds-are-checked-2.rs:9:1
    |
-LL |     fn f<T: Clone>(t: T) -> X<T> {
-   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+LL | fn f<T: Clone>(t: T) -> X<T> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 help: consider restricting type parameter `T` with trait `Clone`
    |
-LL |     pub type X<T: std::clone::Clone> = impl Clone;
-   |                 +++++++++++++++++++
+LL | pub type X<T: std::clone::Clone> = impl Clone;
+   |             +++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
index 7c3a3a84406..3d295358728 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.rs
@@ -5,6 +5,7 @@
 
 type X<'a> = impl Into<&'static str> + From<&'a str>;
 
+#[define_opaque(X)]
 fn f<'a: 'static>(t: &'a str) -> X<'a> {
     t
     //~^ ERROR expected generic lifetime parameter, found `'static`
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
index ad1b9f19d8e..7617268dd8e 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/bounds-are-checked.rs:9:5
+  --> $DIR/bounds-are-checked.rs:10:5
    |
 LL | type X<'a> = impl Into<&'static str> + From<&'a str>;
    |        -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
diff --git a/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs
index 5a9e87c0919..a8524770a85 100644
--- a/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs
+++ b/tests/ui/type-alias-impl-trait/bounds-are-checked3.rs
@@ -9,6 +9,7 @@ struct Struct<V: Display>(Option<V>);
 type Foo<T: Debug> = (impl Debug, Struct<T>);
 //~^ ERROR: `T` doesn't implement `std::fmt::Display`
 
+#[define_opaque(Foo)]
 fn foo<U: Debug + Display>() -> Foo<U> {
     (Vec::<U>::new(), Struct(None))
 }
diff --git a/tests/ui/type-alias-impl-trait/bounds.rs b/tests/ui/type-alias-impl-trait/bounds.rs
index 8e24a937d1d..c131d52a4ba 100644
--- a/tests/ui/type-alias-impl-trait/bounds.rs
+++ b/tests/ui/type-alias-impl-trait/bounds.rs
@@ -9,6 +9,7 @@ use std::fmt::Debug;
 // type alias bounds.
 type Foo<T: Debug> = (impl Debug, usize);
 
+#[define_opaque(Foo)]
 fn foo<U: Debug>() -> Foo<U> {
     (Vec::<U>::new(), 1234)
 }
diff --git a/tests/ui/type-alias-impl-trait/closure-normalization-ice-109020.rs b/tests/ui/type-alias-impl-trait/closure-normalization-ice-109020.rs
index 0dfa1f40ae6..7fd8fa6f9db 100644
--- a/tests/ui/type-alias-impl-trait/closure-normalization-ice-109020.rs
+++ b/tests/ui/type-alias-impl-trait/closure-normalization-ice-109020.rs
@@ -6,14 +6,12 @@
 
 use std::marker::PhantomData;
 
-mod foo {
-    pub type WithEmplacableForFn<'a> = impl super::EmplacableFn + 'a;
+type WithEmplacableForFn<'a> = impl EmplacableFn + 'a;
 
-    fn _constrain(_: &mut ()) -> WithEmplacableForFn<'_> {
-        ()
-    }
+#[define_opaque(WithEmplacableForFn)]
+fn _constrain(_: &mut ()) -> WithEmplacableForFn<'_> {
+    ()
 }
-use foo::*;
 
 fn with_emplacable_for<'a, F, R>(mut f: F) -> R
 where
diff --git a/tests/ui/type-alias-impl-trait/closure_args.rs b/tests/ui/type-alias-impl-trait/closure_args.rs
index 0141a01aad0..8a518c19dba 100644
--- a/tests/ui/type-alias-impl-trait/closure_args.rs
+++ b/tests/ui/type-alias-impl-trait/closure_args.rs
@@ -4,21 +4,19 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub trait Anything {}
-    impl<T> Anything for T {}
-    pub type Input = impl Anything;
+pub trait Anything {}
+impl<T> Anything for T {}
+pub type Input = impl Anything;
 
-    fn bop(_: Input) {
-        super::run(
-            |x: u32| {
-                println!("{x}");
-            },
-            0,
-        );
-    }
+#[define_opaque(Input)]
+fn bop(_: Input) {
+    run(
+        |x: u32| {
+            println!("{x}");
+        },
+        0,
+    );
 }
-use foo::Input;
 
 fn run<F: FnOnce(Input) -> ()>(f: F, i: Input) {
     f(i);
diff --git a/tests/ui/type-alias-impl-trait/closure_args2.rs b/tests/ui/type-alias-impl-trait/closure_args2.rs
index 13ac3d31d83..257c5f86633 100644
--- a/tests/ui/type-alias-impl-trait/closure_args2.rs
+++ b/tests/ui/type-alias-impl-trait/closure_args2.rs
@@ -2,27 +2,25 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub trait Foo {
-        // This was reachable in https://github.com/rust-lang/rust/issues/100800
-        fn foo(&self) {
-            unreachable!()
-        }
+pub trait Foo {
+    // This was reachable in https://github.com/rust-lang/rust/issues/100800
+    fn foo(&self) {
+        unreachable!()
     }
-    impl<T> Foo for T {}
+}
+impl<T> Foo for T {}
 
-    pub struct B;
-    impl B {
-        fn foo(&self) {}
-    }
-    pub type Input = impl Foo;
-    fn bop() -> Input {
-        super::run1(|x: B| x.foo(), B);
-        super::run2(|x: B| x.foo(), B);
-        panic!()
-    }
+pub struct B;
+impl B {
+    fn foo(&self) {}
+}
+pub type Input = impl Foo;
+#[define_opaque(Input)]
+fn bop() -> Input {
+    run1(|x: B| x.foo(), B);
+    run2(|x: B| x.foo(), B);
+    panic!()
 }
-use foo::*;
 
 fn run1<F: FnOnce(Input)>(f: F, i: Input) {
     f(i)
diff --git a/tests/ui/type-alias-impl-trait/closure_infer.rs b/tests/ui/type-alias-impl-trait/closure_infer.rs
index fa0514c34a0..2aa19913ad6 100644
--- a/tests/ui/type-alias-impl-trait/closure_infer.rs
+++ b/tests/ui/type-alias-impl-trait/closure_infer.rs
@@ -22,12 +22,14 @@ impl StreamConsumer for DispatchExecutor {
 
 // Functions that constrain TAITs can contain closures with an `_` in the return type.
 type Foo = impl Sized;
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     || -> _ {}
 }
 
 // The `_` in the closure return type can also be the TAIT itself.
 type Bar = impl Sized;
+#[define_opaque(Bar)]
 fn bar() -> impl FnOnce() -> Bar {
     || -> _ {}
 }
diff --git a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
index e78c7c16c8e..4c99778b66e 100644
--- a/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
+++ b/tests/ui/type-alias-impl-trait/closure_parent_substs.rs
@@ -15,6 +15,7 @@ mod test1 {
     // Hidden type = Closure['?0]
     type Opaque = impl Sized;
 
+    #[define_opaque(Opaque)]
     fn define<'a: 'a>() -> Opaque {
         || {}
     }
@@ -31,6 +32,7 @@ mod test2 {
         &'a (): Trait,
     = impl Sized + 'a;
 
+    #[define_opaque(Opaque)]
     fn define<'a, 'x, 'y>() -> Opaque<'a>
     where
         &'a (): Trait,
@@ -52,6 +54,7 @@ mod test3 {
         (&'a (), &'b ()): Trait,
     = impl Sized + 'a + 'b;
 
+    #[define_opaque(Opaque)]
     fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
     where
         (&'a (), &'b ()): Trait,
diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
index caa9b6d979a..5316a47bbd4 100644
--- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
+++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.rs
@@ -13,6 +13,7 @@
 mod test1 {
     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
 
+    #[define_opaque(Opaque)]
     fn define<'a, 'b>() -> Opaque<'a, 'b>
     where
         'a: 'b,
@@ -26,6 +27,7 @@ mod test1 {
 mod test2 {
     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
 
+    #[define_opaque(Opaque)]
     fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
     where
         'a: 'x,
@@ -40,6 +42,7 @@ mod test2 {
 mod test2_fixed {
     type Opaque<'a: 'b, 'b> = impl Sized + 'a + 'b;
 
+    #[define_opaque(Opaque)]
     fn define<'a, 'b, 'x>() -> Opaque<'a, 'b>
     where
         'a: 'x,
@@ -53,6 +56,7 @@ mod test2_fixed {
 mod test3 {
     type Opaque<T> = impl Sized;
 
+    #[define_opaque(Opaque)]
     fn define<T>() -> Opaque<T>
     where
         T: 'static,
diff --git a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
index ae00d3fc667..ccba2d37fd0 100644
--- a/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
+++ b/tests/ui/type-alias-impl-trait/closure_wf_outlives.stderr
@@ -1,5 +1,5 @@
 error[E0478]: lifetime bound not satisfied
-  --> $DIR/closure_wf_outlives.rs:20:9
+  --> $DIR/closure_wf_outlives.rs:21:9
    |
 LL |         || {}
    |         ^^^^^
@@ -16,34 +16,34 @@ LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                     ^^
 
 error[E0803]: cannot infer an appropriate lifetime due to conflicting requirements
-  --> $DIR/closure_wf_outlives.rs:34:9
+  --> $DIR/closure_wf_outlives.rs:36:9
    |
 LL |         || {}
    |         ^^^^^
    |
 note: first, the lifetime cannot outlive the lifetime `'a` as defined here...
-  --> $DIR/closure_wf_outlives.rs:27:17
+  --> $DIR/closure_wf_outlives.rs:28:17
    |
 LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                 ^^
 note: ...so that the declared lifetime parameter bounds are satisfied
-  --> $DIR/closure_wf_outlives.rs:34:9
+  --> $DIR/closure_wf_outlives.rs:36:9
    |
 LL |         || {}
    |         ^^^^^
 note: but, the lifetime must be valid for the lifetime `'b` as defined here...
-  --> $DIR/closure_wf_outlives.rs:27:21
+  --> $DIR/closure_wf_outlives.rs:28:21
    |
 LL |     type Opaque<'a, 'b> = impl Sized + 'a + 'b;
    |                     ^^
 note: ...so that the declared lifetime parameter bounds are satisfied
-  --> $DIR/closure_wf_outlives.rs:34:9
+  --> $DIR/closure_wf_outlives.rs:36:9
    |
 LL |         || {}
    |         ^^^^^
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/closure_wf_outlives.rs:60:9
+  --> $DIR/closure_wf_outlives.rs:64:9
    |
 LL |         || {}
    |         ^^^^^
@@ -52,7 +52,7 @@ LL |         || {}
    |         ...so that the type `T` will meet its required lifetime bounds...
    |
 note: ...that is required by this bound
-  --> $DIR/closure_wf_outlives.rs:58:12
+  --> $DIR/closure_wf_outlives.rs:62:12
    |
 LL |         T: 'static,
    |            ^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.rs b/tests/ui/type-alias-impl-trait/closures_in_branches.rs
index 7bb490bbec8..d83bf36a444 100644
--- a/tests/ui/type-alias-impl-trait/closures_in_branches.rs
+++ b/tests/ui/type-alias-impl-trait/closures_in_branches.rs
@@ -2,6 +2,7 @@
 
 type Foo = impl std::ops::FnOnce(String) -> usize;
 
+#[define_opaque(Foo)]
 fn foo(b: bool) -> Foo {
     if b {
         |x| x.len() //~ ERROR type annotations needed
@@ -10,8 +11,8 @@ fn foo(b: bool) -> Foo {
     }
 }
 
-
 type Foo1 = impl std::ops::FnOnce(String) -> usize;
+#[define_opaque(Foo1)]
 fn foo1(b: bool) -> Foo1 {
     |x| x.len()
 }
diff --git a/tests/ui/type-alias-impl-trait/closures_in_branches.stderr b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr
index 9cc15f14a99..849ffd214f0 100644
--- a/tests/ui/type-alias-impl-trait/closures_in_branches.stderr
+++ b/tests/ui/type-alias-impl-trait/closures_in_branches.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/closures_in_branches.rs:7:10
+  --> $DIR/closures_in_branches.rs:8:10
    |
 LL |         |x| x.len()
    |          ^  - type must be known at this point
@@ -10,7 +10,7 @@ LL |         |x: /* Type */| x.len()
    |           ++++++++++++
 
 error[E0282]: type annotations needed
-  --> $DIR/closures_in_branches.rs:21:10
+  --> $DIR/closures_in_branches.rs:22:10
    |
 LL |         |x| x.len()
    |          ^  - type must be known at this point
diff --git a/tests/ui/type-alias-impl-trait/coherence.classic.stderr b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
index 98badeef382..e99d4636b13 100644
--- a/tests/ui/type-alias-impl-trait/coherence.classic.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.classic.stderr
@@ -1,5 +1,5 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence.rs:16:1
+  --> $DIR/coherence.rs:17:1
    |
 LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
diff --git a/tests/ui/type-alias-impl-trait/coherence.next.stderr b/tests/ui/type-alias-impl-trait/coherence.next.stderr
index 8d718383110..6d14594e33a 100644
--- a/tests/ui/type-alias-impl-trait/coherence.next.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence.next.stderr
@@ -1,5 +1,5 @@
 error[E0117]: only traits defined in the current crate can be implemented for arbitrary types
-  --> $DIR/coherence.rs:16:1
+  --> $DIR/coherence.rs:17:1
    |
 LL | impl foreign_crate::ForeignTrait for AliasOfForeignType<()> {}
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^----------------------
diff --git a/tests/ui/type-alias-impl-trait/coherence.rs b/tests/ui/type-alias-impl-trait/coherence.rs
index 760e5210c5b..eb27c270804 100644
--- a/tests/ui/type-alias-impl-trait/coherence.rs
+++ b/tests/ui/type-alias-impl-trait/coherence.rs
@@ -9,6 +9,7 @@ trait LocalTrait {}
 impl<T> LocalTrait for foreign_crate::ForeignType<T> {}
 
 type AliasOfForeignType<T> = impl LocalTrait;
+#[define_opaque(AliasOfForeignType)]
 fn use_alias<T>(val: T) -> AliasOfForeignType<T> {
     foreign_crate::ForeignType(val)
 }
diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs
index c1958e4f246..73f13f22bee 100644
--- a/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs
+++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.rs
@@ -13,6 +13,7 @@ trait OtherTrait {}
 
 type Alias = impl SomeTrait;
 
+#[define_opaque(Alias)]
 fn constrain() -> Alias {
     ()
 }
diff --git a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr
index 893a27faced..6b251cfac73 100644
--- a/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr
+++ b/tests/ui/type-alias-impl-trait/coherence_cross_crate.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `OtherTrait` for type `Alias`
-  --> $DIR/coherence_cross_crate.rs:21:1
+  --> $DIR/coherence_cross_crate.rs:22:1
    |
 LL | impl OtherTrait for Alias {}
    | ------------------------- first implementation here
diff --git a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
index 39b3d535ad4..a7e251b1ab9 100644
--- a/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
+++ b/tests/ui/type-alias-impl-trait/coherence_different_hidden_ty.rs
@@ -20,6 +20,7 @@ impl Trait for (TAIT, TAIT) {}
 impl Trait for (u32, i32) {}
 //~^ ERROR conflicting implementations of trait `Trait` for type `(TAIT, TAIT)`
 
+#[define_opaque(TAIT)]
 fn define() -> TAIT {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/coherence_generalization.rs b/tests/ui/type-alias-impl-trait/coherence_generalization.rs
index 2d7de1add49..46cde115b7f 100644
--- a/tests/ui/type-alias-impl-trait/coherence_generalization.rs
+++ b/tests/ui/type-alias-impl-trait/coherence_generalization.rs
@@ -6,6 +6,7 @@
 #![feature(type_alias_impl_trait)]
 trait Trait {}
 type Opaque<T> = impl Sized;
+#[define_opaque(Opaque)]
 fn foo<T>() -> Opaque<T> {
     ()
 }
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
index 5b77bb6c2bc..dc15d530fd7 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.infer.stderr
@@ -1,8 +1,8 @@
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:7:24
+  --> $DIR/const_generic_type.rs:8:24
    |
-LL | async fn test<const N: crate::Bar>() {
-   |                        ^^^^^^^^^^
+LL | async fn test<const N: Bar>() {
+   |                        ^^^
    |
    = note: the only supported types are integers, `bool`, and `char`
 
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
index c7c93eee63e..ba97bbf89f8 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.no_infer.stderr
@@ -1,36 +1,36 @@
 error: `Bar` is forbidden as the type of a const generic parameter
-  --> $DIR/const_generic_type.rs:7:24
+  --> $DIR/const_generic_type.rs:8:24
    |
-LL | async fn test<const N: crate::Bar>() {
-   |                        ^^^^^^^^^^
+LL | async fn test<const N: Bar>() {
+   |                        ^^^
    |
    = note: the only supported types are integers, `bool`, and `char`
 
-error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/const_generic_type.rs:7:10
+error: item does not constrain `Bar::{opaque#0}`
+  --> $DIR/const_generic_type.rs:8:10
    |
-LL | async fn test<const N: crate::Bar>() {
+LL | async fn test<const N: Bar>() {
    |          ^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/const_generic_type.rs:5:12
    |
 LL | type Bar = impl std::fmt::Display;
    |            ^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/const_generic_type.rs:7:38
+error: item does not constrain `Bar::{opaque#0}`
+  --> $DIR/const_generic_type.rs:8:31
    |
-LL |   async fn test<const N: crate::Bar>() {
-   |  ______________________________________^
+LL |   async fn test<const N: Bar>() {
+   |  _______________________________^
 ...  |
 LL | |     let x: u32 = N;
 LL | | }
    | |_^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/const_generic_type.rs:5:12
    |
 LL | type Bar = impl std::fmt::Display;
diff --git a/tests/ui/type-alias-impl-trait/const_generic_type.rs b/tests/ui/type-alias-impl-trait/const_generic_type.rs
index 7149370048b..5b093be9231 100644
--- a/tests/ui/type-alias-impl-trait/const_generic_type.rs
+++ b/tests/ui/type-alias-impl-trait/const_generic_type.rs
@@ -4,7 +4,8 @@
 #![feature(type_alias_impl_trait)]
 type Bar = impl std::fmt::Display;
 
-async fn test<const N: crate::Bar>() {
+#[define_opaque(Bar)]
+async fn test<const N: Bar>() {
     //~^ ERROR: `Bar` is forbidden as the type of a const generic parameter
     //[no_infer]~^^ ERROR item does not constrain
     //[no_infer]~| ERROR item does not constrain
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
index 580258bbb28..c4c55d8e092 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
-  --> $DIR/constrain_in_projection.rs:24:14
+  --> $DIR/constrain_in_projection.rs:25:14
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |              ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
@@ -8,7 +8,7 @@ LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
            but trait `Trait<()>` is implemented for it
 
 error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
-  --> $DIR/constrain_in_projection.rs:24:13
+  --> $DIR/constrain_in_projection.rs:25:13
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<Bar>` is not implemented for `Foo`
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs
index 355c0e1692b..64b9c583ca2 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection.rs
@@ -20,7 +20,8 @@ impl Trait<()> for Foo {
     type Assoc = u32;
 }
 
-fn bop(_: Bar) {
+#[define_opaque(Bar)]
+fn bop() {
     let x = <Foo as Trait<Bar>>::Assoc::default();
     //[current]~^ `Foo: Trait<Bar>` is not satisfied
     //[current]~| `Foo: Trait<Bar>` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
index 777fe1e2788..d7fb6e67ad2 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
-  --> $DIR/constrain_in_projection2.rs:27:14
+  --> $DIR/constrain_in_projection2.rs:28:14
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |              ^^^ the trait `Trait<Bar>` is not implemented for `Foo`
@@ -9,7 +9,7 @@ LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
              `Foo` implements `Trait<u32>`
 
 error[E0277]: the trait bound `Foo: Trait<Bar>` is not satisfied
-  --> $DIR/constrain_in_projection2.rs:27:13
+  --> $DIR/constrain_in_projection2.rs:28:13
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait<Bar>` is not implemented for `Foo`
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
index 0d6eac4216b..7c09ab6a91a 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.next.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed: cannot satisfy `Foo: Trait<Bar>`
-  --> $DIR/constrain_in_projection2.rs:27:14
+  --> $DIR/constrain_in_projection2.rs:28:14
    |
 LL |     let x = <Foo as Trait<Bar>>::Assoc::default();
    |              ^^^ help: use the fully qualified path to an implementation: `<Type as Trait>::Assoc`
diff --git a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
index 16b1329b52f..61773cf59d4 100644
--- a/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_in_projection2.rs
@@ -23,7 +23,8 @@ impl Trait<u32> for Foo {
     type Assoc = u32;
 }
 
-fn bop(_: Bar) {
+#[define_opaque(Bar)]
+fn bop() {
     let x = <Foo as Trait<Bar>>::Assoc::default();
     //[next]~^ ERROR: cannot satisfy `Foo: Trait<Bar>`
     //[current]~^^ ERROR: `Foo: Trait<Bar>` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.rs b/tests/ui/type-alias-impl-trait/constrain_inputs.rs
index 1391a2036b2..7f6698e641d 100644
--- a/tests/ui/type-alias-impl-trait/constrain_inputs.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_inputs.rs
@@ -2,7 +2,9 @@
 
 mod lifetime_params {
     type Ty<'a> = impl Sized;
+    #[define_opaque(Ty)]
     fn defining(s: &str) -> Ty<'_> { s }
+    #[define_opaque(Ty)]
     fn execute(ty: Ty<'_>) -> &str { todo!() }
     //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
     //~| ERROR item does not constrain
@@ -15,7 +17,9 @@ mod lifetime_params {
 
 mod lifetime_params_2 {
     type Ty<'a> = impl FnOnce() -> &'a str;
+    #[define_opaque(Ty)]
     fn defining(s: &str) -> Ty<'_> { move || s }
+    #[define_opaque(Ty)]
     fn execute(ty: Ty<'_>) -> &str { ty() }
     //~^ ERROR return type references an anonymous lifetime, which is not constrained by the fn input types
     //~| ERROR item does not constrain
@@ -24,6 +28,7 @@ mod lifetime_params_2 {
 // regression test for https://github.com/rust-lang/rust/issues/97104
 mod type_params {
     type Ty<T> = impl Sized;
+    #[define_opaque(Ty)]
     fn define<T>(s: T) -> Ty<T> { s }
 
     type BadFnSig = fn(Ty<&str>) -> &str;
diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr
index 436326e66c3..b016715b129 100644
--- a/tests/ui/type-alias-impl-trait/constrain_inputs.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_inputs.stderr
@@ -1,5 +1,5 @@
 error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/constrain_inputs.rs:6:31
+  --> $DIR/constrain_inputs.rs:8:31
    |
 LL |     fn execute(ty: Ty<'_>) -> &str { todo!() }
    |                               ^^^^
@@ -8,7 +8,7 @@ LL |     fn execute(ty: Ty<'_>) -> &str { todo!() }
    = note: consider introducing a named lifetime parameter
 
 error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/constrain_inputs.rs:10:35
+  --> $DIR/constrain_inputs.rs:12:35
    |
 LL |     type BadFnSig = fn(Ty<'_>) -> &str;
    |                                   ^^^^
@@ -17,7 +17,7 @@ LL |     type BadFnSig = fn(Ty<'_>) -> &str;
    = note: consider introducing a named lifetime parameter
 
 error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types
-  --> $DIR/constrain_inputs.rs:12:42
+  --> $DIR/constrain_inputs.rs:14:42
    |
 LL |     type BadTraitRef = dyn Fn(Ty<'_>) -> &str;
    |                                          ^^^^
@@ -25,21 +25,21 @@ LL |     type BadTraitRef = dyn Fn(Ty<'_>) -> &str;
    = note: lifetimes appearing in an associated or opaque type are not considered constrained
    = note: consider introducing a named lifetime parameter
 
-error: item does not constrain `lifetime_params::Ty::{opaque#0}`, but has it in its signature
-  --> $DIR/constrain_inputs.rs:6:8
+error: item does not constrain `lifetime_params::Ty::{opaque#0}`
+  --> $DIR/constrain_inputs.rs:8:8
    |
 LL |     fn execute(ty: Ty<'_>) -> &str { todo!() }
    |        ^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/constrain_inputs.rs:4:19
    |
 LL |     type Ty<'a> = impl Sized;
    |                   ^^^^^^^^^^
 
 error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/constrain_inputs.rs:19:31
+  --> $DIR/constrain_inputs.rs:23:31
    |
 LL |     fn execute(ty: Ty<'_>) -> &str { ty() }
    |                               ^^^^
@@ -47,21 +47,21 @@ LL |     fn execute(ty: Ty<'_>) -> &str { ty() }
    = note: lifetimes appearing in an associated or opaque type are not considered constrained
    = note: consider introducing a named lifetime parameter
 
-error: item does not constrain `lifetime_params_2::Ty::{opaque#0}`, but has it in its signature
-  --> $DIR/constrain_inputs.rs:19:8
+error: item does not constrain `lifetime_params_2::Ty::{opaque#0}`
+  --> $DIR/constrain_inputs.rs:23:8
    |
 LL |     fn execute(ty: Ty<'_>) -> &str { ty() }
    |        ^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/constrain_inputs.rs:17:19
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/constrain_inputs.rs:19:19
    |
 LL |     type Ty<'a> = impl FnOnce() -> &'a str;
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0581]: return type references an anonymous lifetime, which is not constrained by the fn input types
-  --> $DIR/constrain_inputs.rs:29:37
+  --> $DIR/constrain_inputs.rs:34:37
    |
 LL |     type BadFnSig = fn(Ty<&str>) -> &str;
    |                                     ^^^^
@@ -70,7 +70,7 @@ LL |     type BadFnSig = fn(Ty<&str>) -> &str;
    = note: consider introducing a named lifetime parameter
 
 error[E0582]: binding for associated type `Output` references an anonymous lifetime, which does not appear in the trait input types
-  --> $DIR/constrain_inputs.rs:31:44
+  --> $DIR/constrain_inputs.rs:36:44
    |
 LL |     type BadTraitRef = dyn Fn(Ty<&str>) -> &str;
    |                                            ^^^^
diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs
index 3bae0f17309..dc38e9a8cdc 100644
--- a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs
+++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.rs
@@ -4,9 +4,12 @@ trait Static: 'static {}
 impl Static for () {}
 
 type Gal<T> = impl Static;
+#[define_opaque(Gal)]
 fn _defining<T>() -> Gal<T> {}
 
-trait Callable<Arg> { type Output; }
+trait Callable<Arg> {
+    type Output;
+}
 
 /// We can infer `<C as Callable<Arg>>::Output: 'static`,
 /// because we know `C: 'static` and `Arg: 'static`,
diff --git a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr
index 948bd6deacd..0edb0a06884 100644
--- a/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr
+++ b/tests/ui/type-alias-impl-trait/constrain_inputs_unsound.stderr
@@ -1,5 +1,5 @@
 error[E0582]: binding for associated type `Output` references lifetime `'a`, which does not appear in the trait input types
-  --> $DIR/constrain_inputs_unsound.rs:23:58
+  --> $DIR/constrain_inputs_unsound.rs:26:58
    |
 LL |     type MalformedTy = dyn for<'a> Callable<Gal<&'a ()>, Output = &'a str>;
    |                                                          ^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs
index db9c2cc096a..6d9c05d9c68 100644
--- a/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs
+++ b/tests/ui/type-alias-impl-trait/debug-ty-with-weak.rs
@@ -3,12 +3,10 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod bar {
-    pub type Debuggable = impl core::fmt::Debug;
-    fn foo() -> Debuggable {
-        0u32
-    }
+pub type Debuggable = impl core::fmt::Debug;
+#[define_opaque(Debuggable)]
+fn foo() -> Debuggable {
+    0u32
 }
-use bar::Debuggable;
 
 static mut TEST: Option<Debuggable> = None;
diff --git a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr
index 772f487d96a..c2c401da0e8 100644
--- a/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr
+++ b/tests/ui/type-alias-impl-trait/declared_but_never_defined.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
 LL | type Bar = impl std::fmt::Debug;
    |            ^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Bar` must be used in combination with a concrete type within the same module
+   = note: `Bar` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
index d60f1ffbccc..e97a69bd92c 100644
--- a/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
+++ b/tests/ui/type-alias-impl-trait/declared_but_not_defined_in_scope.stderr
@@ -4,7 +4,7 @@ error: unconstrained opaque type
 LL |     pub type Boo = impl ::std::fmt::Debug;
    |                    ^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Boo` must be used in combination with a concrete type within the same module
+   = note: `Boo` must be used in combination with a concrete type within the same crate
 
 error[E0308]: mismatched types
   --> $DIR/declared_but_not_defined_in_scope.rs:11:5
@@ -19,7 +19,7 @@ LL |     ""
    |
    = note: expected opaque type `Boo`
                 found reference `&'static str`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
+note: this item must have a `#[define_opaque(Boo)]` attribute to be able to define hidden types
   --> $DIR/declared_but_not_defined_in_scope.rs:10:4
    |
 LL | fn bomp() -> boo::Boo {
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.rs
new file mode 100644
index 00000000000..c8b6bdbe2b9
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.rs
@@ -0,0 +1,5 @@
+#![feature(type_alias_impl_trait)]
+
+#[define_opaque(String)]
+//~^ ERROR: only opaque types defined in the local crate can be defined
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.stderr
new file mode 100644
index 00000000000..65820e158f3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/foreign_type.stderr
@@ -0,0 +1,8 @@
+error: only opaque types defined in the local crate can be defined
+  --> $DIR/foreign_type.rs:3:17
+   |
+LL | #[define_opaque(String)]
+   |                 ^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.rs
new file mode 100644
index 00000000000..2ca2a753e20
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.rs
@@ -0,0 +1,12 @@
+#![feature(type_alias_impl_trait)]
+
+type Tait<T> = impl Sized;
+//~^ ERROR: unconstrained opaque type
+
+#[define_opaque(Tait::<()>)]
+//~^ ERROR: expected unsuffixed literal
+fn foo() {}
+
+#[define_opaque(Tait<()>)]
+//~^ ERROR: expected one of `(`, `,`, `::`, or `=`, found `<`
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.stderr
new file mode 100644
index 00000000000..96e8bc9851c
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/generics.stderr
@@ -0,0 +1,22 @@
+error: expected unsuffixed literal, found `<`
+  --> $DIR/generics.rs:6:23
+   |
+LL | #[define_opaque(Tait::<()>)]
+   |                       ^
+
+error: expected one of `(`, `,`, `::`, or `=`, found `<`
+  --> $DIR/generics.rs:10:21
+   |
+LL | #[define_opaque(Tait<()>)]
+   |                     ^ expected one of `(`, `,`, `::`, or `=`
+
+error: unconstrained opaque type
+  --> $DIR/generics.rs:3:16
+   |
+LL | type Tait<T> = impl Sized;
+   |                ^^^^^^^^^^
+   |
+   = note: `Tait` must be used in combination with a concrete type within the same crate
+
+error: aborting due to 3 previous errors
+
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.rs
new file mode 100644
index 00000000000..a02e80c6d89
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.rs
@@ -0,0 +1,5 @@
+#![feature(type_alias_impl_trait)]
+
+#[define_opaque(Boom)]
+//~^ ERROR: cannot find type alias or associated type
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.stderr
new file mode 100644
index 00000000000..6b4cd4eac51
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/invalid_path.stderr
@@ -0,0 +1,9 @@
+error[E0412]: cannot find type alias or associated type with opaqaue types `Boom` in this scope
+  --> $DIR/invalid_path.rs:3:17
+   |
+LL | #[define_opaque(Boom)]
+   |                 ^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0412`.
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.rs
new file mode 100644
index 00000000000..6a5a1b456c3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.rs
@@ -0,0 +1,5 @@
+#![feature(type_alias_impl_trait)]
+
+#[define_opaque]
+//~^ ERROR: expected list of type aliases
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.stderr
new file mode 100644
index 00000000000..a3b98ec83b2
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/missing_parens.stderr
@@ -0,0 +1,8 @@
+error: expected list of type aliases
+  --> $DIR/missing_parens.rs:3:1
+   |
+LL | #[define_opaque]
+   | ^^^^^^^^^^^^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs
new file mode 100644
index 00000000000..4b60bad5c03
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.rs
@@ -0,0 +1,7 @@
+#![feature(type_alias_impl_trait)]
+
+type Thing = ();
+
+#[define_opaque(Thing)]
+//~^ ERROR item does not contain any opaque types
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr
new file mode 100644
index 00000000000..66ae3a43b95
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/no_opaque.stderr
@@ -0,0 +1,8 @@
+error: item does not contain any opaque types
+  --> $DIR/no_opaque.rs:5:17
+   |
+LL | #[define_opaque(Thing)]
+   |                 ^^^^^
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.rs b/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.rs
new file mode 100644
index 00000000000..0ad87616a51
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.rs
@@ -0,0 +1,7 @@
+#![feature(type_alias_impl_trait)]
+
+fn foo() {}
+
+#[define_opaque(foo)]
+//~^ ERROR: expected type alias or associated type with opaqaue types
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.stderr b/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.stderr
new file mode 100644
index 00000000000..0f91533bf7e
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/define_opaques_attr/non_type.stderr
@@ -0,0 +1,9 @@
+error[E0573]: expected type alias or associated type with opaqaue types, found function `foo`
+  --> $DIR/non_type.rs:5:17
+   |
+LL | #[define_opaque(foo)]
+   |                 ^^^ not a type alias or associated type with opaqaue types
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0573`.
diff --git a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
index 75a4fbdb5d6..6a07ea05c1a 100644
--- a/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
+++ b/tests/ui/type-alias-impl-trait/defined-by-user-annotation.rs
@@ -11,9 +11,11 @@ impl<A, B: Equate<Proj = A>> Indirect for (A, B) { type Ty = (); }
 mod basic {
     use super::*;
     type Opq = impl Sized;
+    #[define_opaque(Opq)]
     fn define_1(_: Opq) {
         let _ = None::<<(Opq, u8) as Indirect>::Ty>;
     }
+    #[define_opaque(Opq)]
     fn define_2() -> Opq {
         0u8
     }
@@ -23,6 +25,7 @@ mod basic {
 mod lifetime {
     use super::*;
     type Opq<'a> = impl Sized + 'a;
+    #[define_opaque(Opq)]
     fn define<'a: 'b, 'b: 'a>(_: Opq<'a>) {
         let _ = None::<<(Opq<'a>, &'b u8) as Indirect>::Ty>;
     }
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
index 9101e4385b3..bc3904eb4e5 100644
--- a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.rs
@@ -2,6 +2,7 @@
 
 mod case1 {
     type Opaque<'x> = impl Sized + 'x;
+    #[define_opaque(Opaque)]
     fn foo<'s>() -> Opaque<'s> {
         let _ = || { let _: Opaque<'s> = (); };
         //~^ ERROR expected generic lifetime parameter, found `'_`
@@ -10,6 +11,7 @@ mod case1 {
 
 mod case2 {
     type Opaque<'x> = impl Sized + 'x;
+    #[define_opaque(Opaque)]
     fn foo<'s>() -> Opaque<'s> {
         let _ = || -> Opaque<'s> {};
         //~^ ERROR expected generic lifetime parameter, found `'_`
diff --git a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
index a8fd1f691dd..2210291d37b 100644
--- a/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
+++ b/tests/ui/type-alias-impl-trait/defined-in-closure-external-lifetime.stderr
@@ -1,18 +1,18 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/defined-in-closure-external-lifetime.rs:6:29
+  --> $DIR/defined-in-closure-external-lifetime.rs:7:29
    |
 LL |     type Opaque<'x> = impl Sized + 'x;
    |                 -- this generic parameter must be used with a generic lifetime parameter
-LL |     fn foo<'s>() -> Opaque<'s> {
+...
 LL |         let _ = || { let _: Opaque<'s> = (); };
    |                             ^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/defined-in-closure-external-lifetime.rs:14:34
+  --> $DIR/defined-in-closure-external-lifetime.rs:16:34
    |
 LL |     type Opaque<'x> = impl Sized + 'x;
    |                 -- this generic parameter must be used with a generic lifetime parameter
-LL |     fn foo<'s>() -> Opaque<'s> {
+...
 LL |         let _ = || -> Opaque<'s> {};
    |                                  ^^
 
diff --git a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
index 3e7bc32640f..b953cd646a0 100644
--- a/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
+++ b/tests/ui/type-alias-impl-trait/defining-use-submodule.rs
@@ -11,13 +11,24 @@ type Foo = impl std::fmt::Display;
 type Bar = impl std::fmt::Display;
 
 mod foo {
+    #[define_opaque(super::Foo)]
     pub(crate) fn foo() -> super::Foo {
         "foo"
     }
 
     pub(crate) mod bar {
+        #[define_opaque(crate::Bar)]
         pub(crate) fn bar() -> crate::Bar {
             1
         }
     }
 }
+
+mod bar {
+    pub type Baz = impl std::fmt::Display;
+}
+
+#[define_opaque(bar::Baz)]
+fn baz() -> bar::Baz {
+    "boom"
+}
diff --git a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
index eadf21c9138..a3b1aba7041 100644
--- a/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
+++ b/tests/ui/type-alias-impl-trait/destructure_tait-ice-113594.rs
@@ -10,6 +10,7 @@ pub struct Foo {
 
 pub type Tait = impl Sized;
 
+#[define_opaque(Tait)]
 pub async fn ice_cold(beverage: Tait) {
     // Must destructure at least one field of `Foo`
     let Foo { field } = beverage;
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
index 8ce471e3956..e56f60a6693 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal.rs
@@ -2,10 +2,12 @@
 
 pub type Opaque<'a> = impl Sized;
 
+#[define_opaque(Opaque)]
 fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> {
     a
 }
 
+#[define_opaque(Opaque)]
 fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
     //~^ ERROR:  item does not constrain
     None::<Opaque<'static>>
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal.stderr b/tests/ui/type-alias-impl-trait/different_args_considered_equal.stderr
index f27f2234525..587328e2870 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal.stderr
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal.stderr
@@ -1,11 +1,11 @@
-error: item does not constrain `Opaque::{opaque#0}`, but has it in its signature
-  --> $DIR/different_args_considered_equal.rs:9:4
+error: item does not constrain `Opaque::{opaque#0}`
+  --> $DIR/different_args_considered_equal.rs:11:4
    |
 LL | fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
    |    ^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/different_args_considered_equal.rs:3:23
    |
 LL | pub type Opaque<'a> = impl Sized;
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.rs b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.rs
index 43dfea97e6d..902d6ca57e6 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.rs
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.rs
@@ -2,6 +2,7 @@
 
 pub type Opaque<'a> = impl Sized;
 
+#[define_opaque(Opaque)]
 fn get_one<'a>(a: *mut &'a str) -> impl IntoIterator<Item = Opaque<'a>> {
     if a.is_null() {
         Some(a)
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr
index 213272f5f34..562ab4168b5 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal2.stderr
@@ -1,9 +1,9 @@
 error[E0700]: hidden type for `Opaque<'static>` captures lifetime that does not appear in bounds
-  --> $DIR/different_args_considered_equal2.rs:9:9
+  --> $DIR/different_args_considered_equal2.rs:10:9
    |
 LL | pub type Opaque<'a> = impl Sized;
    |                       ---------- opaque type defined here
-LL |
+...
 LL | fn get_one<'a>(a: *mut &'a str) -> impl IntoIterator<Item = Opaque<'a>> {
    |            -- hidden type `*mut &'a str` captures the lifetime `'a` as defined here
 ...
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal3.rs b/tests/ui/type-alias-impl-trait/different_args_considered_equal3.rs
index ea69175ba31..85a7e371b07 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal3.rs
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal3.rs
@@ -5,14 +5,12 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod defining_scope {
-    pub type Opaque<'a> = impl Sized;
+pub type Opaque<'a> = impl Sized;
 
-    fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> {
-        a
-    }
+#[define_opaque(Opaque)]
+fn get_one<'a>(a: *mut &'a str) -> Opaque<'a> {
+    a
 }
-use defining_scope::Opaque;
 
 fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
     None::<Opaque<'static>>
diff --git a/tests/ui/type-alias-impl-trait/different_args_considered_equal3.stderr b/tests/ui/type-alias-impl-trait/different_args_considered_equal3.stderr
index d8f70e3d778..06d6433c4b5 100644
--- a/tests/ui/type-alias-impl-trait/different_args_considered_equal3.stderr
+++ b/tests/ui/type-alias-impl-trait/different_args_considered_equal3.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/different_args_considered_equal3.rs:18:5
+  --> $DIR/different_args_considered_equal3.rs:16:5
    |
 LL | fn get_iter<'a>() -> impl IntoIterator<Item = Opaque<'a>> {
    |             -- lifetime `'a` defined here
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_defining_uses.rs
index 4505c4d9524..246f255e8fc 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses.rs
@@ -5,10 +5,12 @@ fn main() {}
 // two definitions with different types
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     ""
 }
 
+#[define_opaque(Foo)]
 fn bar() -> Foo {
     42i32
     //~^ ERROR concrete type differs from previous
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
index 9e6169b2af7..9a7f4b416f4 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses.rs:13:5
+  --> $DIR/different_defining_uses.rs:15:5
    |
 LL |     42i32
    |     ^^^^^ expected `&'static str`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses.rs:9:5
+  --> $DIR/different_defining_uses.rs:10:5
    |
 LL |     ""
    |     ^^
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
index 4b5f455e381..e8c40e8bf92 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.rs
@@ -2,6 +2,7 @@
 
 type Tait<'a> = impl Sized + 'a;
 
+#[define_opaque(Tait)]
 fn foo<'a, 'b>() -> Tait<'a> {
     if false {
         if { return } {
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
index 6f5be5467f7..d4bd3975924 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-2.stderr
@@ -1,23 +1,23 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type-2.rs:13:5
+  --> $DIR/different_defining_uses_never_type-2.rs:14:5
    |
 LL |     x
    |     ^ expected `i32`, got `()`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-2.rs:8:31
+  --> $DIR/different_defining_uses_never_type-2.rs:9:31
    |
 LL |             let y: Tait<'b> = 1i32;
    |                               ^^^^
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type-2.rs:8:31
+  --> $DIR/different_defining_uses_never_type-2.rs:9:31
    |
 LL |             let y: Tait<'b> = 1i32;
    |                               ^^^^ expected `()`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-2.rs:7:14
+  --> $DIR/different_defining_uses_never_type-2.rs:8:14
    |
 LL |         if { return } {
    |              ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
index a4ac27378e1..b2713b9602c 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.rs
@@ -2,6 +2,7 @@
 
 type Tait<T> = impl Sized;
 
+#[define_opaque(Tait)]
 fn foo<T, U>() -> Tait<T> {
     if false {
         if { return } {
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
index 0fdcb81f667..cb12fddd9a0 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type-3.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type-3.rs:8:30
+  --> $DIR/different_defining_uses_never_type-3.rs:9:30
    |
 LL |             let y: Tait<U> = 1i32;
    |                              ^^^^ expected `()`, got `i32`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type-3.rs:12:22
+  --> $DIR/different_defining_uses_never_type-3.rs:13:22
    |
 LL |     let x: Tait<T> = ();
    |                      ^^
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
index 0b8157fe33d..38597ccaf42 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.rs
@@ -5,14 +5,17 @@ fn main() {}
 // two definitions with different types
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     ""
 }
 
+#[define_opaque(Foo)]
 fn bar() -> Foo { //~ ERROR: concrete type differs from previous defining opaque type use
     panic!()
 }
 
+#[define_opaque(Foo)]
 fn boo() -> Foo {
     loop {}
 }
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
index 2a77eb4c4ac..38afa3cbcd0 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type.rs:12:13
+  --> $DIR/different_defining_uses_never_type.rs:14:13
    |
 LL | fn bar() -> Foo {
    |             ^^^ expected `&'static str`, got `()`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type.rs:9:5
+  --> $DIR/different_defining_uses_never_type.rs:10:5
    |
 LL |     ""
    |     ^^
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs
index c39cc192dc7..03766da34cb 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type2.rs
@@ -7,10 +7,12 @@ fn main() {}
 // two definitions with different types
 type Foo = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     ""
 }
 
+#[define_opaque(Foo)]
 fn bar(arg: bool) -> Foo {
     if arg {
         panic!()
@@ -19,6 +21,7 @@ fn bar(arg: bool) -> Foo {
     }
 }
 
+#[define_opaque(Foo)]
 fn boo(arg: bool) -> Foo {
     if arg {
         loop {}
@@ -27,6 +30,7 @@ fn boo(arg: bool) -> Foo {
     }
 }
 
+#[define_opaque(Foo)]
 fn bar2(arg: bool) -> Foo {
     if arg {
         "bar2"
@@ -35,6 +39,7 @@ fn bar2(arg: bool) -> Foo {
     }
 }
 
+#[define_opaque(Foo)]
 fn boo2(arg: bool) -> Foo {
     if arg {
         "boo2"
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs
index bc827a8f211..b5c2bf504ac 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.rs
@@ -3,9 +3,11 @@
 type Tait = impl Sized;
 
 struct One;
+#[define_opaque(Tait)]
 fn one() -> Tait { One }
 
 struct Two<T>(T);
+#[define_opaque(Tait)]
 fn two() -> Tait { Two::<()>(todo!()) }
 //~^ ERROR concrete type differs from previous defining opaque type use
 
diff --git a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
index abf4a0d241b..21fab818063 100644
--- a/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
+++ b/tests/ui/type-alias-impl-trait/different_defining_uses_never_type3.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_defining_uses_never_type3.rs:9:13
+  --> $DIR/different_defining_uses_never_type3.rs:11:13
    |
 LL | fn two() -> Tait { Two::<()>(todo!()) }
    |             ^^^^ expected `One`, got `Two<()>`
    |
 note: previous use here
-  --> $DIR/different_defining_uses_never_type3.rs:6:20
+  --> $DIR/different_defining_uses_never_type3.rs:7:20
    |
 LL | fn one() -> Tait { One }
    |                    ^^^
diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
index 4f424b8c665..ba3265343c6 100644
--- a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
+++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.rs
@@ -3,10 +3,12 @@
 
 type OneLifetime<'a, 'b> = impl std::fmt::Debug;
 
+#[define_opaque(OneLifetime)]
 fn foo<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
     a
 }
 
+#[define_opaque(OneLifetime)]
 fn bar<'a, 'b>(a: &'a u32, b: &'b u32) -> OneLifetime<'a, 'b> {
     b
     //~^ ERROR: concrete type differs from previous defining opaque type use
diff --git a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
index 07ba17ad27b..b87e884708a 100644
--- a/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
+++ b/tests/ui/type-alias-impl-trait/different_lifetimes_defining_uses.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/different_lifetimes_defining_uses.rs:11:5
+  --> $DIR/different_lifetimes_defining_uses.rs:13:5
    |
 LL |     b
    |     ^ expected `&'a u32`, got `&'b u32`
    |
 note: previous use here
-  --> $DIR/different_lifetimes_defining_uses.rs:7:5
+  --> $DIR/different_lifetimes_defining_uses.rs:8:5
    |
 LL |     a
    |     ^
diff --git a/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs
index 4332f1264a8..987ac381289 100644
--- a/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs
+++ b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.rs
@@ -2,29 +2,32 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod impl_trait_mod {
-    use super::*;
-    pub type OpaqueBlock = impl Trait;
-    //~^ ERROR unconstrained opaque type
-    pub type OpaqueIf = impl Trait;
+pub type OpaqueBlock = impl Trait;
+//~^ ERROR unconstrained opaque type
+pub type OpaqueIf = impl Trait;
 
-    pub struct BlockWrapper(OpaqueBlock);
-    pub struct IfWrapper(pub OpaqueIf);
+pub struct BlockWrapper(OpaqueBlock);
+pub struct IfWrapper(pub OpaqueIf);
 
-    pub fn if_impl() -> Parser<OpaqueIf> {
-        bind(option(block()), |_| block())
-    }
+#[define_opaque(OpaqueIf)]
+pub fn if_impl() -> Parser<OpaqueIf> {
+    bind(option(block()), |_| block())
 }
-use impl_trait_mod::*;
 
 pub trait Trait {
     type Assoc;
 }
 pub struct Parser<P>(P);
 pub struct Bind<P, F>(P, F);
-impl<P, F> Trait for Bind<P, F> { type Assoc = (); }
-impl Trait for BlockWrapper { type Assoc = (); }
-impl Trait for IfWrapper { type Assoc = (); }
+impl<P, F> Trait for Bind<P, F> {
+    type Assoc = ();
+}
+impl Trait for BlockWrapper {
+    type Assoc = ();
+}
+impl Trait for IfWrapper {
+    type Assoc = ();
+}
 
 pub fn block() -> Parser<BlockWrapper> {
     loop {}
@@ -32,8 +35,9 @@ pub fn block() -> Parser<BlockWrapper> {
 pub fn option<P: Trait>(arg: Parser<P>) -> Parser<impl Trait> {
     bind(arg, |_| block())
 }
-fn bind<P: Trait, P2, F: Fn(P::Assoc) -> Parser<P2>>(_: Parser<P>, _: F) -> Parser<Bind<P, F>>
-    { loop {} }
+fn bind<P: Trait, P2, F: Fn(P::Assoc) -> Parser<P2>>(_: Parser<P>, _: F) -> Parser<Bind<P, F>> {
+    loop {}
+}
 
 fn main() {
     if_impl().0;
diff --git a/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr
index 8e5838d5ddf..db97954f698 100644
--- a/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr
+++ b/tests/ui/type-alias-impl-trait/drop-analysis-on-unconstrained-tait.stderr
@@ -1,10 +1,10 @@
 error: unconstrained opaque type
-  --> $DIR/drop-analysis-on-unconstrained-tait.rs:7:28
+  --> $DIR/drop-analysis-on-unconstrained-tait.rs:5:24
    |
-LL |     pub type OpaqueBlock = impl Trait;
-   |                            ^^^^^^^^^^
+LL | pub type OpaqueBlock = impl Trait;
+   |                        ^^^^^^^^^^
    |
-   = note: `OpaqueBlock` must be used in combination with a concrete type within the same module
+   = note: `OpaqueBlock` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs
index b1d5961067b..5dda2597c66 100644
--- a/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs
+++ b/tests/ui/type-alias-impl-trait/duplicate-lifetimes-from-rpit-containing-tait.rs
@@ -4,6 +4,7 @@
 
 type Opaque<'lt> = impl Sized + 'lt;
 
+#[define_opaque(Opaque)]
 fn test<'a>(
     arg: impl Iterator<Item = &'a u8>,
 ) -> impl Iterator<Item = Opaque<'a>> {
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
index b209b4bc89d..64f926fba9e 100644
--- a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.rs
@@ -7,19 +7,21 @@ impl<T> Trait<'_, '_> for T {}
 
 mod mod1 {
     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    #[define_opaque(Opaque)]
     fn test<'a>() -> Opaque<'a, 'a> {}
     //~^ ERROR non-defining opaque type use in defining scope
-    //~| ERROR non-defining opaque type use in defining scope
 }
 
 mod mod2 {
     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    #[define_opaque(Opaque)]
     fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
     //~^ ERROR non-defining opaque type use in defining scope
 }
 
 mod mod3 {
     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
+    #[define_opaque(Opaque)]
     fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
     //~^ ERROR non-defining opaque type use in defining scope
 }
@@ -30,6 +32,7 @@ mod mod3 {
 // it is ambiguous whether `Opaque<'a> := &'a ()` or `Opaque<'a> := &'static ()`
 mod mod4 {
     type Opaque<'a> = impl super::Trait<'a, 'a>;
+    #[define_opaque(Opaque)]
     fn test<'a: 'static>() -> Opaque<'a> {}
     //~^ ERROR expected generic lifetime parameter, found `'static`
 }
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
index b08bc8b8268..34af7cb32c2 100644
--- a/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-not-ok.stderr
@@ -1,17 +1,5 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/equal-lifetime-params-not-ok.rs:10:22
-   |
-LL |     fn test<'a>() -> Opaque<'a, 'a> {}
-   |                      ^^^^^^^^^^^^^^ generic argument `'a` used twice
-   |
-note: for this opaque type
-  --> $DIR/equal-lifetime-params-not-ok.rs:9:27
-   |
-LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
-   |                           ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: non-defining opaque type use in defining scope
-  --> $DIR/equal-lifetime-params-not-ok.rs:10:37
+  --> $DIR/equal-lifetime-params-not-ok.rs:11:37
    |
 LL |     fn test<'a>() -> Opaque<'a, 'a> {}
    |                                     ^^
@@ -23,7 +11,7 @@ LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
    |                 ^^  ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/equal-lifetime-params-not-ok.rs:17:49
+  --> $DIR/equal-lifetime-params-not-ok.rs:18:49
    |
 LL |     fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {}
    |                                                 ^^
@@ -35,25 +23,26 @@ LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
    |                 ^^  ^^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/equal-lifetime-params-not-ok.rs:23:61
+  --> $DIR/equal-lifetime-params-not-ok.rs:25:61
    |
 LL |     fn test<'a: 'b, 'b: 'a>(a: &'a str) -> Opaque<'a, 'b> { a }
    |                                                             ^
    |
 note: lifetime used multiple times
-  --> $DIR/equal-lifetime-params-not-ok.rs:22:17
+  --> $DIR/equal-lifetime-params-not-ok.rs:23:17
    |
 LL |     type Opaque<'a, 'b> = impl super::Trait<'a, 'b>;
    |                 ^^  ^^
 
 error[E0792]: expected generic lifetime parameter, found `'static`
-  --> $DIR/equal-lifetime-params-not-ok.rs:33:42
+  --> $DIR/equal-lifetime-params-not-ok.rs:36:42
    |
 LL |     type Opaque<'a> = impl super::Trait<'a, 'a>;
    |                 -- cannot use static lifetime; use a bound lifetime instead or remove the lifetime parameter from the opaque type
+LL |     #[define_opaque(Opaque)]
 LL |     fn test<'a: 'static>() -> Opaque<'a> {}
    |                                          ^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 4 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
index 0ce85a4d6cb..711aca662d1 100644
--- a/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
+++ b/tests/ui/type-alias-impl-trait/equal-lifetime-params-ok.rs
@@ -12,6 +12,7 @@ impl<T> Trait<'_, '_> for T {}
 
 mod equal_params {
     type Opaque<'a: 'b, 'b: 'a> = impl super::Trait<'a, 'b>;
+    #[define_opaque(Opaque)]
     fn test<'a: 'b, 'b: 'a>() -> Opaque<'a, 'b> {
         let _ = None::<&'a &'b &'a ()>;
         0u8
@@ -20,6 +21,7 @@ mod equal_params {
 
 mod equal_static {
     type Opaque<'a: 'static> = impl Sized + 'a;
+    #[define_opaque(Opaque)]
     fn test<'a: 'static>() -> Opaque<'a> {
         let _ = None::<&'static &'a ()>;
         0u8
diff --git a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
index 07206dd2491..31bdd0815ec 100644
--- a/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
+++ b/tests/ui/type-alias-impl-trait/escaping-bound-var.rs
@@ -16,6 +16,7 @@ impl Trait<'_> for () {
 
 impl Test<'_> for () {}
 
+#[define_opaque(Foo)]
 fn constrain() -> Foo {
     ()
 }
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
index 9ed010f2293..726820bbd5a 100644
--- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.rs
@@ -22,10 +22,12 @@ type StateWidget<'a> = impl Widget<&'a ()>;
 impl<F: for<'a> Fn(&'a ()) -> StateWidget<'a>> Widget<()> for StatefulWidget<F> {
     type State = ();
 
+    #[define_opaque(StateWidget)]
     fn make_state(&self) -> Self::State {}
     //~^ ERROR item does not constrain
 }
 
+#[define_opaque(StateWidget)]
 fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
     //~^ ERROR item does not constrain
     StatefulWidget(build)
diff --git a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
index 9a3f4ae4c1c..4f5c65adab9 100644
--- a/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
+++ b/tests/ui/type-alias-impl-trait/failed-to-normalize-ice-99945.stderr
@@ -1,31 +1,40 @@
-error: item does not constrain `StateWidget::{opaque#0}`, but has it in its signature
-  --> $DIR/failed-to-normalize-ice-99945.rs:25:8
+error: item does not constrain `StateWidget::{opaque#0}`
+  --> $DIR/failed-to-normalize-ice-99945.rs:26:8
    |
 LL |     fn make_state(&self) -> Self::State {}
    |        ^^^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/failed-to-normalize-ice-99945.rs:20:24
    |
 LL | type StateWidget<'a> = impl Widget<&'a ()>;
    |                        ^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `StateWidget::{opaque#0}`, but has it in its signature
-  --> $DIR/failed-to-normalize-ice-99945.rs:29:4
+error: item does not constrain `StateWidget::{opaque#0}`
+  --> $DIR/failed-to-normalize-ice-99945.rs:31:4
    |
 LL | fn new_stateful_widget<F: for<'a> Fn(&'a ()) -> StateWidget<'a>>(build: F) -> impl Widget<()> {
    |    ^^^^^^^^^^^^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/failed-to-normalize-ice-99945.rs:20:24
    |
 LL | type StateWidget<'a> = impl Widget<&'a ()>;
    |                        ^^^^^^^^^^^^^^^^^^^
 
+error[E0792]: expected generic lifetime parameter, found `'a`
+  --> $DIR/failed-to-normalize-ice-99945.rs:33:5
+   |
+LL | type StateWidget<'a> = impl Widget<&'a ()>;
+   |                  -- this generic parameter must be used with a generic lifetime parameter
+...
+LL |     StatefulWidget(build)
+   |     ^^^^^^^^^^^^^^^^^^^^^
+
 error[E0308]: mismatched types
-  --> $DIR/failed-to-normalize-ice-99945.rs:36:29
+  --> $DIR/failed-to-normalize-ice-99945.rs:38:29
    |
 LL | type StateWidget<'a> = impl Widget<&'a ()>;
    |                        ------------------- the expected opaque type
@@ -36,15 +45,6 @@ LL |     new_stateful_widget(|_| ()).make_state();
    = note: expected opaque type `StateWidget<'_>`
                 found unit type `()`
 
-error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/failed-to-normalize-ice-99945.rs:31:5
-   |
-LL | type StateWidget<'a> = impl Widget<&'a ()>;
-   |                  -- this generic parameter must be used with a generic lifetime parameter
-...
-LL |     StatefulWidget(build)
-   |     ^^^^^^^^^^^^^^^^^^^^^
-
 error: aborting due to 4 previous errors
 
 Some errors have detailed explanations: E0308, E0792.
diff --git a/tests/ui/type-alias-impl-trait/fallback.rs b/tests/ui/type-alias-impl-trait/fallback.rs
index d8cf7d71fef..a2f25acca0d 100644
--- a/tests/ui/type-alias-impl-trait/fallback.rs
+++ b/tests/ui/type-alias-impl-trait/fallback.rs
@@ -7,19 +7,20 @@ type Foo = impl Copy;
 
 enum Wrapper<T> {
     First(T),
-    Second
+    Second,
 }
 
 // This method constrains `Foo` to be `bool`
+#[define_opaque(Foo)]
 fn constrained_foo() -> Foo {
     true
 }
 
-
 // This method does not constrain `Foo`.
 // Per RFC 2071, function bodies may either
 // fully constrain an opaque type, or place no
 // constraints on it.
+#[define_opaque(Foo)]
 fn unconstrained_foo() -> Wrapper<Foo> {
     Wrapper::Second
     //~^ ERROR: type annotations needed
diff --git a/tests/ui/type-alias-impl-trait/fallback.stderr b/tests/ui/type-alias-impl-trait/fallback.stderr
index c909ab66f0e..1eb0afb13a8 100644
--- a/tests/ui/type-alias-impl-trait/fallback.stderr
+++ b/tests/ui/type-alias-impl-trait/fallback.stderr
@@ -1,5 +1,5 @@
 error[E0283]: type annotations needed
-  --> $DIR/fallback.rs:24:5
+  --> $DIR/fallback.rs:25:5
    |
 LL | fn unconstrained_foo() -> Wrapper<Foo> {
    |                           ------------ type must be known at this point
diff --git a/tests/ui/type-alias-impl-trait/field-types.rs b/tests/ui/type-alias-impl-trait/field-types.rs
index 24e430afac3..3ea73abb03f 100644
--- a/tests/ui/type-alias-impl-trait/field-types.rs
+++ b/tests/ui/type-alias-impl-trait/field-types.rs
@@ -1,3 +1,6 @@
+//! Show that `defines(StructName)` works for
+//! fields of that struct being an opaque type.
+
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
@@ -11,6 +14,7 @@ struct Bar {
     foo: Foo,
 }
 
+#[define_opaque(Bar)]
 fn bar() -> Bar {
     Bar { foo: "foo" }
 }
diff --git a/tests/ui/type-alias-impl-trait/future.rs b/tests/ui/type-alias-impl-trait/future.rs
index 36d1dcd00ad..e233554f6a1 100644
--- a/tests/ui/type-alias-impl-trait/future.rs
+++ b/tests/ui/type-alias-impl-trait/future.rs
@@ -11,6 +11,7 @@ trait Bar {
 
 type FooFuture<B> = impl Future<Output = ()>;
 
+#[define_opaque(FooFuture)]
 fn foo<B: Bar>(bar: B) -> FooFuture<B> {
     async move { bar.bar() }
     //~^ ERROR: the trait bound `B: Bar` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/future.stderr b/tests/ui/type-alias-impl-trait/future.stderr
index 047ad164239..8510ab27fb7 100644
--- a/tests/ui/type-alias-impl-trait/future.stderr
+++ b/tests/ui/type-alias-impl-trait/future.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `B: Bar` is not satisfied
-  --> $DIR/future.rs:15:5
+  --> $DIR/future.rs:16:5
    |
 LL |     async move { bar.bar() }
    |     ^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
    |
 note: required by a bound in `foo`
-  --> $DIR/future.rs:14:11
+  --> $DIR/future.rs:15:11
    |
 LL | fn foo<B: Bar>(bar: B) -> FooFuture<B> {
    |           ^^^ required by this bound in `foo`
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
index e5f86c8c193..43e887f36c5 100644
--- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.basic.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/generic-not-strictly-equal.rs:33:5
+  --> $DIR/generic-not-strictly-equal.rs:34:5
    |
 LL | type Opaque<'a> = impl Copy + Captures<'a>;
    |             -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
index 693af69d6fa..4a5360c9922 100644
--- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.member_constraints.stderr
@@ -1,9 +1,9 @@
 error[E0700]: hidden type for `Opaque<'x>` captures lifetime that does not appear in bounds
-  --> $DIR/generic-not-strictly-equal.rs:33:5
+  --> $DIR/generic-not-strictly-equal.rs:34:5
    |
 LL | type Opaque<'a> = impl Copy + Captures<'a>;
    |                   ------------------------ opaque type defined here
-LL |
+...
 LL | fn test<'x>(_: Opaque<'x>) {
    |         -- hidden type `&'x u8` captures the lifetime `'x` as defined here
 ...
diff --git a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
index a059fd3b822..c1059e3da33 100644
--- a/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
+++ b/tests/ui/type-alias-impl-trait/generic-not-strictly-equal.rs
@@ -20,6 +20,7 @@ fn relate<X>(_: X, _: X) {}
 
 type Opaque<'a> = impl Copy + Captures<'a>;
 
+#[define_opaque(Opaque)]
 fn test<'x>(_: Opaque<'x>) {
     let opaque = None::<Opaque<'_>>; // let's call this lifetime '?1
 
diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
index 8b683ad2828..d55a9a376b9 100644
--- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
+++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.rs
@@ -4,10 +4,12 @@ fn main() {}
 
 type MyIter<T> = impl Iterator<Item = T>;
 
+#[define_opaque(MyIter)]
 fn my_iter<T>(t: T) -> MyIter<T> {
     std::iter::once(t)
 }
 
+#[define_opaque(MyIter)]
 fn my_iter2<T>(t: T) -> MyIter<T> {
     Some(t).into_iter()
     //~^ ERROR concrete type differs from previous
diff --git a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
index 72271d158a1..6d3279144d8 100644
--- a/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_different_defining_uses.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_different_defining_uses.rs:12:5
+  --> $DIR/generic_different_defining_uses.rs:14:5
    |
 LL |     Some(t).into_iter()
    |     ^^^^^^^^^^^^^^^^^^^ expected `std::iter::Once<T>`, got `std::option::IntoIter<T>`
    |
 note: previous use here
-  --> $DIR/generic_different_defining_uses.rs:8:5
+  --> $DIR/generic_different_defining_uses.rs:9:5
    |
 LL |     std::iter::once(t)
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
index 169d4f8d509..45da4145278 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.rs
@@ -4,8 +4,8 @@ fn main() {}
 
 type Two<'a, 'b> = impl std::fmt::Debug;
 
+#[define_opaque(Two)]
 fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-    //~^ ERROR non-defining opaque type use
     t
     //~^ ERROR non-defining opaque type use
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
index b03bf2466e6..352e6fd3c5c 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_lifetime_param.stderr
@@ -1,16 +1,4 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_lifetime_param.rs:7:26
-   |
-LL | fn one<'a>(t: &'a ()) -> Two<'a, 'a> {
-   |                          ^^^^^^^^^^^ generic argument `'a` used twice
-   |
-note: for this opaque type
-  --> $DIR/generic_duplicate_lifetime_param.rs:5:20
-   |
-LL | type Two<'a, 'b> = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-
-error: non-defining opaque type use in defining scope
   --> $DIR/generic_duplicate_lifetime_param.rs:9:5
    |
 LL |     t
@@ -22,5 +10,5 @@ note: lifetime used multiple times
 LL | type Two<'a, 'b> = impl std::fmt::Debug;
    |          ^^  ^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
index e3c6f4d874b..e8ed38a24ce 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.rs
@@ -18,20 +18,20 @@ type TwoLifetimes<'a, 'b> = impl Debug;
 
 type TwoConsts<const X: usize, const Y: usize> = impl Debug;
 
+#[define_opaque(TwoTys)]
 fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
 
+#[define_opaque(TwoLifetimes)]
 fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
 
+#[define_opaque(TwoConsts)]
 fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-    //~^ ERROR non-defining opaque type use in defining scope
     t
     //~^ ERROR non-defining opaque type use in defining scope
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
index 73570de5326..3e048c8138d 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use.stderr
@@ -1,16 +1,4 @@
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:21:30
-   |
-LL | fn one_ty<T: Debug>(t: T) -> TwoTys<T, T> {
-   |                              ^^^^^^^^^^^^ generic argument `T` used twice
-   |
-note: for this opaque type
-  --> $DIR/generic_duplicate_param_use.rs:15:21
-   |
-LL | type TwoTys<T, U> = impl Debug;
-   |                     ^^^^^^^^^^
-
-error: non-defining opaque type use in defining scope
   --> $DIR/generic_duplicate_param_use.rs:23:5
    |
 LL |     t
@@ -23,30 +11,6 @@ LL | type TwoTys<T, U> = impl Debug;
    |             ^  ^
 
 error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:27:36
-   |
-LL | fn one_lifetime<'a>(t: &'a u32) -> TwoLifetimes<'a, 'a> {
-   |                                    ^^^^^^^^^^^^^^^^^^^^ generic argument `'a` used twice
-   |
-note: for this opaque type
-  --> $DIR/generic_duplicate_param_use.rs:17:29
-   |
-LL | type TwoLifetimes<'a, 'b> = impl Debug;
-   |                             ^^^^^^^^^^
-
-error: non-defining opaque type use in defining scope
-  --> $DIR/generic_duplicate_param_use.rs:33:50
-   |
-LL | fn one_const<const N: usize>(t: *mut [u8; N]) -> TwoConsts<N, N> {
-   |                                                  ^^^^^^^^^^^^^^^ generic argument `N` used twice
-   |
-note: for this opaque type
-  --> $DIR/generic_duplicate_param_use.rs:19:50
-   |
-LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
-   |                                                  ^^^^^^^^^^
-
-error: non-defining opaque type use in defining scope
   --> $DIR/generic_duplicate_param_use.rs:29:5
    |
 LL |     t
@@ -70,5 +34,5 @@ note: constant used multiple times
 LL | type TwoConsts<const X: usize, const Y: usize> = impl Debug;
    |                ^^^^^^^^^^^^^^  ^^^^^^^^^^^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs
index 439214911eb..849d237b809 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use10.rs
@@ -7,6 +7,7 @@ fn main() {}
 
 type Two<T: Debug, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
     (t, 4u32)
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
index 201535efe15..073684b8add 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.rs
@@ -7,6 +7,7 @@ fn main() {}
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
     //~^ ERROR `T` doesn't implement `Debug`
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
index cd6e85764bd..ef0e73f1481 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `T` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use2.rs:11:5
+  --> $DIR/generic_duplicate_param_use2.rs:12:5
    |
 LL |     t
    |     ^ `T` cannot be formatted using `{:?}` because it doesn't implement `Debug`
@@ -10,7 +10,7 @@ note: required by a bound in an opaque type
 LL | type Two<T, U> = impl Debug;
    |                       ^^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/generic_duplicate_param_use2.rs:10:1
+  --> $DIR/generic_duplicate_param_use2.rs:11:1
    |
 LL | fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
index 2074f12750f..f732b233396 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.rs
@@ -7,10 +7,12 @@ fn main() {}
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug, U>(t: T, _: U) -> Two<T, U> {
     t
 }
 
+#[define_opaque(Two)]
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
     u
     //~^ ERROR concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
index 9a10a4980d8..b0a1bd77f85 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use3.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use3.rs:15:5
+  --> $DIR/generic_duplicate_param_use3.rs:17:5
    |
 LL |     u
    |     ^ expected `T`, got `U`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use3.rs:11:5
+  --> $DIR/generic_duplicate_param_use3.rs:12:5
    |
 LL |     t
    |     ^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
index d1e5a0f0198..68a8f3da168 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.rs
@@ -7,6 +7,7 @@ fn main() {}
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
     u
     //~^ ERROR `U` doesn't implement `Debug`
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
index bf3c4a0e04f..0932c72ff93 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use4.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_duplicate_param_use4.rs:11:5
+  --> $DIR/generic_duplicate_param_use4.rs:12:5
    |
 LL |     u
    |     ^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
@@ -10,7 +10,7 @@ note: required by a bound in an opaque type
 LL | type Two<T, U> = impl Debug;
    |                       ^^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/generic_duplicate_param_use4.rs:10:1
+  --> $DIR/generic_duplicate_param_use4.rs:11:1
    |
 LL | fn three<T, U: Debug>(_: T, u: U) -> Two<T, U> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
index b3d6beaf848..d450bef5758 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.rs
@@ -7,10 +7,12 @@ fn main() {}
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u)
 }
 
+#[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (u, t)
     //~^ ERROR concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
index b0027f8fa57..b8a2a937416 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use5.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use5.rs:15:5
+  --> $DIR/generic_duplicate_param_use5.rs:17:5
    |
 LL |     (u, t)
    |     ^^^^^^ expected `(T, U)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use5.rs:11:5
+  --> $DIR/generic_duplicate_param_use5.rs:12:5
    |
 LL |     (t, u)
    |     ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
index fa8b2a290b9..24d03b9e60d 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.rs
@@ -7,10 +7,12 @@ fn main() {}
 // test that unused generic parameters are ok
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, t)
 }
 
+#[define_opaque(Two)]
 fn three<T: Copy + Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (u, t)
     //~^ ERROR concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
index 09c01932cef..983e58d3c70 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use6.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use6.rs:15:5
+  --> $DIR/generic_duplicate_param_use6.rs:17:5
    |
 LL |     (u, t)
    |     ^^^^^^ expected `(T, T)`, got `(U, T)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use6.rs:11:5
+  --> $DIR/generic_duplicate_param_use6.rs:12:5
    |
 LL |     (t, t)
    |     ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs
index adc912294fd..6f4a81ed760 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use7.rs
@@ -7,18 +7,22 @@ fn main() {}
 
 type Two<A: Debug, B> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug + Copy, U>(t: T, u: U) -> Two<T, U> {
     (t, t)
 }
 
+#[define_opaque(Two)]
 fn three<T: Debug, U>(t: T, t2: T, u: U) -> Two<T, U> {
     (t, t2)
 }
 
+#[define_opaque(Two)]
 fn four<T: Debug, U, V>(t: T, t2: T, u: U, v: V) -> Two<T, U> {
     (t, t2)
 }
 
+#[define_opaque(Two)]
 fn five<X, Y: Debug>(x: X, y: Y, y2: Y) -> Two<Y, X> {
     (y, y2)
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
index 76c13bb027b..03057c84782 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.rs
@@ -6,10 +6,12 @@ fn main() {}
 
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn two<T: Debug, U: Debug>(t: T, _: U) -> Two<T, U> {
     (t, 4u32)
 }
 
+#[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(_: T, u: U) -> Two<T, U> {
     (u, 4u32)
     //~^ concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
index 09d2abe3663..48c98c1e2b1 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use8.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use8.rs:14:5
+  --> $DIR/generic_duplicate_param_use8.rs:16:5
    |
 LL |     (u, 4u32)
    |     ^^^^^^^^^ expected `(T, u32)`, got `(U, u32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use8.rs:10:5
+  --> $DIR/generic_duplicate_param_use8.rs:11:5
    |
 LL |     (t, 4u32)
    |     ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
index 5da7aab0da7..74176550ab2 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.rs
@@ -11,10 +11,12 @@ trait Foo {
     const BAR: Self::Bar;
 }
 
+#[define_opaque(Two)]
 fn two<T: Debug + Foo, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u, T::BAR)
 }
 
+#[define_opaque(Two)]
 fn three<T: Debug, U: Debug>(t: T, u: U) -> Two<T, U> {
     (t, u, 42)
     //~^ ERROR concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
index 6e1bb3dfa17..542324c949f 100644
--- a/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_duplicate_param_use9.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/generic_duplicate_param_use9.rs:19:5
+  --> $DIR/generic_duplicate_param_use9.rs:21:5
    |
 LL |     (t, u, 42)
    |     ^^^^^^^^^^ expected `(A, B, <A as Foo>::Bar)`, got `(A, B, i32)`
    |
 note: previous use here
-  --> $DIR/generic_duplicate_param_use9.rs:15:5
+  --> $DIR/generic_duplicate_param_use9.rs:16:5
    |
 LL |     (t, u, T::BAR)
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs
index b9b34f55e7e..d5fb1b461ec 100644
--- a/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs
+++ b/tests/ui/type-alias-impl-trait/generic_lifetime_param.rs
@@ -6,6 +6,7 @@ fn main() {}
 
 type Region<'a> = impl std::fmt::Debug;
 
+#[define_opaque(Region)]
 fn region<'b>(a: &'b ()) -> Region<'b> {
     a
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
index 68f4c6923ae..7791410294c 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.rs
@@ -12,20 +12,20 @@ type OneConst<const X: usize> = impl Debug;
 
 // Not defining uses, because they doesn't define *all* possible generics.
 
+#[define_opaque(OneTy)]
 fn concrete_ty() -> OneTy<u32> {
-    //~^ ERROR: non-defining opaque type use in defining scope
     5u32
     //~^ ERROR: expected generic type parameter, found `u32`
 }
 
+#[define_opaque(OneLifetime)]
 fn concrete_lifetime() -> OneLifetime<'static> {
-    //~^ ERROR: non-defining opaque type use in defining scope
     6u32
     //~^ ERROR: expected generic lifetime parameter, found `'static`
 }
 
+#[define_opaque(OneConst)]
 fn concrete_const() -> OneConst<{ 123 }> {
-    //~^ ERROR: non-defining opaque type use in defining scope
     7u32
     //~^ ERROR: expected generic constant parameter, found `123`
 }
diff --git a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
index bd68b4e3ea4..1b0ce7cc619 100644
--- a/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_nondefining_use.stderr
@@ -1,15 +1,3 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:15:21
-   |
-LL | fn concrete_ty() -> OneTy<u32> {
-   |                     ^^^^^^^^^^ argument `u32` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/generic_nondefining_use.rs:7:17
-   |
-LL | type OneTy<T> = impl Debug;
-   |                 ^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `u32`
   --> $DIR/generic_nondefining_use.rs:17:5
    |
@@ -19,30 +7,6 @@ LL | type OneTy<T> = impl Debug;
 LL |     5u32
    |     ^^^^
 
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:21:27
-   |
-LL | fn concrete_lifetime() -> OneLifetime<'static> {
-   |                           ^^^^^^^^^^^^^^^^^^^^ argument `'static` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/generic_nondefining_use.rs:9:24
-   |
-LL | type OneLifetime<'a> = impl Debug;
-   |                        ^^^^^^^^^^
-
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/generic_nondefining_use.rs:27:24
-   |
-LL | fn concrete_const() -> OneConst<{ 123 }> {
-   |                        ^^^^^^^^^^^^^^^^^ argument `123` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/generic_nondefining_use.rs:11:33
-   |
-LL | type OneConst<const X: usize> = impl Debug;
-   |                                 ^^^^^^^^^^
-
 error[E0792]: expected generic lifetime parameter, found `'static`
   --> $DIR/generic_nondefining_use.rs:23:5
    |
@@ -61,6 +25,6 @@ LL | type OneConst<const X: usize> = impl Debug;
 LL |     7u32
    |     ^^^^
 
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.rs b/tests/ui/type-alias-impl-trait/generic_not_used.rs
index c70f473cff5..6042cdd30a9 100644
--- a/tests/ui/type-alias-impl-trait/generic_not_used.rs
+++ b/tests/ui/type-alias-impl-trait/generic_not_used.rs
@@ -5,6 +5,7 @@ fn main() {}
 type WrongGeneric<T: 'static> = impl 'static;
 //~^ ERROR: at least one trait must be specified
 
+#[define_opaque(WrongGeneric)]
 fn wrong_generic<U: 'static, V: 'static>(_: U, v: V) -> WrongGeneric<U> {
     v
     //~^ ERROR type parameter `V` is part of concrete type but not used in parameter list
diff --git a/tests/ui/type-alias-impl-trait/generic_not_used.stderr b/tests/ui/type-alias-impl-trait/generic_not_used.stderr
index fd720239a52..5fe2fefcecf 100644
--- a/tests/ui/type-alias-impl-trait/generic_not_used.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_not_used.stderr
@@ -5,7 +5,7 @@ LL | type WrongGeneric<T: 'static> = impl 'static;
    |                                 ^^^^^^^^^^^^
 
 error: type parameter `V` is part of concrete type but not used in parameter list for the `impl Trait` type alias
-  --> $DIR/generic_not_used.rs:9:5
+  --> $DIR/generic_not_used.rs:10:5
    |
 LL |     v
    |     ^
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
index c60f5c11cd1..4b8a1cfc472 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.rs
@@ -9,6 +9,7 @@ fn main() {
     type WrongGeneric<T> = impl 'static;
     //~^ ERROR: at least one trait must be specified
 
+    #[define_opaque(WrongGeneric)]
     fn wrong_generic<T>(t: T) -> WrongGeneric<T> {
         t
         //~^ ERROR the parameter type `T` may not live long enough
diff --git a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
index c352a33fbbc..2b3f7d75028 100644
--- a/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_type_does_not_live_long_enough.stderr
@@ -14,7 +14,7 @@ LL |     type WrongGeneric<T> = impl 'static;
    |                       - this generic parameter must be used with a generic type parameter
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/generic_type_does_not_live_long_enough.rs:13:9
+  --> $DIR/generic_type_does_not_live_long_enough.rs:14:9
    |
 LL |         t
    |         ^
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs
index 1acacc778de..9c2180e92fc 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.rs
@@ -6,6 +6,7 @@ trait Trait {}
 type Underconstrained<T: Trait> = impl Send;
 
 // no `Trait` bound
+#[define_opaque(Underconstrained)]
 fn underconstrain<T>(_: T) -> Underconstrained<T> {
     //~^ ERROR the trait bound `T: Trait`
     //~| ERROR the trait bound `T: Trait`
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
index c24f8fd867f..b1bc62c5910 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/generic_underconstrained.rs:9:31
+  --> $DIR/generic_underconstrained.rs:10:31
    |
 LL | fn underconstrain<T>(_: T) -> Underconstrained<T> {
    |                               ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
@@ -15,7 +15,7 @@ LL | fn underconstrain<T: Trait>(_: T) -> Underconstrained<T> {
    |                    +++++++
 
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/generic_underconstrained.rs:9:31
+  --> $DIR/generic_underconstrained.rs:10:31
    |
 LL | fn underconstrain<T>(_: T) -> Underconstrained<T> {
    |                               ^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs
index 1e1bece9a1c..f05f9776006 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.rs
@@ -5,6 +5,7 @@ fn main() {}
 type Underconstrained<T: std::fmt::Debug> = impl Send;
 
 // not a defining use, because it doesn't define *all* possible generics
+#[define_opaque(Underconstrained)]
 fn underconstrained<U>(_: U) -> Underconstrained<U> {
     //~^ ERROR `U` doesn't implement `Debug`
     //~| ERROR `U` doesn't implement `Debug`
@@ -14,6 +15,7 @@ fn underconstrained<U>(_: U) -> Underconstrained<U> {
 type Underconstrained2<T: std::fmt::Debug> = impl Send;
 
 // not a defining use, because it doesn't define *all* possible generics
+#[define_opaque(Underconstrained2)]
 fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
     //~^ ERROR `V` doesn't implement `Debug`
     //~| ERROR `V` doesn't implement `Debug`
diff --git a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
index 93df5ddca79..429c3b9175a 100644
--- a/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
+++ b/tests/ui/type-alias-impl-trait/generic_underconstrained2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:8:33
+  --> $DIR/generic_underconstrained2.rs:9:33
    |
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                                 ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
@@ -15,13 +15,13 @@ LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      +++++++++++++++++
 
 error[E0277]: `V` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:17:43
+  --> $DIR/generic_underconstrained2.rs:19:43
    |
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                                           ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
 note: required by a bound on the type alias `Underconstrained2`
-  --> $DIR/generic_underconstrained2.rs:14:27
+  --> $DIR/generic_underconstrained2.rs:15:27
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl Send;
    |                           ^^^^^^^^^^^^^^^ required by this bound
@@ -31,7 +31,7 @@ LL | fn underconstrained2<U, V: std::fmt::Debug>(_: U, _: V) -> Underconstrained
    |                          +++++++++++++++++
 
 error[E0277]: `U` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:8:33
+  --> $DIR/generic_underconstrained2.rs:9:33
    |
 LL | fn underconstrained<U>(_: U) -> Underconstrained<U> {
    |                                 ^^^^^^^^^^^^^^^^^^^ `U` cannot be formatted using `{:?}` because it doesn't implement `Debug`
@@ -48,13 +48,13 @@ LL | fn underconstrained<U: std::fmt::Debug>(_: U) -> Underconstrained<U> {
    |                      +++++++++++++++++
 
 error[E0277]: `V` doesn't implement `Debug`
-  --> $DIR/generic_underconstrained2.rs:17:43
+  --> $DIR/generic_underconstrained2.rs:19:43
    |
 LL | fn underconstrained2<U, V>(_: U, _: V) -> Underconstrained2<V> {
    |                                           ^^^^^^^^^^^^^^^^^^^^ `V` cannot be formatted using `{:?}` because it doesn't implement `Debug`
    |
 note: required by a bound on the type alias `Underconstrained2`
-  --> $DIR/generic_underconstrained2.rs:14:27
+  --> $DIR/generic_underconstrained2.rs:15:27
    |
 LL | type Underconstrained2<T: std::fmt::Debug> = impl Send;
    |                           ^^^^^^^^^^^^^^^ required by this bound
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
index eb19b49c7e2..bf97dd9a25c 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.rs
@@ -15,6 +15,7 @@ trait Trait: Sized {
 
 impl Trait for Bar {
     type Assoc = impl std::fmt::Debug;
+    //~^ ERROR: unconstrained opaque type
     fn foo() -> Foo<Bar> {
         Foo { field: () }
         //~^ ERROR: mismatched types
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
index 00aedfae463..879f024dee7 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_projection_behind_struct_field.stderr
@@ -1,20 +1,23 @@
+error: unconstrained opaque type
+  --> $DIR/hidden_behind_projection_behind_struct_field.rs:17:18
+   |
+LL |     type Assoc = impl std::fmt::Debug;
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Assoc` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/hidden_behind_projection_behind_struct_field.rs:19:22
+  --> $DIR/hidden_behind_projection_behind_struct_field.rs:20:22
    |
 LL |     type Assoc = impl std::fmt::Debug;
    |                  -------------------- the expected opaque type
-LL |     fn foo() -> Foo<Bar> {
+...
 LL |         Foo { field: () }
    |                      ^^ expected opaque type, found `()`
    |
    = note: expected opaque type `<Bar as Trait>::Assoc`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/hidden_behind_projection_behind_struct_field.rs:18:8
-   |
-LL |     fn foo() -> Foo<Bar> {
-   |        ^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
index 3117060cef0..b1dcf98f4dd 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.rs
@@ -13,6 +13,7 @@ trait Trait: Sized {
 
 impl Trait for Bar {
     type Assoc = impl std::fmt::Debug;
+    //~^ ERROR: unconstrained opaque type
     fn foo() -> Foo {
         Foo { field: () }
         //~^ ERROR: mismatched types
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
index 4910e794e8d..1820560eadd 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field2.stderr
@@ -1,20 +1,23 @@
+error: unconstrained opaque type
+  --> $DIR/hidden_behind_struct_field2.rs:15:18
+   |
+LL |     type Assoc = impl std::fmt::Debug;
+   |                  ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Assoc` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/hidden_behind_struct_field2.rs:17:22
+  --> $DIR/hidden_behind_struct_field2.rs:18:22
    |
 LL |     type Assoc = impl std::fmt::Debug;
    |                  -------------------- the expected opaque type
-LL |     fn foo() -> Foo {
+...
 LL |         Foo { field: () }
    |                      ^^ expected opaque type, found `()`
    |
    = note: expected opaque type `<Bar as Trait>::Assoc`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/hidden_behind_struct_field2.rs:16:8
-   |
-LL |     fn foo() -> Foo {
-   |        ^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs
index c1f13599412..70697e2fa65 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.rs
@@ -14,6 +14,7 @@ trait Trait: Sized {
 
 impl Trait for Bar {
     type Assoc2 = impl std::fmt::Debug;
+    //~^ ERROR: unconstrained opaque type
     type Assoc = impl Iterator<Item = Foo>;
     fn foo() -> Self::Assoc {
         vec![Foo { field: () }].into_iter()
diff --git a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr
index f10ccc00299..9ce696fa26c 100644
--- a/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_behind_struct_field3.stderr
@@ -1,5 +1,13 @@
+error: unconstrained opaque type
+  --> $DIR/hidden_behind_struct_field3.rs:16:19
+   |
+LL |     type Assoc2 = impl std::fmt::Debug;
+   |                   ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Assoc2` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/hidden_behind_struct_field3.rs:19:27
+  --> $DIR/hidden_behind_struct_field3.rs:20:27
    |
 LL |     type Assoc2 = impl std::fmt::Debug;
    |                   -------------------- the expected opaque type
@@ -9,12 +17,7 @@ LL |         vec![Foo { field: () }].into_iter()
    |
    = note: expected opaque type `<Bar as Trait>::Assoc2`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/hidden_behind_struct_field3.rs:18:8
-   |
-LL |     fn foo() -> Self::Assoc {
-   |        ^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
index 5b5acb31812..0a8860321da 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.rs
@@ -9,6 +9,7 @@
 mod sus {
     use super::*;
     pub type Sep = impl Sized + std::fmt::Display;
+    #[define_opaque(Sep)]
     pub fn mk_sep() -> Sep {
         String::from("hello")
     }
@@ -34,6 +35,7 @@ mod sus {
     // `define_tait` is not actually callable, and thus assumed
     // `Bar<()>: Copy` even though it isn't.
     pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
+    #[define_opaque(Tait)]
     pub fn define_tait() -> Tait
     where
         // this proves `Bar<()>: Copy`, but `define_tait` is
diff --git a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
index 8547fd53c18..20991a30b53 100644
--- a/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/hidden_type_mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0271]: type mismatch resolving `<() as Proj>::Assoc == i32`
-  --> $DIR/hidden_type_mismatch.rs:43:9
+  --> $DIR/hidden_type_mismatch.rs:45:9
    |
 LL |     pub type Sep = impl Sized + std::fmt::Display;
    |                    ------------------------------ the found opaque type
@@ -8,26 +8,26 @@ LL |         Bar { inner: 1i32, _marker: () }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ type mismatch resolving `<() as Proj>::Assoc == i32`
    |
 note: expected this to be `i32`
-  --> $DIR/hidden_type_mismatch.rs:20:22
+  --> $DIR/hidden_type_mismatch.rs:21:22
    |
 LL |         type Assoc = sus::Sep;
    |                      ^^^^^^^^
    = note:     expected type `i32`
            found opaque type `Sep`
 note: required for `Bar<()>` to implement `Copy`
-  --> $DIR/hidden_type_mismatch.rs:32:39
+  --> $DIR/hidden_type_mismatch.rs:33:39
    |
 LL |     impl<T: Proj<Assoc = i32> + Copy> Copy for Bar<T> {}
    |                  -----------          ^^^^     ^^^^^^
    |                  |
    |                  unsatisfied trait bound introduced here
 note: required by a bound in an opaque type
-  --> $DIR/hidden_type_mismatch.rs:36:26
+  --> $DIR/hidden_type_mismatch.rs:37:26
    |
 LL |     pub type Tait = impl Copy + From<Bar<()>> + Into<Bar<()>>;
    |                          ^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/hidden_type_mismatch.rs:37:5
+  --> $DIR/hidden_type_mismatch.rs:39:5
    |
 LL | /     pub fn define_tait() -> Tait
 LL | |     where
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs
index e43f53e4057..6008df3b0a2 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params.rs
@@ -22,6 +22,7 @@ struct Terminator;
 type Successors<'a> = impl std::fmt::Debug + 'a;
 
 impl Terminator {
+    #[define_opaque(Successors)]
     fn successors(&self, _: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {}
 }
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
index 19c6099135d..8ed7c1336f2 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params2.rs
@@ -2,6 +2,7 @@
 //! and normalizing something behind them actually works.
 
 //@ edition: 2021
+//@ check-pass
 
 #![feature(type_alias_impl_trait)]
 
@@ -22,9 +23,9 @@ struct Terminator;
 type Successors<'a> = impl std::fmt::Debug + 'a;
 
 impl Terminator {
+    #[define_opaque(Successors, Tait)]
     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
         f = g;
-        //~^ ERROR mismatched types
     }
 }
 
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
deleted file mode 100644
index 790e7fe8580..00000000000
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params2.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/higher_kinded_params2.rs:26:13
-   |
-LL | type Tait = impl std::fmt::Debug;
-   |             -------------------- the expected opaque type
-...
-LL |         f = g;
-   |             ^ expected fn pointer, found fn item
-   |
-   = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait`
-                 found fn item `for<'a> fn(&'a ()) -> String {g}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/higher_kinded_params2.rs:25:8
-   |
-LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
-   |        ^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
index 3845cde29fa..4fb2e60b5c5 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.rs
@@ -22,6 +22,7 @@ struct Terminator;
 type Successors<'a> = impl std::fmt::Debug + 'a;
 
 impl Terminator {
+    #[define_opaque(Successors, Tait)]
     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
         f = g;
         //~^ ERROR mismatched types
diff --git a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
index 41a3f9ce268..558792987f3 100644
--- a/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
+++ b/tests/ui/type-alias-impl-trait/higher_kinded_params3.stderr
@@ -1,19 +1,14 @@
 error[E0308]: mismatched types
-  --> $DIR/higher_kinded_params3.rs:26:13
+  --> $DIR/higher_kinded_params3.rs:27:9
    |
 LL | type Tait<'a> = impl std::fmt::Debug + 'a;
    |                 ------------------------- the expected opaque type
 ...
 LL |         f = g;
-   |             ^ expected fn pointer, found fn item
+   |         ^^^^^ one type is more general than the other
    |
    = note: expected fn pointer `for<'x> fn(&'x ()) -> Tait<'x>`
-                 found fn item `for<'a> fn(&'a ()) -> &'a () {g}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/higher_kinded_params3.rs:25:8
-   |
-LL |     fn successors(&self, mut f: for<'x> fn(&'x ()) -> <&'x A as B>::C) -> Successors<'_> {
-   |        ^^^^^^^^^^
+              found fn pointer `for<'a> fn(&'a ()) -> &'a ()`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
index c6d1202ef85..994adc476e2 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.rs
@@ -6,6 +6,7 @@ fn id(s: &str) -> &str {
 
 type Opaque<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque)]
 fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
     (id, id) //~ ERROR expected generic lifetime parameter, found `'_`
 }
@@ -16,22 +17,26 @@ fn id2<'a, 'b>(s: (&'a str, &'b str)) -> (&'a str, &'b str) {
 
 type Opaque2<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque2)]
 fn test2() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque2<'a>, Opaque2<'b>) {
     id2 //~ ERROR expected generic lifetime parameter, found `'a`
 }
 
 type Opaque3<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque3)]
 fn test3(s: &str) -> (impl Fn(&str) -> Opaque3<'_>, Opaque3<'_>) {
     (id, s) //~ ERROR expected generic lifetime parameter, found `'_`
 }
 
 type Opaque4<'a> = impl Sized + 'a;
+#[define_opaque(Opaque4)]
 fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
     (s, id) //~ ERROR expected generic lifetime parameter, found `'_`
 }
 
 type Inner<'a> = impl Sized;
+#[define_opaque(Inner)]
 fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
     |x| x //~ ERROR expected generic lifetime parameter, found `'a`
 }
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
index d49be73d94e..d404d60f31e 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/hkl_forbidden.rs:10:5
+  --> $DIR/hkl_forbidden.rs:11:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
@@ -8,7 +8,7 @@ LL |     (id, id)
    |     ^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/hkl_forbidden.rs:20:5
+  --> $DIR/hkl_forbidden.rs:22:5
    |
 LL | type Opaque2<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -17,7 +17,7 @@ LL |     id2
    |     ^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/hkl_forbidden.rs:26:5
+  --> $DIR/hkl_forbidden.rs:29:5
    |
 LL | type Opaque3<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
@@ -26,20 +26,20 @@ LL |     (id, s)
    |     ^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/hkl_forbidden.rs:31:5
+  --> $DIR/hkl_forbidden.rs:35:5
    |
 LL | type Opaque4<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
-LL | fn test4(s: &str) -> (Opaque4<'_>, impl Fn(&str) -> Opaque4<'_>) {
+...
 LL |     (s, id)
    |     ^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/hkl_forbidden.rs:36:5
+  --> $DIR/hkl_forbidden.rs:41:5
    |
 LL | type Inner<'a> = impl Sized;
    |            -- this generic parameter must be used with a generic lifetime parameter
-LL | fn outer_impl() -> impl for<'a> Fn(&'a ()) -> Inner<'a> {
+...
 LL |     |x| x
    |     ^^^^^
 
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
index 3d583d4413d..92e383d11f1 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.rs
@@ -10,6 +10,7 @@ impl<'a> Trait<'a> for () {
     type Assoc = ();
 }
 
+#[define_opaque(Opaque)]
 fn test() -> &'static dyn for<'a> Trait<'a, Assoc = Opaque<'a>> {
     &()
     //~^ ERROR: expected generic lifetime parameter, found `'a`
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
index 0a9a9d6bcf4..7404c844ae7 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden2.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/hkl_forbidden2.rs:14:5
+  --> $DIR/hkl_forbidden2.rs:15:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
index a4148599f77..c7f04dc07bb 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.rs
@@ -6,6 +6,7 @@ fn foo<'a>(x: &'a ()) -> &'a () {
     x
 }
 
+#[define_opaque(Opaque)]
 fn test() -> for<'a> fn(&'a ()) -> Opaque<'a> {
     foo //~ ERROR: mismatched types
 }
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
index d262177a86b..b8c04185a7d 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden3.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/hkl_forbidden3.rs:10:5
+  --> $DIR/hkl_forbidden3.rs:11:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |                   --------------- the expected opaque type
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
index fd06ea677c3..7e010918b29 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.rs
@@ -15,6 +15,7 @@ async fn operation(_: &mut ()) -> () {
     //~^ ERROR: expected generic lifetime parameter, found `'any`
 }
 
+#[define_opaque(FutNothing)]
 async fn call<F>(_f: F)
 //~^ ERROR item does not constrain
 where
diff --git a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
index feb161c3b04..2ca6a199448 100644
--- a/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
+++ b/tests/ui/type-alias-impl-trait/hkl_forbidden4.stderr
@@ -1,43 +1,43 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/hkl_forbidden4.rs:12:1
-   |
-LL | async fn operation(_: &mut ()) -> () {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
-   |
-note: previous use here
-  --> $DIR/hkl_forbidden4.rs:14:5
-   |
-LL |     call(operation).await
-   |     ^^^^^^^^^^^^^^^
-
-error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signature
-  --> $DIR/hkl_forbidden4.rs:18:10
+error: item does not constrain `FutNothing::{opaque#0}`
+  --> $DIR/hkl_forbidden4.rs:19:10
    |
 LL | async fn call<F>(_f: F)
    |          ^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/hkl_forbidden4.rs:10:23
    |
 LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: item does not constrain `FutNothing::{opaque#0}`, but has it in its signature
-  --> $DIR/hkl_forbidden4.rs:22:1
+error: item does not constrain `FutNothing::{opaque#0}`
+  --> $DIR/hkl_forbidden4.rs:23:1
    |
 LL | / {
 ...  |
 LL | | }
    | |_^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/hkl_forbidden4.rs:10:23
    |
 LL | type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
+error: concrete type differs from previous defining opaque type use
+  --> $DIR/hkl_forbidden4.rs:12:1
+   |
+LL | async fn operation(_: &mut ()) -> () {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `FutNothing<'_>`, got `{async fn body of operation()}`
+   |
+note: previous use here
+  --> $DIR/hkl_forbidden4.rs:14:5
+   |
+LL |     call(operation).await
+   |     ^^^^^^^^^^^^^^^
+
 error[E0792]: expected generic lifetime parameter, found `'any`
   --> $DIR/hkl_forbidden4.rs:14:5
    |
@@ -48,7 +48,7 @@ LL |     call(operation).await
    |     ^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'any`
-  --> $DIR/hkl_forbidden4.rs:22:1
+  --> $DIR/hkl_forbidden4.rs:23:1
    |
 LL |   type FutNothing<'a> = impl 'a + Future<Output = ()>;
    |                   -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs
index 2bcb8f06f4f..29e7c7d19fc 100644
--- a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs
+++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.rs
@@ -18,6 +18,7 @@ trait MyFrom<T>: Sized {
 trait F {}
 impl F for () {}
 type DummyT<T> = impl F;
+#[define_opaque(DummyT)]
 fn _dummy_t<T>() -> DummyT<T> {}
 
 struct Phantom1<T>(PhantomData<T>);
@@ -25,6 +26,7 @@ struct Phantom2<T>(PhantomData<T>);
 struct Scope<T>(Phantom2<DummyT<T>>);
 
 impl<T> Scope<T> {
+    #[define_opaque(DummyT)]
     fn new() -> Self {
         //~^ ERROR item does not constrain
         unimplemented!()
@@ -41,6 +43,7 @@ impl<T> MyFrom<Phantom2<T>> for Phantom1<T> {
 impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
     //~^ ERROR the type parameter `T` is not constrained by the impl
     type O = T;
+    #[define_opaque(DummyT)]
     fn my_index(self) -> Self::O {
         MyFrom::my_from(self.0).ok().unwrap()
     }
diff --git a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
index 0ab4c34381a..d18a824287c 100644
--- a/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
+++ b/tests/ui/type-alias-impl-trait/ice-failed-to-resolve-instance-for-110696.stderr
@@ -1,17 +1,17 @@
 error[E0207]: the type parameter `T` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:41:6
+  --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:43:6
    |
 LL | impl<T: MyFrom<Phantom2<DummyT<U>>>, U> MyIndex<DummyT<T>> for Scope<U> {
    |      ^ unconstrained type parameter
 
-error: item does not constrain `DummyT::{opaque#0}`, but has it in its signature
-  --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:28:8
+error: item does not constrain `DummyT::{opaque#0}`
+  --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:30:8
    |
 LL |     fn new() -> Self {
    |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/ice-failed-to-resolve-instance-for-110696.rs:20:18
    |
 LL | type DummyT<T> = impl F;
diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs
index 71416eb531a..a9cae611ec5 100644
--- a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs
+++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.rs
@@ -18,6 +18,7 @@ impl Foo for () {
 
     type Baz<T> = impl Sized;
     //~^ ERROR type `Baz` has 1 type parameter but its trait declaration has 0 type parameters
+    //~| ERROR: unconstrained opaque type
 
     fn test<'a>() -> Self::Bar<'a> {
         &()
diff --git a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
index e5a21ff8b4e..13f5d8b8ea6 100644
--- a/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
+++ b/tests/ui/type-alias-impl-trait/impl-trait-in-type-alias-with-bad-substs.stderr
@@ -7,6 +7,14 @@ LL |     type Baz<'a>;
 LL |     type Baz<T> = impl Sized;
    |              ^ found 1 type parameter
 
-error: aborting due to 1 previous error
+error: unconstrained opaque type
+  --> $DIR/impl-trait-in-type-alias-with-bad-substs.rs:19:19
+   |
+LL |     type Baz<T> = impl Sized;
+   |                   ^^^^^^^^^^
+   |
+   = note: `Baz` must be used in combination with a concrete type within the same impl
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0049`.
diff --git a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs
index 00d1a1a226d..b50345bb637 100644
--- a/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs
+++ b/tests/ui/type-alias-impl-trait/impl_for_weak_alias.rs
@@ -7,6 +7,7 @@ auto trait Trait {}
 impl Trait for Alias {}
 //~^ ERROR traits with a default impl, like `Trait`, cannot be implemented for type alias `Alias`
 
+#[define_opaque(Alias)]
 fn _def() -> Alias {
     (42, 42)
 }
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
index 91610c92d22..3bbfee42ef6 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_generic_tait.rs
@@ -9,6 +9,7 @@ impl Foo for i32 {
     type Assoc = u32;
 }
 type ImplTrait = impl Sized;
+#[define_opaque(ImplTrait)]
 fn constrain() -> ImplTrait {
     1u64
 }
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs
index 3f1a9d12b44..a05c65be48b 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.rs
@@ -5,6 +5,7 @@ impl Foo for () {}
 impl Foo for i32 {}
 
 type Bar<T: Foo> = impl std::fmt::Debug;
+#[define_opaque(Bar)]
 fn defining_use<T: Foo>() -> Bar<T> {
     42
 }
@@ -18,6 +19,7 @@ impl Bop for Bar<i32> {}
 //~^ ERROR conflicting implementations
 
 type Barr = impl std::fmt::Debug;
+#[define_opaque(Barr)]
 fn defining_use2() -> Barr {
     42
 }
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
index aaf75cc3db9..2f44ee481ad 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_same_tait.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
-  --> $DIR/impl_trait_for_same_tait.rs:17:1
+  --> $DIR/impl_trait_for_same_tait.rs:18:1
    |
 LL | impl Bop for Bar<()> {}
    | -------------------- first implementation here
@@ -8,7 +8,7 @@ LL | impl Bop for Bar<i32> {}
    | ^^^^^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
 
 error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
-  --> $DIR/impl_trait_for_same_tait.rs:26:1
+  --> $DIR/impl_trait_for_same_tait.rs:28:1
    |
 LL | impl Bop for Bar<()> {}
    | -------------------- first implementation here
@@ -17,7 +17,7 @@ LL | impl Bop for Barr {}
    | ^^^^^^^^^^^^^^^^^ conflicting implementation for `Bar<()>`
 
 error[E0119]: conflicting implementations of trait `Bop` for type `Bar<()>`
-  --> $DIR/impl_trait_for_same_tait.rs:30:1
+  --> $DIR/impl_trait_for_same_tait.rs:32:1
    |
 LL | impl Bop for Bar<()> {}
    | -------------------- first implementation here
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs
index bce5ba7c91c..07ac284d501 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait.rs
@@ -4,6 +4,7 @@
 #![feature(type_alias_impl_trait)]
 type Alias = impl Sized;
 
+#[define_opaque(Alias)]
 fn constrain() -> Alias {
     1i32
 }
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
index 8ec20acef4d..e0045df08ec 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.rs
@@ -3,17 +3,18 @@
 use std::fmt::Debug;
 
 type Foo = impl Debug;
-pub trait Yay { }
-impl Yay for Foo { }
+pub trait Yay {}
+impl Yay for Foo {}
 
+#[define_opaque(Foo)]
 fn foo() {
-    is_yay::<u32>();   //~ ERROR: the trait bound `u32: Yay` is not satisfied
+    is_yay::<u32>(); //~ ERROR: the trait bound `u32: Yay` is not satisfied
     is_debug::<u32>(); // OK
-    is_yay::<Foo>();   // OK
+    is_yay::<Foo>(); // OK
     is_debug::<Foo>(); // OK
 }
 
-fn is_yay<T: Yay>() { }
-fn is_debug<T: Debug>() { }
+fn is_yay<T: Yay>() {}
+fn is_debug<T: Debug>() {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
index 9840bcef7d1..0ebf9f06437 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound.stderr
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `u32: Yay` is not satisfied
-  --> $DIR/impl_trait_for_tait_bound.rs:10:14
+  --> $DIR/impl_trait_for_tait_bound.rs:11:14
    |
 LL |     is_yay::<u32>();
    |              ^^^ the trait `Yay` is not implemented for `u32`
    |
    = help: the trait `Yay` is implemented for `Foo`
 note: required by a bound in `is_yay`
-  --> $DIR/impl_trait_for_tait_bound.rs:16:14
+  --> $DIR/impl_trait_for_tait_bound.rs:17:14
    |
-LL | fn is_yay<T: Yay>() { }
+LL | fn is_yay<T: Yay>() {}
    |              ^^^ required by this bound in `is_yay`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
index a4b8c2d190d..0a8dadb89e2 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.rs
@@ -4,13 +4,14 @@ use std::fmt::Debug;
 
 type Foo = impl Debug;
 
-pub trait Yay { }
-impl Yay for u32 { }
+pub trait Yay {}
+impl Yay for u32 {}
 
+#[define_opaque(Foo)]
 fn foo() {
     is_yay::<Foo>(); //~ ERROR: the trait bound `Foo: Yay` is not satisfied
 }
 
-fn is_yay<T: Yay>() { }
+fn is_yay<T: Yay>() {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
index 2259aa7bb15..4fff9ad26cb 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_for_tait_bound2.stderr
@@ -1,14 +1,14 @@
 error[E0277]: the trait bound `Foo: Yay` is not satisfied
-  --> $DIR/impl_trait_for_tait_bound2.rs:11:14
+  --> $DIR/impl_trait_for_tait_bound2.rs:12:14
    |
 LL |     is_yay::<Foo>();
    |              ^^^ the trait `Yay` is not implemented for `Foo`
    |
    = help: the trait `Yay` is implemented for `u32`
 note: required by a bound in `is_yay`
-  --> $DIR/impl_trait_for_tait_bound2.rs:14:14
+  --> $DIR/impl_trait_for_tait_bound2.rs:15:14
    |
-LL | fn is_yay<T: Yay>() { }
+LL | fn is_yay<T: Yay>() {}
    |              ^^^ required by this bound in `is_yay`
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/type-alias-impl-trait/impl_trait_in_trait_defined_outside_trait.stderr b/tests/ui/type-alias-impl-trait/impl_trait_in_trait_defined_outside_trait.stderr
index 1d7a97c5367..a7e4ba29d3a 100644
--- a/tests/ui/type-alias-impl-trait/impl_trait_in_trait_defined_outside_trait.stderr
+++ b/tests/ui/type-alias-impl-trait/impl_trait_in_trait_defined_outside_trait.stderr
@@ -11,11 +11,6 @@ LL |         let x: Self::Assoc = 42;
    |
    = note: expected opaque type `<() as Trait>::Assoc`
                      found type `{integer}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/impl_trait_in_trait_defined_outside_trait.rs:14:8
-   |
-LL |     fn foo() {
-   |        ^^^
 
 error[E0308]: mismatched types
   --> $DIR/impl_trait_in_trait_defined_outside_trait.rs:31:30
@@ -30,11 +25,6 @@ LL |         let x: Self::Assoc = 42;
    |
    = note: expected opaque type `<() as Trait2>::Assoc`
                      found type `{integer}`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/impl_trait_in_trait_defined_outside_trait.rs:30:11
-   |
-LL |     const FOO: () = {
-   |           ^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.rs b/tests/ui/type-alias-impl-trait/implied_bounds.rs
index 269c0eff025..65d7234bd44 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds.rs
+++ b/tests/ui/type-alias-impl-trait/implied_bounds.rs
@@ -1,11 +1,8 @@
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    use super::Equals;
-    pub type WithLifetime<'a> = impl Equals<SelfType = ()>;
-    fn _defining_use<'a>() -> WithLifetime<'a> {}
-}
-use foo::WithLifetime;
+pub type WithLifetime<'a> = impl Equals<SelfType = ()>;
+#[define_opaque(WithLifetime)]
+fn _defining_use<'a>() -> WithLifetime<'a> {}
 
 trait Convert<'a> {
     type Witness;
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds.stderr b/tests/ui/type-alias-impl-trait/implied_bounds.stderr
index 23f1141e544..eda87bcbf90 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_bounds.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/implied_bounds.rs:21:9
+  --> $DIR/implied_bounds.rs:18:9
    |
 LL | impl<'a> Convert<'a> for () {
    |      -- lifetime `'a` defined here
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds2.rs b/tests/ui/type-alias-impl-trait/implied_bounds2.rs
index 845476ef974..0d829113ce7 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds2.rs
+++ b/tests/ui/type-alias-impl-trait/implied_bounds2.rs
@@ -2,12 +2,10 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod helper {
-    pub type Ty<'a, A> = impl Sized + 'a;
-    fn defining<'a, A>() -> Ty<'a, A> {}
-    pub fn assert_static<T: 'static>() {}
-}
-use helper::*;
+pub type Ty<'a, A> = impl Sized + 'a;
+#[define_opaque(Ty)]
+fn defining<'a, A>() -> Ty<'a, A> {}
+pub fn assert_static<T: 'static>() {}
 fn test<'a, A>()
 where
     Ty<'a, A>: 'static,
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
index 76a63741e18..b6120cd4cc3 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
+++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.rs
@@ -1,11 +1,8 @@
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    use super::Equals;
-    pub type WithLifetime<T> = impl Equals<SelfType = ()>;
-    fn _defining_use<T>() -> WithLifetime<T> {}
-}
-use foo::WithLifetime;
+pub type WithLifetime<T> = impl Equals<SelfType = ()>;
+#[define_opaque(WithLifetime)]
+fn _defining_use<T>() -> WithLifetime<T> {}
 
 trait Convert<'a> {
     type Witness;
diff --git a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
index 391a8a75786..887c8552d2f 100644
--- a/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_bounds_from_types.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/implied_bounds_from_types.rs:21:9
+  --> $DIR/implied_bounds_from_types.rs:18:9
    |
 LL | impl<'a> Convert<'a> for () {
    |      -- lifetime `'a` defined here
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr
index 49997b073c9..3bc6b9205ec 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.error.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Yay` for type `<() as HideIt>::Assoc`
-  --> $DIR/implied_lifetime_wf_check.rs:26:1
+  --> $DIR/implied_lifetime_wf_check.rs:27:1
    |
 LL | impl Yay for <() as HideIt>::Assoc {}
    | ---------------------------------- first implementation here
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs
index d85c7f60023..7950d6ad80c 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check.rs
@@ -7,6 +7,7 @@
 
 type Alias = impl Sized;
 
+#[define_opaque(Alias)]
 fn constrain() -> Alias {
     1i32
 }
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
index fb251e9bde1..889438d1b73 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.rs
@@ -2,6 +2,7 @@
 
 mod test_lifetime_param {
     pub type Ty<'a> = impl Sized;
+    #[define_opaque(Ty)]
     fn defining(a: &str) -> Ty<'_> {
         a
     }
@@ -17,6 +18,7 @@ where
 
 mod test_higher_kinded_lifetime_param {
     pub type Ty<'a> = impl Sized + 'a;
+    #[define_opaque(Ty)]
     fn defining(a: &str) -> Ty<'_> {
         a
     }
@@ -40,6 +42,7 @@ mod test_higher_kinded_lifetime_param2 {
 
 mod test_type_param {
     pub type Ty<A> = impl Sized;
+    #[define_opaque(Ty)]
     fn defining<A>(s: A) -> Ty<A> {
         s
     }
@@ -54,13 +57,13 @@ where
 }
 
 mod test_implied_from_fn_sig {
-    mod foo {
-        pub type Opaque<T: 'static> = impl Sized;
-        fn defining<T: 'static>() -> Opaque<T> {}
-    }
+    pub type Opaque<T: 'static> = impl Sized;
+    #[define_opaque(Opaque)]
+    fn defining<T: 'static>() -> Opaque<T> {}
+
     fn assert_static<T: 'static>() {}
 
-    fn test<T>(_: foo::Opaque<T>) {
+    fn test<T>(_: Opaque<T>) {
         assert_static::<T>();
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
index c9af4bda572..7311f5882f7 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check3.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:14:5
+  --> $DIR/implied_lifetime_wf_check3.rs:15:5
    |
 LL | fn test_lifetime_param_test<'a>()
    |                             -- lifetime `'a` defined here
@@ -8,7 +8,7 @@ LL |     test_lifetime_param::assert_static::<'a>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:29:5
+  --> $DIR/implied_lifetime_wf_check3.rs:31:5
    |
 LL | fn test_higher_kinded_lifetime_param_test<'a>()
    |                                           -- lifetime `'a` defined here
@@ -17,7 +17,7 @@ LL |     test_higher_kinded_lifetime_param::assert_static::<'a>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:36:9
+  --> $DIR/implied_lifetime_wf_check3.rs:38:9
    |
 LL |     fn test<'a>() {
    |             -- lifetime `'a` defined here
@@ -25,7 +25,7 @@ LL |         assert_static::<'a>()
    |         ^^^^^^^^^^^^^^^^^^^ requires that `'a` must outlive `'static`
 
 error[E0310]: the parameter type `A` may not live long enough
-  --> $DIR/implied_lifetime_wf_check3.rs:52:5
+  --> $DIR/implied_lifetime_wf_check3.rs:55:5
    |
 LL |     test_type_param::assert_static::<A>()
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
index 7b2bbc99530..5484b91e6f1 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.rs
@@ -1,14 +1,12 @@
 #![feature(type_alias_impl_trait)]
 
-mod test_type_param_static {
-    pub type Ty<A> = impl Sized + 'static;
-    fn defining<A: 'static>(s: A) -> Ty<A> {
-        s
-        //~^ ERROR: the parameter type `A` may not live long enough
-    }
-    pub fn assert_static<A: 'static>() {}
+pub type Ty<A> = impl Sized + 'static;
+#[define_opaque(Ty)]
+fn defining<A: 'static>(s: A) -> Ty<A> {
+    s
+    //~^ ERROR: the parameter type `A` may not live long enough
 }
-use test_type_param_static::*;
+pub fn assert_static<A: 'static>() {}
 
 fn test<A>()
 where
diff --git a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
index 060d68eb632..3cec4bbb099 100644
--- a/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
+++ b/tests/ui/type-alias-impl-trait/implied_lifetime_wf_check4_static.stderr
@@ -1,24 +1,24 @@
 error[E0310]: the parameter type `A` may not live long enough
-  --> $DIR/implied_lifetime_wf_check4_static.rs:6:9
+  --> $DIR/implied_lifetime_wf_check4_static.rs:6:5
    |
-LL |         s
-   |         ^
-   |         |
-   |         the parameter type `A` must be valid for the static lifetime...
-   |         ...so that the type `A` will meet its required lifetime bounds...
+LL |     s
+   |     ^
+   |     |
+   |     the parameter type `A` must be valid for the static lifetime...
+   |     ...so that the type `A` will meet its required lifetime bounds...
    |
 note: ...that is required by this bound
-  --> $DIR/implied_lifetime_wf_check4_static.rs:4:35
+  --> $DIR/implied_lifetime_wf_check4_static.rs:3:31
    |
-LL |     pub type Ty<A> = impl Sized + 'static;
-   |                                   ^^^^^^^
+LL | pub type Ty<A> = impl Sized + 'static;
+   |                               ^^^^^^^
 help: consider adding an explicit lifetime bound
    |
-LL |     pub type Ty<A: 'static> = impl Sized + 'static;
-   |                  +++++++++
+LL | pub type Ty<A: 'static> = impl Sized + 'static;
+   |              +++++++++
 
 error[E0310]: the parameter type `A` may not live long enough
-  --> $DIR/implied_lifetime_wf_check4_static.rs:17:5
+  --> $DIR/implied_lifetime_wf_check4_static.rs:15:5
    |
 LL |     assert_static::<A>()
    |     ^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs
index 4a9f162823e..126fb66b9db 100644
--- a/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs
+++ b/tests/ui/type-alias-impl-trait/imply_bounds_from_bounds.rs
@@ -2,19 +2,17 @@
 
 #![feature(impl_trait_in_assoc_type, type_alias_impl_trait)]
 
-mod foo {
-    pub trait Callable {
-        type Output;
-        fn call() -> Self::Output;
-    }
+pub trait Callable {
+    type Output;
+    fn call() -> Self::Output;
+}
 
-    pub type OutputHelper = impl Sized;
-    impl<'a> Callable for &'a () {
-        type Output = OutputHelper;
-        fn call() -> Self::Output {}
-    }
+pub type OutputHelper = impl Sized;
+impl<'a> Callable for &'a () {
+    type Output = OutputHelper;
+    #[define_opaque(OutputHelper)]
+    fn call() -> Self::Output {}
 }
-use foo::*;
 
 fn test<'a>() -> impl Sized {
     <&'a () as Callable>::call()
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.rs b/tests/ui/type-alias-impl-trait/in-where-clause.rs
index 065af57a864..8d5bfc48a66 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.rs
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.rs
@@ -5,6 +5,7 @@
 type Bar = impl Sized;
 //~^ ERROR: cycle
 
+#[define_opaque(Bar)]
 fn foo() -> Bar
 where
     Bar: Send,
diff --git a/tests/ui/type-alias-impl-trait/in-where-clause.stderr b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
index 5ac09e20b02..114cac64573 100644
--- a/tests/ui/type-alias-impl-trait/in-where-clause.stderr
+++ b/tests/ui/type-alias-impl-trait/in-where-clause.stderr
@@ -1,12 +1,12 @@
 error[E0283]: type annotations needed: cannot satisfy `Bar: Send`
-  --> $DIR/in-where-clause.rs:12:9
+  --> $DIR/in-where-clause.rs:13:9
    |
 LL |     [0; 1 + 2]
    |         ^^^^^
    |
    = note: cannot satisfy `Bar: Send`
 note: required by a bound in `foo`
-  --> $DIR/in-where-clause.rs:10:10
+  --> $DIR/in-where-clause.rs:11:10
    |
 LL | fn foo() -> Bar
    |    --- required by a bound in this function
@@ -21,7 +21,7 @@ LL | type Bar = impl Sized;
    |            ^^^^^^^^^^
    |
 note: ...which requires type-checking `foo`...
-  --> $DIR/in-where-clause.rs:8:1
+  --> $DIR/in-where-clause.rs:9:1
    |
 LL | / fn foo() -> Bar
 LL | | where
diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.rs b/tests/ui/type-alias-impl-trait/incomplete-inference.rs
index 4c8bf2cfca1..70acb1870e2 100644
--- a/tests/ui/type-alias-impl-trait/incomplete-inference.rs
+++ b/tests/ui/type-alias-impl-trait/incomplete-inference.rs
@@ -2,11 +2,13 @@
 
 type Foo = impl Sized;
 
+#[define_opaque(Foo)]
 fn bar() -> Foo {
     None
     //~^ ERROR: type annotations needed [E0282]
 }
 
+#[define_opaque(Foo)]
 fn baz() -> Foo {
     Some(())
 }
diff --git a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr
index 3976a43a89c..0b2bac0a153 100644
--- a/tests/ui/type-alias-impl-trait/incomplete-inference.stderr
+++ b/tests/ui/type-alias-impl-trait/incomplete-inference.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/incomplete-inference.rs:6:5
+  --> $DIR/incomplete-inference.rs:7:5
    |
 LL |     None
    |     ^^^^ cannot infer type of the type parameter `T` declared on the enum `Option`
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.rs b/tests/ui/type-alias-impl-trait/inference-cycle.rs
index 6e4507ed460..951f177377a 100644
--- a/tests/ui/type-alias-impl-trait/inference-cycle.rs
+++ b/tests/ui/type-alias-impl-trait/inference-cycle.rs
@@ -1,24 +1,24 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-mod m {
-    pub type Foo = impl std::fmt::Debug;
+//@ check-pass
 
-    pub fn foo() -> Foo {
-        is_send(bar())
-    }
+pub type Foo = impl std::fmt::Debug;
 
-    pub fn bar() {
-        // Cycle: error today, but it'd be nice if it eventually worked
-        is_send(foo());
-        //~^ ERROR: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
-    }
+#[define_opaque(Foo)]
+pub fn foo() -> Foo {
+    is_send(bar())
+}
 
-    fn baz() -> Foo {
-        ()
-    }
+pub fn bar() {
+    is_send(foo());
+}
 
-    fn is_send<T: Send>(_: T) {}
+#[define_opaque(Foo)]
+fn baz() -> Foo {
+    ()
 }
 
+fn is_send<T: Send>(_: T) {}
+
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/inference-cycle.stderr b/tests/ui/type-alias-impl-trait/inference-cycle.stderr
deleted file mode 100644
index 8b809ba014d..00000000000
--- a/tests/ui/type-alias-impl-trait/inference-cycle.stderr
+++ /dev/null
@@ -1,22 +0,0 @@
-error: cannot check whether the hidden type of `inference_cycle[4ecc]::m::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/inference-cycle.rs:13:17
-   |
-LL |         is_send(foo());
-   |         ------- ^^^^^
-   |         |
-   |         required by a bound introduced by this call
-   |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/inference-cycle.rs:5:20
-   |
-LL |     pub type Foo = impl std::fmt::Debug;
-   |                    ^^^^^^^^^^^^^^^^^^^^
-note: required by a bound in `is_send`
-  --> $DIR/inference-cycle.rs:21:19
-   |
-LL |     fn is_send<T: Send>(_: T) {}
-   |                   ^^^^ required by this bound in `is_send`
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
index 6609d4eb5a2..ef6871bec7c 100644
--- a/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
+++ b/tests/ui/type-alias-impl-trait/infinite-cycle-involving-weak.rs
@@ -3,6 +3,9 @@
 type T = impl Copy;
 //~^ ERROR cannot resolve opaque type
 
-static STATIC: T = None::<&'static T>;
+#[define_opaque(T)]
+fn foo() -> T {
+    None::<&'static T>
+}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs
index 93c52126d69..ae9712bd891 100644
--- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.rs
@@ -7,6 +7,7 @@ trait Foo {
 
 impl Foo for () {
     type Foo = impl std::fmt::Debug;
+    //~^ ERROR: unconstrained opaque type
     fn bar() {
         let x: Self::Foo = ();
         //~^ ERROR: mismatched types
diff --git a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
index 169d8e41d20..82bd0025d6d 100644
--- a/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
+++ b/tests/ui/type-alias-impl-trait/invalid_impl_trait_in_assoc_ty.stderr
@@ -1,9 +1,17 @@
+error: unconstrained opaque type
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:9:16
+   |
+LL |     type Foo = impl std::fmt::Debug;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:11:28
+  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:12:28
    |
 LL |     type Foo = impl std::fmt::Debug;
    |                -------------------- the expected opaque type
-LL |     fn bar() {
+...
 LL |         let x: Self::Foo = ();
    |                ---------   ^^ expected opaque type, found `()`
    |                |
@@ -11,12 +19,7 @@ LL |         let x: Self::Foo = ();
    |
    = note: expected opaque type `<() as Foo>::Foo`
                 found unit type `()`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/invalid_impl_trait_in_assoc_ty.rs:10:8
-   |
-LL |     fn bar() {
-   |        ^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/issue-101750.rs b/tests/ui/type-alias-impl-trait/issue-101750.rs
index 9367be8ca07..2f9304ce3bc 100644
--- a/tests/ui/type-alias-impl-trait/issue-101750.rs
+++ b/tests/ui/type-alias-impl-trait/issue-101750.rs
@@ -2,21 +2,18 @@
 
 //@ check-pass
 
-mod foo {
-    pub trait Trait {}
+pub trait Trait {}
 
-    pub type TAIT = impl Trait;
+pub type TAIT = impl Trait;
 
-    pub struct Concrete;
-    impl Trait for Concrete {}
+pub struct Concrete;
+impl Trait for Concrete {}
 
-    pub fn tait() -> TAIT {
-        Concrete
-    }
+#[define_opaque(TAIT)]
+pub fn tait() -> TAIT {
+    Concrete
 }
 
-use foo::*;
-
 trait OuterTrait {
     type Item;
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.rs b/tests/ui/type-alias-impl-trait/issue-104817.rs
index 49146321614..13bbfa12a67 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.rs
+++ b/tests/ui/type-alias-impl-trait/issue-104817.rs
@@ -8,6 +8,7 @@
 trait OpaqueTrait {}
 impl<T> OpaqueTrait for T {}
 type OpaqueType = impl OpaqueTrait;
+#[define_opaque(OpaqueType)]
 fn mk_opaque() -> OpaqueType {
     || 0
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
index df5a6c320a8..4f227310ee7 100644
--- a/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-104817.stock.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `AnotherTrait`
-  --> $DIR/issue-104817.rs:16:1
+  --> $DIR/issue-104817.rs:17:1
    |
 LL | impl<T: Send> AnotherTrait for T {}
    | -------------------------------- first implementation here
diff --git a/tests/ui/type-alias-impl-trait/issue-109054.rs b/tests/ui/type-alias-impl-trait/issue-109054.rs
index d3eb6521593..0c9304a42f3 100644
--- a/tests/ui/type-alias-impl-trait/issue-109054.rs
+++ b/tests/ui/type-alias-impl-trait/issue-109054.rs
@@ -10,8 +10,10 @@ type FnType = impl Fn(&u32) -> ReturnType;
 impl std::ops::Deref for CallMe {
     type Target = FnType;
 
+    #[define_opaque(FnType)]
     fn deref(&self) -> &Self::Target {
         //~^ ERROR: item does not constrain `ReturnType
+        #[define_opaque(ReturnType)]
         fn inner(val: &u32) -> ReturnType {
             async move { *val * 2 }
         }
diff --git a/tests/ui/type-alias-impl-trait/issue-109054.stderr b/tests/ui/type-alias-impl-trait/issue-109054.stderr
index 2a4aa63bb8c..919b0a287c4 100644
--- a/tests/ui/type-alias-impl-trait/issue-109054.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-109054.stderr
@@ -1,18 +1,18 @@
-error: item does not constrain `ReturnType::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-109054.rs:13:8
+error: item does not constrain `ReturnType::{opaque#0}`
+  --> $DIR/issue-109054.rs:14:8
    |
 LL |     fn deref(&self) -> &Self::Target {
    |        ^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/issue-109054.rs:7:23
    |
 LL | type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a;
    |                       ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/issue-109054.rs:19:9
+  --> $DIR/issue-109054.rs:21:9
    |
 LL | type ReturnType<'a> = impl std::future::Future<Output = u32> + 'a;
    |                 -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs
deleted file mode 100644
index 50eeff0b18f..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-// Checks to ensure that we properly detect when a closure constrains an opaque type
-
-#![feature(type_alias_impl_trait)]
-
-use std::fmt::Debug;
-
-fn main() {
-    type Opaque = impl Debug;
-    fn _unused() -> Opaque { String::new() }
-    let null = || -> Opaque { 0 };
-    //~^ ERROR: concrete type differs from previous defining opaque type use
-    println!("{:?}", null());
-}
diff --git a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr b/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
deleted file mode 100644
index 4570ce8e41d..00000000000
--- a/tests/ui/type-alias-impl-trait/issue-52843-closure-constrain.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error: concrete type differs from previous defining opaque type use
-  --> $DIR/issue-52843-closure-constrain.rs:10:31
-   |
-LL |     let null = || -> Opaque { 0 };
-   |                               ^ expected `String`, got `i32`
-   |
-note: previous use here
-  --> $DIR/issue-52843-closure-constrain.rs:9:30
-   |
-LL |     fn _unused() -> Opaque { String::new() }
-   |                              ^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/type-alias-impl-trait/issue-52843.rs b/tests/ui/type-alias-impl-trait/issue-52843.rs
index 159d3ccd27e..fd28eb8381d 100644
--- a/tests/ui/type-alias-impl-trait/issue-52843.rs
+++ b/tests/ui/type-alias-impl-trait/issue-52843.rs
@@ -3,6 +3,7 @@
 type Foo<T> = impl Default;
 
 #[allow(unused)]
+#[define_opaque(Foo)]
 fn foo<T: Default>(t: T) -> Foo<T> {
     t
     //~^ ERROR: the trait bound `T: Default` is not satisfied
diff --git a/tests/ui/type-alias-impl-trait/issue-52843.stderr b/tests/ui/type-alias-impl-trait/issue-52843.stderr
index 6673b03525d..ee2390d0945 100644
--- a/tests/ui/type-alias-impl-trait/issue-52843.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-52843.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `T: Default` is not satisfied
-  --> $DIR/issue-52843.rs:7:5
+  --> $DIR/issue-52843.rs:8:5
    |
 LL |     t
    |     ^ the trait `Default` is not implemented for `T`
@@ -10,7 +10,7 @@ note: required by a bound in an opaque type
 LL | type Foo<T> = impl Default;
    |                    ^^^^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/issue-52843.rs:6:1
+  --> $DIR/issue-52843.rs:7:1
    |
 LL | fn foo<T: Default>(t: T) -> Foo<T> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.rs b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
index 43df49adc42..5f44a9aa2df 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.rs
@@ -2,15 +2,14 @@
 #![allow(dead_code)]
 
 type Bug<T, U> = impl Fn(T) -> U + Copy;
-//~^ ERROR cycle detected
 
+#[define_opaque(Bug)]
+//~^ ERROR: only functions and methods can define opaque types
 const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-//~^ ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature
-//~| ERROR item does not constrain `Bug::{opaque#0}`, but has it in its signature
-//~| ERROR non-defining opaque type use in defining scope
 
+#[define_opaque(Bug)]
 fn make_bug<T, U: From<T>>() -> Bug<T, U> {
-    |x| x.into()
+    |x| x.into() //~ ERROR is not satisfied
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
index 678b0c84f78..5739662ff80 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092-2.stderr
@@ -1,68 +1,25 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/issue-53092-2.rs:7:18
+error: only functions and methods can define opaque types
+  --> $DIR/issue-53092-2.rs:6:1
    |
-LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-   |                  ^^^^^^^^^^^ argument `u8` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/issue-53092-2.rs:4:18
-   |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
+LL | #[define_opaque(Bug)]
+   | ^^^^^^^^^^^^^^^^^^^^^
 
-error[E0391]: cycle detected when computing type of `Bug::{opaque#0}`
-  --> $DIR/issue-53092-2.rs:4:18
-   |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-   |
-note: ...which requires computing type of opaque `Bug::{opaque#0}`...
-  --> $DIR/issue-53092-2.rs:4:18
-   |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-note: ...which requires type-checking `CONST_BUG`...
-  --> $DIR/issue-53092-2.rs:7:1
-   |
-LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: ...which requires computing layout of `Bug<u8, ()>`...
-   = note: ...which requires normalizing `Bug<u8, ()>`...
-   = note: ...which again requires computing type of `Bug::{opaque#0}`, completing the cycle
-note: cycle used when checking that `Bug::{opaque#0}` is well-formed
-  --> $DIR/issue-53092-2.rs:4:18
+error[E0277]: the trait bound `U: From<T>` is not satisfied
+  --> $DIR/issue-53092-2.rs:12:5
    |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-   = note: see https://rustc-dev-guide.rust-lang.org/overview.html#queries and https://rustc-dev-guide.rust-lang.org/query.html for more information
-
-error: item does not constrain `Bug::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-53092-2.rs:7:7
-   |
-LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-   |       ^^^^^^^^^
-   |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-53092-2.rs:4:18
-   |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
-
-error: item does not constrain `Bug::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-53092-2.rs:7:61
+LL |     |x| x.into()
+   |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
-LL | const CONST_BUG: Bug<u8, ()> = unsafe { std::mem::transmute(|_: u8| ()) };
-   |                                                             ^^^^^^^
+note: required by a bound in `make_bug`
+  --> $DIR/issue-53092-2.rs:11:19
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-53092-2.rs:4:18
+LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+   |                   ^^^^^^^ required by this bound in `make_bug`
+help: consider restricting type parameter `U` with trait `From`
    |
-LL | type Bug<T, U> = impl Fn(T) -> U + Copy;
-   |                  ^^^^^^^^^^^^^^^^^^^^^^
+LL | type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
+   |              +++++++++++++++++++++++
 
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
-Some errors have detailed explanations: E0391, E0792.
-For more information about an error, try `rustc --explain E0391`.
+For more information about this error, try `rustc --explain E0277`.
diff --git a/tests/ui/type-alias-impl-trait/issue-53092.rs b/tests/ui/type-alias-impl-trait/issue-53092.rs
index 83b51227aaa..a2e6ddc11b6 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53092.rs
@@ -1,14 +1,13 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-mod bug {
-    pub type Bug<T, U> = impl Fn(T) -> U + Copy;
+pub type Bug<T, U> = impl Fn(T) -> U + Copy;
 
-    fn make_bug<T, U: From<T>>() -> Bug<T, U> {
-        |x| x.into() //~ ERROR the trait bound `U: From<T>` is not satisfied
-    }
+#[define_opaque(Bug)]
+fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+    |x| x.into()
+    //~^ ERROR the trait bound `U: From<T>` is not satisfied
 }
-use bug::Bug;
 
 union Moo {
     x: Bug<u8, ()>,
diff --git a/tests/ui/type-alias-impl-trait/issue-53092.stderr b/tests/ui/type-alias-impl-trait/issue-53092.stderr
index 579902aa3ab..a8554b9a989 100644
--- a/tests/ui/type-alias-impl-trait/issue-53092.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53092.stderr
@@ -1,18 +1,18 @@
 error[E0277]: the trait bound `U: From<T>` is not satisfied
-  --> $DIR/issue-53092.rs:8:9
+  --> $DIR/issue-53092.rs:8:5
    |
-LL |         |x| x.into()
-   |         ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
+LL |     |x| x.into()
+   |     ^^^^^^^^^^^^ the trait `From<T>` is not implemented for `U`
    |
 note: required by a bound in `make_bug`
-  --> $DIR/issue-53092.rs:7:23
+  --> $DIR/issue-53092.rs:7:19
    |
-LL |     fn make_bug<T, U: From<T>>() -> Bug<T, U> {
-   |                       ^^^^^^^ required by this bound in `make_bug`
+LL | fn make_bug<T, U: From<T>>() -> Bug<T, U> {
+   |                   ^^^^^^^ required by this bound in `make_bug`
 help: consider restricting type parameter `U` with trait `From`
    |
-LL |     pub type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
-   |                      +++++++++++++++++++++++
+LL | pub type Bug<T, U: std::convert::From<T>> = impl Fn(T) -> U + Copy;
+   |                  +++++++++++++++++++++++
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.rs b/tests/ui/type-alias-impl-trait/issue-53096.rs
index 590fce84fc9..c24f1bf44fa 100644
--- a/tests/ui/type-alias-impl-trait/issue-53096.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53096.rs
@@ -1,13 +1,11 @@
 #![feature(rustc_attrs)]
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub type Foo = impl Fn() -> usize;
-    pub const fn bar() -> Foo {
-        || 0usize
-    }
+pub type Foo = impl Fn() -> usize;
+#[define_opaque(Foo)]
+pub const fn bar() -> Foo {
+    || 0usize
 }
-use foo::*;
 const BAZR: Foo = bar();
 
 #[rustc_error]
diff --git a/tests/ui/type-alias-impl-trait/issue-53096.stderr b/tests/ui/type-alias-impl-trait/issue-53096.stderr
index 0a744e7be9c..53490896af7 100644
--- a/tests/ui/type-alias-impl-trait/issue-53096.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-53096.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-53096.rs:14:1
+  --> $DIR/issue-53096.rs:12:1
    |
 LL | fn main() {}
    | ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
index 0d9126d3993..f02ccbbb93c 100644
--- a/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
+++ b/tests/ui/type-alias-impl-trait/issue-53678-coroutine-and-const-fn.rs
@@ -3,21 +3,20 @@
 
 //@ check-pass
 
-mod gen {
-    use std::ops::Coroutine;
+use std::ops::Coroutine;
 
-    pub type CoroOnce<Y, R> = impl Coroutine<Yield = Y, Return = R>;
+pub type CoroOnce<Y, R> = impl Coroutine<Yield = Y, Return = R>;
 
-    pub const fn const_coroutine<Y, R>(yielding: Y, returning: R) -> CoroOnce<Y, R> {
-        #[coroutine]
-        move || {
-            yield yielding;
+#[define_opaque(CoroOnce)]
+pub const fn const_coroutine<Y, R>(yielding: Y, returning: R) -> CoroOnce<Y, R> {
+    #[coroutine]
+    move || {
+        yield yielding;
 
-            return returning;
-        }
+        return returning;
     }
 }
 
-const FOO: gen::CoroOnce<usize, usize> = gen::const_coroutine(10, 100);
+const FOO: CoroOnce<usize, usize> = const_coroutine(10, 100);
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
index e54dd01122e..a3c37759ac0 100644
--- a/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
+++ b/tests/ui/type-alias-impl-trait/issue-55099-lifetime-inference.rs
@@ -18,6 +18,7 @@ struct Foo<'a> {
 type F = impl Future;
 
 impl<'a> Foo<'a> {
+    #[define_opaque(F)]
     fn reply(&mut self) -> F {
         AndThen(|| ())
     }
diff --git a/tests/ui/type-alias-impl-trait/issue-57961.rs b/tests/ui/type-alias-impl-trait/issue-57961.rs
index 61af7a0f625..0b39e21d8b7 100644
--- a/tests/ui/type-alias-impl-trait/issue-57961.rs
+++ b/tests/ui/type-alias-impl-trait/issue-57961.rs
@@ -11,6 +11,7 @@ impl Foo for () {
     //~^ ERROR expected `IntoIter<u32>` to be an iterator that yields `X`, but it yields `u32`
 }
 
+#[define_opaque(X)]
 fn incoherent() -> X {
     22_i32
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
index 899e81ed562..c2a9f153815 100644
--- a/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58662-coroutine-with-lifetime.rs
@@ -7,6 +7,7 @@ use std::ops::{Coroutine, CoroutineState};
 use std::pin::Pin;
 
 type RandCoroutine<'a> = impl Coroutine<Return = (), Yield = u64> + 'a;
+#[define_opaque(RandCoroutine)]
 fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> {
     #[coroutine]
     move || {
@@ -18,6 +19,7 @@ fn rand_coroutine<'a>(rng: &'a ()) -> RandCoroutine<'a> {
 }
 
 pub type RandCoroutineWithIndirection<'c> = impl Coroutine<Return = (), Yield = u64> + 'c;
+#[define_opaque(RandCoroutineWithIndirection)]
 pub fn rand_coroutine_with_indirection<'a>(rng: &'a ()) -> RandCoroutineWithIndirection<'a> {
     fn helper<'b>(rng: &'b ()) -> impl 'b + Coroutine<Return = (), Yield = u64> {
         #[coroutine]
diff --git a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
index 9d74c0687fe..aef13947f55 100644
--- a/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58662-simplified.rs
@@ -8,6 +8,8 @@ trait Trait {}
 impl<T> Trait for T {}
 
 type Foo<'c> = impl Trait + 'c;
+
+#[define_opaque(Foo)]
 fn foo<'a>(rng: &'a ()) -> Foo<'a> {
     fn helper<'b>(rng: &'b ()) -> impl 'b + Trait {
         rng
@@ -16,5 +18,4 @@ fn foo<'a>(rng: &'a ()) -> Foo<'a> {
     helper(rng)
 }
 
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-58951-2.rs b/tests/ui/type-alias-impl-trait/issue-58951-2.rs
index fb92b127436..de6b9e74119 100644
--- a/tests/ui/type-alias-impl-trait/issue-58951-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58951-2.rs
@@ -2,14 +2,12 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod defining_use_scope {
-    pub type A = impl Iterator;
+pub type A = impl Iterator;
 
-    pub fn def_a() -> A {
-        0..1
-    }
+#[define_opaque(A)]
+pub fn def_a() -> A {
+    0..1
 }
-use defining_use_scope::*;
 
 pub fn use_a() {
     def_a().map(|x| x);
diff --git a/tests/ui/type-alias-impl-trait/issue-58951.rs b/tests/ui/type-alias-impl-trait/issue-58951.rs
index b9f27b031c7..de6b9e74119 100644
--- a/tests/ui/type-alias-impl-trait/issue-58951.rs
+++ b/tests/ui/type-alias-impl-trait/issue-58951.rs
@@ -2,16 +2,15 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod helper {
-    pub type A = impl Iterator;
+pub type A = impl Iterator;
 
-    pub fn def_a() -> A {
-        0..1
-    }
+#[define_opaque(A)]
+pub fn def_a() -> A {
+    0..1
 }
 
 pub fn use_a() {
-    helper::def_a().map(|x| x);
+    def_a().map(|x| x);
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.rs b/tests/ui/type-alias-impl-trait/issue-60407.rs
index 6c7c76b5ac7..5b8ff6b74de 100644
--- a/tests/ui/type-alias-impl-trait/issue-60407.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60407.rs
@@ -1,13 +1,11 @@
 #![feature(type_alias_impl_trait, rustc_attrs)]
 
-mod bar {
-    pub type Debuggable = impl core::fmt::Debug;
+pub type Debuggable = impl core::fmt::Debug;
 
-    pub fn foo() -> Debuggable {
-        0u32
-    }
+#[define_opaque(Debuggable)]
+pub fn foo() -> Debuggable {
+    0u32
 }
-use bar::*;
 
 static mut TEST: Option<Debuggable> = None;
 
diff --git a/tests/ui/type-alias-impl-trait/issue-60407.stderr b/tests/ui/type-alias-impl-trait/issue-60407.stderr
index bba9092e977..f517d5b65fa 100644
--- a/tests/ui/type-alias-impl-trait/issue-60407.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-60407.stderr
@@ -1,5 +1,5 @@
 error: fatal error triggered by #[rustc_error]
-  --> $DIR/issue-60407.rs:15:1
+  --> $DIR/issue-60407.rs:13:1
    |
 LL | fn main() {
    | ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.rs b/tests/ui/type-alias-impl-trait/issue-60564.rs
index 48bd70bcca9..f28258b3b22 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.rs
+++ b/tests/ui/type-alias-impl-trait/issue-60564.rs
@@ -16,8 +16,8 @@ where
     E: std::fmt::Debug,
 {
     type BitsIter = IterBitsIter<T, E, u8>;
+    #[define_opaque(IterBitsIter)]
     fn iter_bits(self, n: u8) -> Self::BitsIter {
-        //~^ ERROR non-defining opaque type use
         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
         //~^ ERROR expected generic type parameter, found `u8`
     }
diff --git a/tests/ui/type-alias-impl-trait/issue-60564.stderr b/tests/ui/type-alias-impl-trait/issue-60564.stderr
index d42495e934d..6aaed7d4296 100644
--- a/tests/ui/type-alias-impl-trait/issue-60564.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-60564.stderr
@@ -1,15 +1,3 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/issue-60564.rs:19:34
-   |
-LL |     fn iter_bits(self, n: u8) -> Self::BitsIter {
-   |                                  ^^^^^^^^^^^^^^ argument `u8` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/issue-60564.rs:8:30
-   |
-LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
-   |                              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `u8`
   --> $DIR/issue-60564.rs:21:9
    |
@@ -19,6 +7,6 @@ LL | type IterBitsIter<T, E, I> = impl std::iter::Iterator<Item = I>;
 LL |         (0u8..n).rev().map(move |shift| ((self >> T::from(shift)) & T::from(1)).try_into().unwrap())
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
index 38abc3ec7e8..6de026a26d5 100644
--- a/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63263-closure-return.rs
@@ -8,6 +8,7 @@
 
 pub type Closure = impl FnOnce();
 
+#[define_opaque(Closure)]
 fn bop() -> Closure {
     || -> Closure { || () };
     panic!()
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.rs b/tests/ui/type-alias-impl-trait/issue-63279.rs
index 02f2111468a..10da40d2f90 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63279.rs
@@ -2,6 +2,7 @@
 
 type Closure = impl FnOnce();
 
+#[define_opaque(Closure)]
 fn c() -> Closure {
     //~^ ERROR: expected a `FnOnce()` closure, found `()`
     || -> Closure { || () }
diff --git a/tests/ui/type-alias-impl-trait/issue-63279.stderr b/tests/ui/type-alias-impl-trait/issue-63279.stderr
index 97158ee297d..8f0e9c5fde0 100644
--- a/tests/ui/type-alias-impl-trait/issue-63279.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-63279.stderr
@@ -1,5 +1,5 @@
 error[E0277]: expected a `FnOnce()` closure, found `()`
-  --> $DIR/issue-63279.rs:5:11
+  --> $DIR/issue-63279.rs:6:11
    |
 LL | fn c() -> Closure {
    |           ^^^^^^^ expected an `FnOnce()` closure, found `()`
@@ -8,7 +8,7 @@ LL | fn c() -> Closure {
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0277]: expected a `FnOnce()` closure, found `()`
-  --> $DIR/issue-63279.rs:7:11
+  --> $DIR/issue-63279.rs:8:11
    |
 LL |     || -> Closure { || () }
    |           ^^^^^^^ expected an `FnOnce()` closure, found `()`
@@ -17,26 +17,26 @@ LL |     || -> Closure { || () }
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0308]: mismatched types
-  --> $DIR/issue-63279.rs:7:21
+  --> $DIR/issue-63279.rs:8:21
    |
 LL |     || -> Closure { || () }
    |                     ^^^^^ expected `()`, found closure
    |
    = note: expected unit type `()`
-                found closure `{closure@$DIR/issue-63279.rs:7:21: 7:23}`
+                found closure `{closure@$DIR/issue-63279.rs:8:21: 8:23}`
 help: use parentheses to call this closure
    |
 LL |     || -> Closure { (|| ())() }
    |                     +     +++
 
 error[E0308]: mismatched types
-  --> $DIR/issue-63279.rs:7:5
+  --> $DIR/issue-63279.rs:8:5
    |
 LL |     || -> Closure { || () }
    |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found closure
    |
    = note: expected unit type `()`
-                found closure `{closure@$DIR/issue-63279.rs:7:5: 7:18}`
+                found closure `{closure@$DIR/issue-63279.rs:8:5: 8:18}`
 help: use parentheses to call this closure
    |
 LL |     (|| -> Closure { || () })()
diff --git a/tests/ui/type-alias-impl-trait/issue-63355.rs b/tests/ui/type-alias-impl-trait/issue-63355.rs
index a0d0355b5af..0b29bfeb98f 100644
--- a/tests/ui/type-alias-impl-trait/issue-63355.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63355.rs
@@ -21,6 +21,7 @@ impl Foo for () {}
 impl Bar for () {
     type Foo = FooImpl;
 
+    #[define_opaque(FooImpl)]
     fn foo() -> Self::Foo {
         ()
     }
@@ -33,10 +34,12 @@ impl Baz for () {
     type Foo = FooImpl;
     type Bar = BarImpl;
 
+    #[define_opaque(FooImpl)]
     fn foo() -> Self::Foo {
         ()
     }
 
+    #[define_opaque(BarImpl)]
     fn bar() -> Self::Bar {
         //~^ ERROR: item does not constrain `FooImpl::{opaque#0}`
         ()
diff --git a/tests/ui/type-alias-impl-trait/issue-63355.stderr b/tests/ui/type-alias-impl-trait/issue-63355.stderr
index 6755c038056..cb1ef0ce41d 100644
--- a/tests/ui/type-alias-impl-trait/issue-63355.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-63355.stderr
@@ -1,12 +1,12 @@
-error: item does not constrain `FooImpl::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-63355.rs:40:8
+error: item does not constrain `FooImpl::{opaque#0}`
+  --> $DIR/issue-63355.rs:43:8
    |
 LL |     fn bar() -> Self::Bar {
    |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/issue-63355.rs:29:20
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/issue-63355.rs:30:20
    |
 LL | pub type FooImpl = impl Foo;
    |                    ^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs
index 51f95637969..5ea73965701 100644
--- a/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs
+++ b/tests/ui/type-alias-impl-trait/issue-63677-type-alias-coherence.rs
@@ -16,6 +16,9 @@ impl<T> Trait for S1<T> {}
 impl<T: Trait> S2<T> {}
 impl T3 {}
 
-pub fn use_t1() -> T1 { S1(()) }
+#[define_opaque(T1)]
+pub fn use_t1() -> T1 {
+    S1(())
+}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-65384.rs b/tests/ui/type-alias-impl-trait/issue-65384.rs
index 44ca5cb94b0..86bbc93c8bd 100644
--- a/tests/ui/type-alias-impl-trait/issue-65384.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65384.rs
@@ -9,6 +9,7 @@ type Bar = impl MyTrait;
 impl MyTrait for Bar {}
 //~^ ERROR: conflicting implementations of trait `MyTrait` for type `()`
 
-fn bazr() -> Bar { }
+#[define_opaque(Bar)]
+fn bazr() -> Bar {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
index f98ce4a426c..6fc3aa8ce7e 100644
--- a/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65679-inst-opaque-ty-from-val-twice.rs
@@ -1,20 +1,19 @@
 //@ check-pass
 
 #![feature(type_alias_impl_trait, rustc_attrs)]
-mod foo {
-    pub type T = impl Sized;
-    // The concrete type referred by impl-trait-type-alias(`T`) is guaranteed
-    // to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive;
-    // so difference assertion should not be declared on impl-trait-type-alias's instances.
-    // for details, check RFC-2515:
-    // https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md
 
-    fn bop(_: T) {
-        super::take(|| {});
-        super::take(|| {});
-    }
+pub type T = impl Sized;
+// The concrete type referred by impl-trait-type-alias(`T`) is guaranteed
+// to be the same as where it occurs, whereas `impl Trait`'s instance is location sensitive;
+// so difference assertion should not be declared on impl-trait-type-alias's instances.
+// for details, check RFC-2515:
+// https://github.com/rust-lang/rfcs/blob/master/text/2515-type_alias_impl_trait.md
+
+#[define_opaque(T)]
+fn bop() {
+    take(|| {});
+    take(|| {});
 }
-use foo::*;
 
 fn take(_: fn() -> T) {}
 
diff --git a/tests/ui/type-alias-impl-trait/issue-65918.rs b/tests/ui/type-alias-impl-trait/issue-65918.rs
index 275b9717cef..00dab6f2744 100644
--- a/tests/ui/type-alias-impl-trait/issue-65918.rs
+++ b/tests/ui/type-alias-impl-trait/issue-65918.rs
@@ -15,13 +15,11 @@ trait MyFrom<T>: Sized {
 }
 
 /* MCVE starts here */
-mod f {
-    pub trait F {}
-    impl F for () {}
-    pub type DummyT<T> = impl F;
-    fn _dummy_t<T>() -> DummyT<T> {}
-}
-use f::DummyT;
+pub trait F {}
+impl F for () {}
+pub type DummyT<T> = impl F;
+#[define_opaque(DummyT)]
+fn _dummy_t<T>() -> DummyT<T> {}
 
 struct Phantom1<T>(PhantomData<T>);
 struct Phantom2<T>(PhantomData<T>);
diff --git a/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs
index 0e3d01c2d61..009dc31ba26 100644
--- a/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs
+++ b/tests/ui/type-alias-impl-trait/issue-66580-closure-coherence.rs
@@ -6,6 +6,7 @@
 
 type Closure = impl FnOnce();
 
+#[define_opaque(Closure)]
 fn closure() -> Closure {
     || {}
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
index c320b0db31b..2d38b3030be 100644
--- a/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
+++ b/tests/ui/type-alias-impl-trait/issue-67844-nested-opaque.rs
@@ -22,6 +22,7 @@ impl WithAssoc for MyStruct {
     type AssocType = MyParam;
 }
 
+#[define_opaque(Return)]
 fn my_fun<A>() -> Return<A> {
     MyStruct
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
index 9dcdb578568..205d4832b0a 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.rs
@@ -6,9 +6,9 @@
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
 
+#[define_opaque(Alias)]
 fn f<'a>() -> Alias<'a, ()> {}
-//~^ ERROR non-defining opaque type use
-//~| ERROR expected generic type parameter, found `()`
+//~^ ERROR expected generic type parameter, found `()`
 
 fn main() {}
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
index 085bffe907b..178aa5cf345 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use-2.stderr
@@ -1,24 +1,12 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use-2.rs:9:15
-   |
-LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^ argument `()` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/issue-68368-non-defining-use-2.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `()`
-  --> $DIR/issue-68368-non-defining-use-2.rs:9:29
+  --> $DIR/issue-68368-non-defining-use-2.rs:10:29
    |
 LL | type Alias<'a, U> = impl Trait<U>;
    |                - this generic parameter must be used with a generic type parameter
-LL |
+...
 LL | fn f<'a>() -> Alias<'a, ()> {}
    |                             ^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
index dfe2ee8204c..f3fa4fea746 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.rs
@@ -6,9 +6,9 @@
 trait Trait<T> {}
 type Alias<'a, U> = impl Trait<U>;
 
+#[define_opaque(Alias)]
 fn f<'a>() -> Alias<'a, ()> {}
 //~^ ERROR expected generic type parameter, found `()`
-//~| ERROR non-defining opaque type use
 
 fn main() {}
 
diff --git a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
index ea704ffff97..bfbd506a7a5 100644
--- a/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-68368-non-defining-use.stderr
@@ -1,24 +1,12 @@
-error[E0792]: non-defining opaque type use in defining scope
-  --> $DIR/issue-68368-non-defining-use.rs:9:15
-   |
-LL | fn f<'a>() -> Alias<'a, ()> {}
-   |               ^^^^^^^^^^^^^ argument `()` is not a generic parameter
-   |
-note: for this opaque type
-  --> $DIR/issue-68368-non-defining-use.rs:7:21
-   |
-LL | type Alias<'a, U> = impl Trait<U>;
-   |                     ^^^^^^^^^^^^^
-
 error[E0792]: expected generic type parameter, found `()`
-  --> $DIR/issue-68368-non-defining-use.rs:9:29
+  --> $DIR/issue-68368-non-defining-use.rs:10:29
    |
 LL | type Alias<'a, U> = impl Trait<U>;
    |                - this generic parameter must be used with a generic type parameter
-LL |
+...
 LL | fn f<'a>() -> Alias<'a, ()> {}
    |                             ^^
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0792`.
diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
index a0f8e48e268..f9a68a1b0b3 100644
--- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
+++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-error.rs
@@ -19,6 +19,7 @@ impl<T> WithAssoc<T> for () {
 type Return<A> = impl WithAssoc<A, AssocType = impl SomeTrait + 'a>;
 //~^ ERROR use of undeclared lifetime name `'a`
 
+#[define_opaque(Return)]
 fn my_fun<T>() -> Return<T> {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
index 8e631fd1b6a..f62260bd3f0 100644
--- a/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
+++ b/tests/ui/type-alias-impl-trait/issue-69136-inner-lifetime-resolve-ok.rs
@@ -18,6 +18,7 @@ impl WithAssoc for () {
 
 type Return<'a> = impl WithAssoc<AssocType = impl Sized + 'a>;
 
+#[define_opaque(Return)]
 fn my_fun<'a>() -> Return<'a> {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/issue-69323.rs b/tests/ui/type-alias-impl-trait/issue-69323.rs
index 18bc4cf9178..af536186f72 100644
--- a/tests/ui/type-alias-impl-trait/issue-69323.rs
+++ b/tests/ui/type-alias-impl-trait/issue-69323.rs
@@ -9,6 +9,7 @@ fn test1<A: Iterator<Item = &'static str>>(x: A) -> Chain<A, impl Iterator<Item
 }
 
 type I<A> = Chain<A, impl Iterator<Item = &'static str>>;
+#[define_opaque(I)]
 fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> {
     x.chain(once(","))
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.rs b/tests/ui/type-alias-impl-trait/issue-70121.rs
index b90bd312a0b..5aec99a1c37 100644
--- a/tests/ui/type-alias-impl-trait/issue-70121.rs
+++ b/tests/ui/type-alias-impl-trait/issue-70121.rs
@@ -2,6 +2,7 @@
 
 pub type Successors<'a> = impl Iterator<Item = &'a ()>;
 
+#[define_opaque(Successors)]
 pub fn f<'a>() -> Successors<'a> {
     None.into_iter()
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-70121.stderr b/tests/ui/type-alias-impl-trait/issue-70121.stderr
index ed2eb17fbea..8388998956f 100644
--- a/tests/ui/type-alias-impl-trait/issue-70121.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-70121.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-70121.rs:18:5
+  --> $DIR/issue-70121.rs:19:5
    |
 LL | pub type Successors<'a> = impl Iterator<Item = &'a ()>;
    |                           ---------------------------- the expected opaque type
@@ -11,8 +11,8 @@ LL |     None.into_iter()
    |
    = note: expected opaque type `Successors<'a>`
                    found struct `std::option::IntoIter<_>`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-70121.rs:17:8
+note: this item must have a `#[define_opaque(Successors)]` attribute to be able to define hidden types
+  --> $DIR/issue-70121.rs:18:8
    |
 LL | pub fn kazusa<'a>() -> <&'a () as Tr>::Item {
    |        ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/issue-72793.rs b/tests/ui/type-alias-impl-trait/issue-72793.rs
index 0353b7f3787..a51d7f5634a 100644
--- a/tests/ui/type-alias-impl-trait/issue-72793.rs
+++ b/tests/ui/type-alias-impl-trait/issue-72793.rs
@@ -3,24 +3,21 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub trait T {
-        type Item;
-    }
-
-    pub type Alias<'a> = impl T<Item = &'a ()>;
+pub trait T {
+    type Item;
+}
 
-    struct S;
-    impl<'a> T for &'a S {
-        type Item = &'a ();
-    }
+pub type Alias<'a> = impl T<Item = &'a ()>;
 
-    pub fn filter_positive<'a>() -> Alias<'a> {
-        &S
-    }
+struct S;
+impl<'a> T for &'a S {
+    type Item = &'a ();
 }
 
-use foo::*;
+#[define_opaque(Alias)]
+pub fn filter_positive<'a>() -> Alias<'a> {
+    &S
+}
 
 fn with_positive(fun: impl Fn(Alias<'_>)) {
     fun(filter_positive());
diff --git a/tests/ui/type-alias-impl-trait/issue-74244.rs b/tests/ui/type-alias-impl-trait/issue-74244.rs
index bb4104b3d25..60b1bee9ff6 100644
--- a/tests/ui/type-alias-impl-trait/issue-74244.rs
+++ b/tests/ui/type-alias-impl-trait/issue-74244.rs
@@ -13,6 +13,7 @@ impl<T> Allocator for DefaultAllocator {
 
 type A = impl Fn(<DefaultAllocator as Allocator>::Buffer);
 
+#[define_opaque(A)]
 fn foo() -> A {
     |_| ()
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-74280.rs b/tests/ui/type-alias-impl-trait/issue-74280.rs
index ad641eaa00d..c8dc1adec41 100644
--- a/tests/ui/type-alias-impl-trait/issue-74280.rs
+++ b/tests/ui/type-alias-impl-trait/issue-74280.rs
@@ -4,6 +4,7 @@
 
 type Test = impl Copy;
 
+#[define_opaque(Test)]
 fn test() -> Test {
     let y = || -> Test { () };
     7 //~ ERROR mismatched types
diff --git a/tests/ui/type-alias-impl-trait/issue-74280.stderr b/tests/ui/type-alias-impl-trait/issue-74280.stderr
index c09efbe4e13..a89a3f77b3d 100644
--- a/tests/ui/type-alias-impl-trait/issue-74280.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-74280.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/issue-74280.rs:9:5
+  --> $DIR/issue-74280.rs:10:5
    |
 LL | fn test() -> Test {
    |              ---- expected `()` because of return type
diff --git a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
index 90ab4fd8d97..3e17126834c 100644
--- a/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
+++ b/tests/ui/type-alias-impl-trait/issue-76202-trait-impl-for-tait.rs
@@ -7,19 +7,17 @@
 //@ check-pass
 #![feature(type_alias_impl_trait)]
 
-mod g {
-    pub trait Dummy {}
-    impl Dummy for () {}
-    pub type F = impl Dummy;
-    pub fn f() -> F {}
-}
-use g::*;
+pub trait Dummy {}
+impl Dummy for () {}
+pub type F = impl Dummy;
+#[define_opaque(F)]
+pub fn f() -> F {}
 
 trait Test {
     fn test(self);
 }
 
-impl Test for define::F {
+impl Test for F {
     fn test(self) {}
 }
 
@@ -29,17 +27,14 @@ impl Test for i32 {
     fn test(self) {}
 }
 
-mod define {
-    use super::*;
-
-    pub trait Dummy {}
-    impl Dummy for () {}
+pub trait Dummy2 {}
+impl Dummy2 for () {}
 
-    pub type F = impl Dummy;
-    pub fn f() -> F {}
-}
+pub type F2 = impl Dummy2;
+#[define_opaque(F2)]
+pub fn f2() -> F2 {}
 
 fn main() {
-    let x = define::f();
+    let x = f();
     x.test();
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.rs b/tests/ui/type-alias-impl-trait/issue-77179.rs
index 1dc74c6b5fe..18afc54dbdc 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.rs
+++ b/tests/ui/type-alias-impl-trait/issue-77179.rs
@@ -4,10 +4,11 @@
 
 type Pointer<T> = impl std::ops::Deref<Target = T>;
 
+#[define_opaque(Pointer)]
 fn test() -> Pointer<_> {
     //~^ ERROR: the placeholder `_` is not allowed within types
     Box::new(1)
-    //~^ ERROR: mismatched types
+    //~^ ERROR: expected generic type parameter, found `i32`
 }
 
 fn main() {
diff --git a/tests/ui/type-alias-impl-trait/issue-77179.stderr b/tests/ui/type-alias-impl-trait/issue-77179.stderr
index 16bbc996d90..bc11283f328 100644
--- a/tests/ui/type-alias-impl-trait/issue-77179.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-77179.stderr
@@ -1,36 +1,28 @@
-error[E0308]: mismatched types
-  --> $DIR/issue-77179.rs:9:5
-   |
-LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
-   |                   -------------------------------- the expected opaque type
-LL |
-LL | fn test() -> Pointer<_> {
-   |              ---------- expected `Pointer<_>` because of return type
-LL |
-LL |     Box::new(1)
-   |     ^^^^^^^^^^^ expected opaque type, found `Box<{integer}>`
-   |
-   = note: expected opaque type `Pointer<_>`
-                   found struct `Box<{integer}>`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/issue-77179.rs:7:4
-   |
-LL | fn test() -> Pointer<_> {
-   |    ^^^^
-
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/issue-77179.rs:7:22
+  --> $DIR/issue-77179.rs:8:22
    |
 LL | fn test() -> Pointer<_> {
-   |                      ^ not allowed in type signatures
+   |              --------^-
+   |              |       |
+   |              |       not allowed in type signatures
+   |              help: replace with the correct return type: `Pointer<i32>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
-  --> $DIR/issue-77179.rs:18:25
+  --> $DIR/issue-77179.rs:19:25
    |
 LL |     fn bar() -> Pointer<_>;
    |                         ^ not allowed in type signatures
 
+error[E0792]: expected generic type parameter, found `i32`
+  --> $DIR/issue-77179.rs:10:5
+   |
+LL | type Pointer<T> = impl std::ops::Deref<Target = T>;
+   |              - this generic parameter must be used with a generic type parameter
+...
+LL |     Box::new(1)
+   |     ^^^^^^^^^^^
+
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0121, E0308.
+Some errors have detailed explanations: E0121, E0792.
 For more information about an error, try `rustc --explain E0121`.
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
index 2a39da1176c..99ad48c8c32 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-trait-impl-for-tait.rs
@@ -8,6 +8,7 @@
 trait Foo {}
 impl Foo for () {}
 type Bar = impl Foo;
+#[define_opaque(Bar)]
 fn _defining_use() -> Bar {}
 
 trait TraitArg<T> {
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr
index ec7b9e0e12b..577d8667a57 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.current.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
-  --> $DIR/issue-84660-unsoundness.rs:29:1
+  --> $DIR/issue-84660-unsoundness.rs:31:1
    |
 LL | impl<In, Out> Trait<Bar, In> for Out {
    | ------------------------------------ first implementation here
@@ -7,14 +7,14 @@ LL | impl<In, Out> Trait<Bar, In> for Out {
 LL | impl<In, Out> Trait<(), In> for Out {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
-error: item does not constrain `Bar::{opaque#0}`, but has it in its signature
-  --> $DIR/issue-84660-unsoundness.rs:22:8
+error: item does not constrain `Bar::{opaque#0}`
+  --> $DIR/issue-84660-unsoundness.rs:24:8
    |
 LL |     fn convert(_i: In) -> Self::Out {
    |        ^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/issue-84660-unsoundness.rs:12:12
    |
 LL | type Bar = impl Foo;
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
index e33102f687c..9e83de5375f 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.next.stderr
@@ -1,5 +1,5 @@
 error[E0119]: conflicting implementations of trait `Trait<Bar, _>`
-  --> $DIR/issue-84660-unsoundness.rs:29:1
+  --> $DIR/issue-84660-unsoundness.rs:31:1
    |
 LL | impl<In, Out> Trait<Bar, In> for Out {
    | ------------------------------------ first implementation here
@@ -8,7 +8,7 @@ LL | impl<In, Out> Trait<(), In> for Out {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ conflicting implementation
 
 error[E0284]: type annotations needed: cannot satisfy `Bar == _`
-  --> $DIR/issue-84660-unsoundness.rs:22:37
+  --> $DIR/issue-84660-unsoundness.rs:24:37
    |
 LL |       fn convert(_i: In) -> Self::Out {
    |  _____________________________________^
diff --git a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
index f3234bafd11..4391bf01dc9 100644
--- a/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
+++ b/tests/ui/type-alias-impl-trait/issue-84660-unsoundness.rs
@@ -10,6 +10,7 @@
 trait Foo {}
 impl Foo for () {}
 type Bar = impl Foo;
+#[define_opaque(Bar)]
 fn _defining_use() -> Bar {}
 
 trait Trait<T, In> {
@@ -19,9 +20,10 @@ trait Trait<T, In> {
 
 impl<In, Out> Trait<Bar, In> for Out {
     type Out = Out;
+    #[define_opaque(Bar)]
     fn convert(_i: In) -> Self::Out {
         //[next]~^  ERROR: cannot satisfy `Bar == _`
-        //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`, but has it in its signature
+        //[current]~^^ ERROR: item does not constrain `Bar::{opaque#0}`
         unreachable!();
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-89686.rs b/tests/ui/type-alias-impl-trait/issue-89686.rs
index f734c518dd2..5370b8844ff 100644
--- a/tests/ui/type-alias-impl-trait/issue-89686.rs
+++ b/tests/ui/type-alias-impl-trait/issue-89686.rs
@@ -11,6 +11,7 @@ trait Trait {
 
     fn f(&self) -> Self::F;
 
+    #[define_opaque(G)]
     fn g<'a>(&'a self) -> G<'a, Self>
     where
         Self: Sized,
diff --git a/tests/ui/type-alias-impl-trait/issue-89686.stderr b/tests/ui/type-alias-impl-trait/issue-89686.stderr
index 6fa7e197c40..7ad1442f666 100644
--- a/tests/ui/type-alias-impl-trait/issue-89686.stderr
+++ b/tests/ui/type-alias-impl-trait/issue-89686.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/issue-89686.rs:18:9
+  --> $DIR/issue-89686.rs:19:9
    |
 LL |         async move { self.f().await }
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Trait` is not implemented for `T`
diff --git a/tests/ui/type-alias-impl-trait/issue-93411.rs b/tests/ui/type-alias-impl-trait/issue-93411.rs
index 2d08b7ba4c1..11cbb876631 100644
--- a/tests/ui/type-alias-impl-trait/issue-93411.rs
+++ b/tests/ui/type-alias-impl-trait/issue-93411.rs
@@ -14,6 +14,7 @@ fn main() {
 }
 
 type BlahFut<'a> = impl Future<Output = ()> + Send + 'a;
+#[define_opaque(BlahFut)]
 fn blah<'a>(_value: &'a u8) -> BlahFut<'a> {
     async {}
 }
diff --git a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
index 7097123d608..08f3c404bed 100644
--- a/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
+++ b/tests/ui/type-alias-impl-trait/issue-96572-unconstrained.rs
@@ -44,6 +44,7 @@ fn r#struct() {
 mod only_pattern {
     type T = impl Copy;
 
+    #[define_opaque(T)]
     fn foo(foo: T) {
         let (mut x, mut y) = foo;
         x = 42;
@@ -52,6 +53,7 @@ mod only_pattern {
 
     type U = impl Copy;
 
+    #[define_opaque(U)]
     fn bar(bar: Option<U>) {
         match bar {
             Some((mut x, mut y)) => {
@@ -64,6 +66,7 @@ mod only_pattern {
 
     type V = impl Copy;
 
+    #[define_opaque(V)]
     fn baz(baz: Option<V>) {
         match baz {
             _ => {}
diff --git a/tests/ui/type-alias-impl-trait/itiat-forbid-nested-items.stderr b/tests/ui/type-alias-impl-trait/itiat-forbid-nested-items.stderr
index c177201431a..5b38b83e4d9 100644
--- a/tests/ui/type-alias-impl-trait/itiat-forbid-nested-items.stderr
+++ b/tests/ui/type-alias-impl-trait/itiat-forbid-nested-items.stderr
@@ -11,11 +11,6 @@ LL |             let x: <() as Foo>::Assoc = 42_i32;
    |
    = note: expected opaque type `<() as Foo>::Assoc`
                      found type `i32`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/itiat-forbid-nested-items.rs:11:12
-   |
-LL |         fn foo() -> <() as Foo>::Assoc {
-   |            ^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs
index 1bc352041a5..075b0bd75fa 100644
--- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs
+++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.rs
@@ -6,6 +6,7 @@
 
 type Tait = impl FnOnce() -> ();
 
+#[define_opaque(Tait)]
 fn reify_as_tait() -> Thunk<Tait> {
     //~^ ERROR: expected a `FnOnce()` closure, found `()`
     Thunk::new(|cont| cont)
diff --git a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr
index 921667f577b..0bee0dfa9c7 100644
--- a/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr
+++ b/tests/ui/type-alias-impl-trait/lazy_subtyping_of_opaques.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/lazy_subtyping_of_opaques.rs:11:5
+  --> $DIR/lazy_subtyping_of_opaques.rs:12:5
    |
 LL | fn reify_as_tait() -> Thunk<Tait> {
    |                       ----------- expected `Thunk<_>` because of return type
@@ -11,7 +11,7 @@ LL |     Thunk::new(|cont| cont)
            found unit type `()`
 
 error[E0277]: expected a `FnOnce()` closure, found `()`
-  --> $DIR/lazy_subtyping_of_opaques.rs:11:23
+  --> $DIR/lazy_subtyping_of_opaques.rs:12:23
    |
 LL |     Thunk::new(|cont| cont)
    |                       ^^^^ expected an `FnOnce()` closure, found `()`
@@ -20,7 +20,7 @@ LL |     Thunk::new(|cont| cont)
    = note: wrap the `()` in a closure with no arguments: `|| { /* code */ }`
 
 error[E0277]: expected a `FnOnce()` closure, found `()`
-  --> $DIR/lazy_subtyping_of_opaques.rs:9:23
+  --> $DIR/lazy_subtyping_of_opaques.rs:10:23
    |
 LL | fn reify_as_tait() -> Thunk<Tait> {
    |                       ^^^^^^^^^^^ expected an `FnOnce()` closure, found `()`
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
index 45a55050c44..b58840718a3 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.rs
@@ -2,6 +2,7 @@
 
 type Foo<'a> = impl Sized;
 
+#[define_opaque(Foo)]
 fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
     (x, y)
     //~^ ERROR opaque type used twice with different lifetimes
@@ -9,6 +10,7 @@ fn foo<'a, 'b>(x: &'a u32, y: &'b u32) -> (Foo<'a>, Foo<'b>) {
 
 type Bar<'a, 'b> = impl std::fmt::Debug;
 
+#[define_opaque(Bar)]
 fn bar<'x, 'y>(i: &'x i32, j: &'y i32) -> (Bar<'x, 'y>, Bar<'y, 'x>) {
     (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
diff --git a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
index 4f7b0f17407..719748edc01 100644
--- a/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/lifetime_mismatch.stderr
@@ -1,5 +1,5 @@
 error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:6:5
+  --> $DIR/lifetime_mismatch.rs:7:5
    |
 LL |     (x, y)
    |     ^^^^^^
@@ -8,13 +8,13 @@ LL |     (x, y)
    |     lifetime `'b` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:6:5
+  --> $DIR/lifetime_mismatch.rs:7:5
    |
 LL |     (x, y)
    |     ^^^^^^
 
 error: opaque type used twice with different lifetimes
-  --> $DIR/lifetime_mismatch.rs:13:5
+  --> $DIR/lifetime_mismatch.rs:15:5
    |
 LL |     (i, j)
    |     ^^^^^^
@@ -23,7 +23,7 @@ LL |     (i, j)
    |     lifetime `'y` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/lifetime_mismatch.rs:13:5
+  --> $DIR/lifetime_mismatch.rs:15:5
    |
 LL |     (i, j)
    |     ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
index a9c05ad3342..07e7126f8a0 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution.current.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
-  --> $DIR/method_resolution.rs:21:14
+  --> $DIR/method_resolution.rs:22:14
    |
 LL | struct Bar<T>(T);
    | ------------- method `bar` not found for this struct
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
index 6b34358a56e..7462d2b478b 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution.next.stderr
@@ -1,5 +1,5 @@
 error[E0599]: no method named `bar` found for struct `Bar<u32>` in the current scope
-  --> $DIR/method_resolution.rs:21:14
+  --> $DIR/method_resolution.rs:22:14
    |
 LL | struct Bar<T>(T);
    | ------------- method `bar` not found for this struct
diff --git a/tests/ui/type-alias-impl-trait/method_resolution.rs b/tests/ui/type-alias-impl-trait/method_resolution.rs
index f636aba15c0..a9162d0e28b 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution.rs
@@ -11,6 +11,7 @@ type Foo = impl Sized;
 struct Bar<T>(T);
 
 impl Bar<Foo> {
+    #[define_opaque(Foo)]
     fn bar(mut self) {
         self.0 = 42_u32;
     }
@@ -23,6 +24,7 @@ impl Bar<u32> {
     }
 }
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     42_u32
 }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution2.rs b/tests/ui/type-alias-impl-trait/method_resolution2.rs
index f69661db799..a4c4bbbace6 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution2.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution2.rs
@@ -12,6 +12,7 @@ type Foo = impl Sized;
 struct Bar<T>(T);
 
 impl Bar<Foo> {
+    #[define_opaque(Foo)]
     fn bar(self) {
         self.foo()
     }
@@ -21,6 +22,7 @@ impl Bar<u32> {
     fn foo(self) {}
 }
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     42_u32
 }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution3.rs b/tests/ui/type-alias-impl-trait/method_resolution3.rs
index 0e6176bfe03..a18dcc9a2fe 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution3.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution3.rs
@@ -27,6 +27,7 @@ impl Bar<u32> {
     fn foo(self) {}
 }
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     42_u32
 }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
index e4c4d121733..569a9f49bbe 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.current.stderr
@@ -1,5 +1,5 @@
 error[E0307]: invalid `self` parameter type: `Bar<Foo>`
-  --> $DIR/method_resolution4.rs:27:18
+  --> $DIR/method_resolution4.rs:25:18
    |
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
@@ -8,7 +8,7 @@ LL |     fn foo(self: Bar<Foo>) {
    = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
-  --> $DIR/method_resolution4.rs:31:20
+  --> $DIR/method_resolution4.rs:29:20
    |
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
index e4c4d121733..569a9f49bbe 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.next.stderr
@@ -1,5 +1,5 @@
 error[E0307]: invalid `self` parameter type: `Bar<Foo>`
-  --> $DIR/method_resolution4.rs:27:18
+  --> $DIR/method_resolution4.rs:25:18
    |
 LL |     fn foo(self: Bar<Foo>) {
    |                  ^^^^^^^^
@@ -8,7 +8,7 @@ LL |     fn foo(self: Bar<Foo>) {
    = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
 
 error[E0307]: invalid `self` parameter type: `&Bar<Foo>`
-  --> $DIR/method_resolution4.rs:31:20
+  --> $DIR/method_resolution4.rs:29:20
    |
 LL |     fn foomp(self: &Bar<Foo>) {
    |                    ^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/method_resolution4.rs b/tests/ui/type-alias-impl-trait/method_resolution4.rs
index f33b4e473ae..8a1b60b0c6e 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution4.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution4.rs
@@ -7,14 +7,12 @@
 
 #![feature(type_alias_impl_trait, arbitrary_self_types)]
 
-mod foo {
-    pub type Foo = impl Copy;
+pub type Foo = impl Copy;
 
-    fn foo() -> Foo {
-        42_u32
-    }
+#[define_opaque(Foo)]
+fn foo() -> Foo {
+    42_u32
 }
-use foo::Foo;
 
 #[derive(Copy, Clone)]
 struct Bar<T>(T);
diff --git a/tests/ui/type-alias-impl-trait/method_resolution5.rs b/tests/ui/type-alias-impl-trait/method_resolution5.rs
index 64355e4560d..b22c44ceb13 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution5.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution5.rs
@@ -12,20 +12,20 @@ type Foo = impl Sized;
 struct Bar<T>(T);
 
 impl Bar<Foo> {
+    #[define_opaque(Foo)]
     fn bar(mut self) {
         self.0 = 42_u32;
     }
 }
 
 impl Bar<u32> {
-    fn foo(self)
-    where
-        Foo:,
-    {
+    #[define_opaque(Foo)]
+    fn foo(self) {
         self.bar()
     }
 }
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     42_u32
 }
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
index f331da1af87..841aa12f983 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.current.stderr
@@ -1,11 +1,11 @@
-error: item does not constrain `Tait::{opaque#0}`, but has it in its signature
-  --> $DIR/method_resolution_trait_method_from_opaque.rs:24:8
+error: item does not constrain `Tait::{opaque#0}`
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:26:8
    |
 LL |     fn foo(&mut self) {
    |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/method_resolution_trait_method_from_opaque.rs:17:13
    |
 LL | type Tait = impl Iterator<Item = ()>;
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
index 2617ce124c1..bbdd3923821 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.next.stderr
@@ -1,5 +1,5 @@
 error[E0282]: type annotations needed
-  --> $DIR/method_resolution_trait_method_from_opaque.rs:26:9
+  --> $DIR/method_resolution_trait_method_from_opaque.rs:28:9
    |
 LL |         self.bar.next().unwrap();
    |         ^^^^^^^^ cannot infer type
diff --git a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
index b6adf08853f..93461fcbb0b 100644
--- a/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
+++ b/tests/ui/type-alias-impl-trait/method_resolution_trait_method_from_opaque.rs
@@ -17,10 +17,12 @@ pub struct Foo {
 type Tait = impl Iterator<Item = ()>;
 
 impl Foo {
+    #[define_opaque(Tait)]
     pub fn new() -> Foo {
         Foo { bar: std::iter::empty() }
     }
 
+    #[define_opaque(Tait)]
     fn foo(&mut self) {
         //[current]~^ ERROR: item does not constrain
         self.bar.next().unwrap();
diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs
index c178fcf5a91..d77efa39aeb 100644
--- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs
+++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.rs
@@ -2,6 +2,7 @@
 
 type Opaque2<T> = impl Sized;
 type Opaque<'a, T> = Opaque2<T>;
+#[define_opaque(Opaque)]
 fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x } //~ WARNING elided lifetime has a name
 //~^ ERROR: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds
 
diff --git a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
index e2c21f1636b..61eb76ffc5a 100644
--- a/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
+++ b/tests/ui/type-alias-impl-trait/missing_lifetime_bound.stderr
@@ -1,5 +1,5 @@
 warning: elided lifetime has a name
-  --> $DIR/missing_lifetime_bound.rs:5:41
+  --> $DIR/missing_lifetime_bound.rs:6:41
    |
 LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
    |             --                          ^ this elided lifetime gets resolved as `'a`
@@ -9,11 +9,11 @@ LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
    = note: `#[warn(elided_named_lifetimes)]` on by default
 
 error[E0700]: hidden type for `Opaque2<T>` captures lifetime that does not appear in bounds
-  --> $DIR/missing_lifetime_bound.rs:5:47
+  --> $DIR/missing_lifetime_bound.rs:6:47
    |
 LL | type Opaque2<T> = impl Sized;
    |                   ---------- opaque type defined here
-LL | type Opaque<'a, T> = Opaque2<T>;
+...
 LL | fn defining<'a, T>(x: &'a i32) -> Opaque<T> { x }
    |             --                                ^
    |             |
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
index b887fcf3083..3dd2d53fe3d 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.rs
@@ -6,6 +6,7 @@
 
 type Y<A, B> = impl std::fmt::Debug;
 
+#[define_opaque(Y)]
 fn g<A, B>() -> (Y<A, B>, Y<B, A>) {
     (42_i64, 60) //~ ERROR concrete type differs from previous defining opaque type use
 }
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
index b050b08a8e2..d6558576577 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-infer.stderr
@@ -1,5 +1,5 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:10:5
+  --> $DIR/multiple-def-uses-in-one-fn-infer.rs:11:5
    |
 LL |     (42_i64, 60)
    |     ^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
index 580fb58ef83..39e4912ae3a 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.rs
@@ -2,6 +2,7 @@
 
 type Foo<'a, 'b> = impl std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo<'x, 'y>(i: &'x i32, j: &'y i32) -> (Foo<'x, 'y>, Foo<'y, 'x>) {
     (i, j)
     //~^ ERROR opaque type used twice with different lifetimes
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
index b2b9e604a6b..03f2b1c532a 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-lifetimes.stderr
@@ -1,5 +1,5 @@
 error: opaque type used twice with different lifetimes
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
+  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:7:5
    |
 LL |     (i, j)
    |     ^^^^^^
@@ -8,7 +8,7 @@ LL |     (i, j)
    |     lifetime `'y` previously used here
    |
 note: if all non-lifetime generic parameters are the same, but the lifetime parameters differ, it is not possible to differentiate the opaque types
-  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:6:5
+  --> $DIR/multiple-def-uses-in-one-fn-lifetimes.rs:7:5
    |
 LL |     (i, j)
    |     ^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
index aba41a9d852..50c97060cef 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn-pass.rs
@@ -3,11 +3,13 @@
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
 
+#[define_opaque(X)]
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
     (a.clone(), a)
 }
 
 type Tait<'x> = impl Sized;
+#[define_opaque(Tait)]
 fn define<'a: 'b, 'b: 'a>(x: &'a u8, y: &'b u8) -> (Tait<'a>, Tait<'b>) {
     ((), ())
 }
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
index da845e86147..5e2b140ef8b 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.rs
@@ -6,6 +6,7 @@
 
 type X<A, B> = impl Into<&'static A>;
 
+#[define_opaque(X)]
 fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
     //~^ ERROR the trait bound `&'static B: From<&A>` is not satisfied
     (a, a)
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
index b5f38074632..05a169882cb 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `&'static B: From<&A>` is not satisfied
-  --> $DIR/multiple-def-uses-in-one-fn.rs:9:45
+  --> $DIR/multiple-def-uses-in-one-fn.rs:10:45
    |
 LL | fn f<A, B: 'static>(a: &'static A, b: B) -> (X<A, B>, X<B, A>) {
    |                                             ^^^^^^^^^^^^^^^^^^ the trait `From<&A>` is not implemented for `&'static B`
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
index 14510a5294e..1357d772be1 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.rs
@@ -6,6 +6,7 @@
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
 
+#[define_opaque(X)]
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
     (a.clone(), a)
     //~^ ERROR concrete type differs from previous defining opaque type
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
index c7a4b2115bf..15e9b6fbf76 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn2.stderr
@@ -1,5 +1,5 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/multiple-def-uses-in-one-fn2.rs:10:5
+  --> $DIR/multiple-def-uses-in-one-fn2.rs:11:5
    |
 LL |     (a.clone(), a)
    |     ^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
index 11a922443e6..11d23efec75 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.rs
@@ -6,10 +6,12 @@
 
 type X<A: ToString + Clone, B: ToString + Clone> = impl ToString;
 
+#[define_opaque(X)]
 fn f<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<B, A>) {
     (a, b)
 }
 
+#[define_opaque(X)]
 fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
     (a, b)
     //~^ ERROR mismatched types
diff --git a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
index c3128ea6f5e..42ba769797b 100644
--- a/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
+++ b/tests/ui/type-alias-impl-trait/multiple-def-uses-in-one-fn3.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-def-uses-in-one-fn3.rs:14:9
+  --> $DIR/multiple-def-uses-in-one-fn3.rs:16:9
    |
 LL | fn g<A: ToString + Clone, B: ToString + Clone>(a: A, b: B) -> (X<A, B>, X<A, B>) {
    |      -                    - found type parameter
diff --git a/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr
index ca15b134a99..3a13ab7cb95 100644
--- a/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-impl-trait-in-tait.stderr
@@ -31,7 +31,7 @@ error: unconstrained opaque type
 LL | pub type Tait = impl Iterator<Item = (&'db LocalKey, impl Iterator)>;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Tait` must be used in combination with a concrete type within the same module
+   = note: `Tait` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/nested-impl-trait-in-tait.rs:3:54
@@ -39,7 +39,7 @@ error: unconstrained opaque type
 LL | pub type Tait = impl Iterator<Item = (&'db LocalKey, impl Iterator)>;
    |                                                      ^^^^^^^^^^^^^
    |
-   = note: `Tait` must be used in combination with a concrete type within the same module
+   = note: `Tait` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr b/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr
index aa0c1076117..54389efc9c6 100644
--- a/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-in-anon-const.stderr
@@ -13,7 +13,7 @@ error: unconstrained opaque type
 LL |                     type B<Z> = impl Sized;
    |                                 ^^^^^^^^^^
    |
-   = note: `B` must be used in combination with a concrete type within the same item
+   = note: `B` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
index ba705d6f85a..6ef6f31953f 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.rs
@@ -4,11 +4,13 @@ trait Trait<'a> { type Assoc; }
 impl<'a> Trait<'a> for () { type Assoc = &'a str; }
 
 type WithoutLt = impl Sized;
+#[define_opaque(WithoutLt)]
 fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
 //~^ ERROR captures lifetime that does not appear in bounds
 
 type WithLt<'a> = impl Sized + 'a;
 
+#[define_opaque(WithLt)]
 fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
 //~^ ERROR expected generic lifetime parameter, found `'a`
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
index f208730552d..ad60d186dd3 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-hrtb.stderr
@@ -1,19 +1,20 @@
 error[E0700]: hidden type for `WithoutLt` captures lifetime that does not appear in bounds
-  --> $DIR/nested-tait-hrtb.rs:7:62
+  --> $DIR/nested-tait-hrtb.rs:8:62
    |
 LL | type WithoutLt = impl Sized;
    |                  ---------- opaque type defined here
+LL | #[define_opaque(WithoutLt)]
 LL | fn without_lt() -> impl for<'a> Trait<'a, Assoc = WithoutLt> {}
    |                             --                               ^^
    |                             |
    |                             hidden type `&'a str` captures the lifetime `'a` as defined here
 
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/nested-tait-hrtb.rs:12:60
+  --> $DIR/nested-tait-hrtb.rs:14:60
    |
 LL | type WithLt<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
-LL |
+...
 LL | fn with_lt() -> impl for<'a> Trait<'a, Assoc = WithLt<'a>> {}
    |                                                            ^^
 
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
index 915432bbe67..b19f34a67ff 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
-  --> $DIR/nested-tait-inference.rs:17:13
+  --> $DIR/nested-tait-inference.rs:18:13
    |
 LL | fn foo() -> impl Foo<FooX> {
    |             ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
index 50d51c7faf9..d4ad72797cf 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference.rs
@@ -14,6 +14,7 @@ trait Foo<A> {}
 
 impl Foo<()> for () {}
 
+#[define_opaque(FooX)]
 fn foo() -> impl Foo<FooX> {
     //[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
     // FIXME(type-alias-impl-trait): We could probably make this work.
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
index 9da3926ac70..27372ceed94 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `(): Foo<FooX>` is not satisfied
-  --> $DIR/nested-tait-inference2.rs:17:13
+  --> $DIR/nested-tait-inference2.rs:18:13
    |
 LL | fn foo() -> impl Foo<FooX> {
    |             ^^^^^^^^^^^^^^ the trait `Foo<FooX>` is not implemented for `()`
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
index 9647d9e376e..b733739e4c8 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.next.stderr
@@ -1,5 +1,5 @@
 error[E0284]: type annotations needed: cannot satisfy `impl Foo<FooX> == ()`
-  --> $DIR/nested-tait-inference2.rs:19:5
+  --> $DIR/nested-tait-inference2.rs:20:5
    |
 LL |     ()
    |     ^^ cannot satisfy `impl Foo<FooX> == ()`
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
index 28d72b0cbee..4aeecb9140c 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference2.rs
@@ -14,6 +14,7 @@ trait Foo<A> {}
 impl Foo<()> for () {}
 impl Foo<u32> for () {}
 
+#[define_opaque(FooX)]
 fn foo() -> impl Foo<FooX> {
     //[current]~^ ERROR: the trait bound `(): Foo<FooX>` is not satisfied
     ()
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
index aaf2812532d..3e7b8c80d1b 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.rs
@@ -9,6 +9,7 @@ trait Foo<A> {}
 
 impl Foo<FooX> for () {}
 
+#[define_opaque(FooX)]
 fn foo() -> impl Foo<FooX> {
     //~^ ERROR: item does not constrain
     ()
diff --git a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
index 969409ebc59..be7aec92312 100644
--- a/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
+++ b/tests/ui/type-alias-impl-trait/nested-tait-inference3.stderr
@@ -1,11 +1,11 @@
-error: item does not constrain `FooX::{opaque#0}`, but has it in its signature
-  --> $DIR/nested-tait-inference3.rs:12:4
+error: item does not constrain `FooX::{opaque#0}`
+  --> $DIR/nested-tait-inference3.rs:13:4
    |
 LL | fn foo() -> impl Foo<FooX> {
    |    ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/nested-tait-inference3.rs:6:13
    |
 LL | type FooX = impl Debug;
diff --git a/tests/ui/type-alias-impl-trait/nested.rs b/tests/ui/type-alias-impl-trait/nested.rs
index 524703939f1..1a89039af8a 100644
--- a/tests/ui/type-alias-impl-trait/nested.rs
+++ b/tests/ui/type-alias-impl-trait/nested.rs
@@ -7,6 +7,7 @@ trait Trait<T> {}
 
 impl<T, U> Trait<T> for U {}
 
+#[define_opaque(Bar)]
 fn bar() -> Bar {
     //~^ ERROR: item does not constrain
     42
diff --git a/tests/ui/type-alias-impl-trait/nested.stderr b/tests/ui/type-alias-impl-trait/nested.stderr
index ca1cf6058ea..59911f65a23 100644
--- a/tests/ui/type-alias-impl-trait/nested.stderr
+++ b/tests/ui/type-alias-impl-trait/nested.stderr
@@ -1,18 +1,18 @@
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/nested.rs:10:4
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/nested.rs:11:4
    |
 LL | fn bar() -> Bar {
    |    ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
   --> $DIR/nested.rs:3:12
    |
 LL | type Foo = impl std::fmt::Debug;
    |            ^^^^^^^^^^^^^^^^^^^^
 
 error[E0277]: `Bar` doesn't implement `Debug`
-  --> $DIR/nested.rs:16:22
+  --> $DIR/nested.rs:17:22
    |
 LL |     println!("{:?}", bar());
    |                      ^^^^^ `Bar` cannot be formatted using `{:?}` because it doesn't implement `Debug`
diff --git a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
index 004e79d6738..c0581b018e9 100644
--- a/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
+++ b/tests/ui/type-alias-impl-trait/nested_inference_failure.rs
@@ -22,6 +22,7 @@ struct Foo<T: Debug, F: FnOnce(T)> {
 type ImplT = impl Debug;
 type FooImpl = Foo<ImplT, impl FnOnce(ImplT)>;
 
+#[define_opaque(FooImpl)]
 fn bar() -> FooImpl {
     Foo::<i32, _> { f: |_| (), _phantom: PhantomData }
 }
diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
index 4def8948708..5adae476bfe 100644
--- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
+++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.rs
@@ -1,21 +1,21 @@
 #![feature(type_alias_impl_trait)]
 
-mod my_mod {
-    use std::fmt::Debug;
+use std::fmt::Debug;
 
-    pub type Foo = impl Debug;
-    pub type Foot = impl Debug;
+pub type Foo = impl Debug;
+pub type Foot = impl Debug;
 
-    pub fn get_foo() -> Foo {
-        5i32
-    }
+#[define_opaque(Foo)]
+pub fn get_foo() -> Foo {
+    5i32
+}
 
-    pub fn get_foot(_: Foo) -> Foot {
-        //~^ ERROR: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-        get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
-    }
+#[define_opaque(Foot, Foo)]
+pub fn get_foot(_: Foo) -> Foot {
+    //~^ ERROR: item does not constrain `Foo::{opaque#0}`
+    get_foo() //~ ERROR opaque type's hidden type cannot be another opaque type
 }
 
 fn main() {
-    let _: my_mod::Foot = my_mod::get_foot(my_mod::get_foo());
+    let _: Foot = get_foot(get_foo());
 }
diff --git a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
index 889cff1ba09..aabae315777 100644
--- a/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
+++ b/tests/ui/type-alias-impl-trait/nested_type_alias_impl_trait.stderr
@@ -1,32 +1,32 @@
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/nested_type_alias_impl_trait.rs:13:12
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/nested_type_alias_impl_trait.rs:14:8
    |
-LL |     pub fn get_foot(_: Foo) -> Foot {
-   |            ^^^^^^^^
+LL | pub fn get_foot(_: Foo) -> Foot {
+   |        ^^^^^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/nested_type_alias_impl_trait.rs:6:20
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/nested_type_alias_impl_trait.rs:5:16
    |
-LL |     pub type Foo = impl Debug;
-   |                    ^^^^^^^^^^
+LL | pub type Foo = impl Debug;
+   |                ^^^^^^^^^^
 
 error: opaque type's hidden type cannot be another opaque type from the same scope
-  --> $DIR/nested_type_alias_impl_trait.rs:15:9
+  --> $DIR/nested_type_alias_impl_trait.rs:16:5
    |
-LL |         get_foo()
-   |         ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
+LL |     get_foo()
+   |     ^^^^^^^^^ one of the two opaque types used here has to be outside its defining scope
    |
 note: opaque type whose hidden type is being assigned
-  --> $DIR/nested_type_alias_impl_trait.rs:7:21
+  --> $DIR/nested_type_alias_impl_trait.rs:6:17
    |
-LL |     pub type Foot = impl Debug;
-   |                     ^^^^^^^^^^
+LL | pub type Foot = impl Debug;
+   |                 ^^^^^^^^^^
 note: opaque type being used as hidden type
-  --> $DIR/nested_type_alias_impl_trait.rs:6:20
+  --> $DIR/nested_type_alias_impl_trait.rs:5:16
    |
-LL |     pub type Foo = impl Debug;
-   |                    ^^^^^^^^^^
+LL | pub type Foo = impl Debug;
+   |                ^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
index 590107d1038..fc47243d693 100644
--- a/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
+++ b/tests/ui/type-alias-impl-trait/never_reveal_concrete_type.rs
@@ -4,10 +4,12 @@ fn main() {}
 
 type NoReveal = impl std::fmt::Debug;
 
+#[define_opaque(NoReveal)]
 fn define_no_reveal() -> NoReveal {
     ""
 }
 
+#[define_opaque(NoReveal)]
 fn no_reveal(x: NoReveal) {
     let _: &'static str = x;
     let _ = x as &'static str;
diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
index 41238c27351..8e5e4719415 100644
--- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
+++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.rs
@@ -3,18 +3,17 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub type Foo = impl Copy;
+pub type Foo = impl Copy;
 
-    // make compiler happy about using 'Foo'
-    pub fn bar(x: Foo) -> Foo {
-        //~^ ERROR: item does not constrain `Foo::{opaque#0}`
-        x
-    }
+// make compiler happy about using 'Foo'
+#[define_opaque(Foo)]
+pub fn bar(x: Foo) -> Foo {
+    //~^ ERROR: item does not constrain `Foo::{opaque#0}`
+    x
 }
 
 fn main() {
     unsafe {
-        let _: foo::Foo = std::mem::transmute(0u8);
+        let _: Foo = std::mem::transmute(0u8);
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
index eed88c5df4f..a57793d5a77 100644
--- a/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
+++ b/tests/ui/type-alias-impl-trait/no_inferrable_concrete_type.stderr
@@ -1,15 +1,15 @@
-error: item does not constrain `Foo::{opaque#0}`, but has it in its signature
-  --> $DIR/no_inferrable_concrete_type.rs:10:12
+error: item does not constrain `Foo::{opaque#0}`
+  --> $DIR/no_inferrable_concrete_type.rs:10:8
    |
-LL |     pub fn bar(x: Foo) -> Foo {
-   |            ^^^
+LL | pub fn bar(x: Foo) -> Foo {
+   |        ^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/no_inferrable_concrete_type.rs:7:20
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/no_inferrable_concrete_type.rs:6:16
    |
-LL |     pub type Foo = impl Copy;
-   |                    ^^^^^^^^^
+LL | pub type Foo = impl Copy;
+   |                ^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs
index 61153b1e171..42161dcde66 100644
--- a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs
+++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.rs
@@ -2,11 +2,10 @@
 
 fn main() {}
 
-mod boo {
-    pub type Boo = impl ::std::fmt::Debug;
-    fn bomp() -> Boo {
-        ""
-    }
+pub type Boo = impl ::std::fmt::Debug;
+#[define_opaque(Boo)]
+fn define() -> Boo {
+    ""
 }
 
 // We don't actually know the type here.
@@ -15,10 +14,10 @@ fn bomp2() {
     let _: &str = bomp(); //~ ERROR mismatched types
 }
 
-fn bomp() -> boo::Boo {
+fn bomp() -> Boo {
     "" //~ ERROR mismatched types
 }
 
-fn bomp_loop() -> boo::Boo {
+fn bomp_loop() -> Boo {
     loop {}
 }
diff --git a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
index 863282a0ff9..f4416eb009a 100644
--- a/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
+++ b/tests/ui/type-alias-impl-trait/no_revealing_outside_defining_module.stderr
@@ -1,8 +1,8 @@
 error[E0308]: mismatched types
-  --> $DIR/no_revealing_outside_defining_module.rs:15:19
+  --> $DIR/no_revealing_outside_defining_module.rs:14:19
    |
-LL |     pub type Boo = impl ::std::fmt::Debug;
-   |                    ---------------------- the found opaque type
+LL | pub type Boo = impl ::std::fmt::Debug;
+   |                ---------------------- the found opaque type
 ...
 LL |     let _: &str = bomp();
    |            ----   ^^^^^^ expected `&str`, found opaque type
@@ -11,29 +11,29 @@ LL |     let _: &str = bomp();
    |
    = note: expected reference `&str`
             found opaque type `Boo`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/no_revealing_outside_defining_module.rs:14:4
+note: this item must have a `#[define_opaque(Boo)]` attribute to be able to define hidden types
+  --> $DIR/no_revealing_outside_defining_module.rs:13:4
    |
 LL | fn bomp2() {
    |    ^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/no_revealing_outside_defining_module.rs:19:5
+  --> $DIR/no_revealing_outside_defining_module.rs:18:5
    |
-LL |     pub type Boo = impl ::std::fmt::Debug;
-   |                    ---------------------- the expected opaque type
+LL | pub type Boo = impl ::std::fmt::Debug;
+   |                ---------------------- the expected opaque type
 ...
-LL | fn bomp() -> boo::Boo {
-   |              -------- expected `Boo` because of return type
+LL | fn bomp() -> Boo {
+   |              --- expected `Boo` because of return type
 LL |     ""
    |     ^^ expected opaque type, found `&str`
    |
    = note: expected opaque type `Boo`
                 found reference `&'static str`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/no_revealing_outside_defining_module.rs:18:4
+note: this item must have a `#[define_opaque(Boo)]` attribute to be able to define hidden types
+  --> $DIR/no_revealing_outside_defining_module.rs:17:4
    |
-LL | fn bomp() -> boo::Boo {
+LL | fn bomp() -> Boo {
    |    ^^^^
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/type-alias-impl-trait/normalize-alias-type.rs b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs
index 9fcf42e188c..d0fcfb438fb 100644
--- a/tests/ui/type-alias-impl-trait/normalize-alias-type.rs
+++ b/tests/ui/type-alias-impl-trait/normalize-alias-type.rs
@@ -18,7 +18,7 @@ pub fn tr1() -> impl Tr {
 }
 
 struct Inner {
-    x: helper::X,
+    x: X,
 }
 impl Tr for Inner {
     fn get(&self) -> u32 {
@@ -26,14 +26,9 @@ impl Tr for Inner {
     }
 }
 
-mod helper {
-    pub use super::*;
-    pub type X = impl Tr;
+pub type X = impl Tr;
 
-    pub fn tr2() -> impl Tr
-    where
-        X:,
-    {
-        Inner { x: tr1() }
-    }
+#[define_opaque(X)]
+pub fn tr2() -> impl Tr {
+    Inner { x: tr1() }
 }
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
index a40dac06a01..75cc5948e93 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.current.stderr
@@ -1,29 +1,29 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:26:20
+  --> $DIR/normalize-hidden-types.rs:27:20
    |
 LL |     fn define() -> Opaque {
    |                    ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:27:9
+  --> $DIR/normalize-hidden-types.rs:28:9
    |
 LL |         dyn_hoops::<_>(0)
    |         ^^^^^^^^^^^^^^^^^
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:34:22
+  --> $DIR/normalize-hidden-types.rs:36:22
    |
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                      ^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:34:31
+  --> $DIR/normalize-hidden-types.rs:36:31
    |
 LL |     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
    |                               ^^^^^^^^^^^^^^^^^
 
 error[E0308]: mismatched types
-  --> $DIR/normalize-hidden-types.rs:43:25
+  --> $DIR/normalize-hidden-types.rs:47:25
    |
 LL |     type Opaque = impl Sized;
    |                   ---------- the expected opaque type
@@ -39,13 +39,13 @@ LL |         let _: Opaque = dyn_hoops::<u8>(0);
    = note: for more information, visit https://doc.rust-lang.org/book/ch19-03-advanced-traits.html
 
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/normalize-hidden-types.rs:52:25
+  --> $DIR/normalize-hidden-types.rs:57:25
    |
 LL |         let _: Opaque = dyn_hoops::<_>(0);
    |                         ^^^^^^^^^^^^^^^^^ expected `*const (dyn FnOnce(()) + 'static)`, got `*const dyn for<'a> FnOnce(<u8 as Trait>::Gat<'a>)`
    |
 note: previous use here
-  --> $DIR/normalize-hidden-types.rs:53:9
+  --> $DIR/normalize-hidden-types.rs:58:9
    |
 LL |         None
    |         ^^^^
diff --git a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
index 4028dba82bf..bc007169b83 100644
--- a/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
+++ b/tests/ui/type-alias-impl-trait/normalize-hidden-types.rs
@@ -23,6 +23,7 @@ fn dyn_hoops<T: Trait>(_: T) -> *const dyn FnOnce(T::Gat<'_>) {
 mod typeof_1 {
     use super::*;
     type Opaque = impl Sized;
+    #[define_opaque(Opaque)]
     fn define() -> Opaque {
         dyn_hoops::<_>(0)
     }
@@ -31,13 +32,16 @@ mod typeof_1 {
 mod typeof_2 {
     use super::*;
     type Opaque = impl Sized;
+    #[define_opaque(Opaque)]
     fn define_1() -> Opaque { dyn_hoops::<_>(0) }
+    #[define_opaque(Opaque)]
     fn define_2() -> Opaque { dyn_hoops::<u8>(0) }
 }
 
 mod typeck {
     use super::*;
     type Opaque = impl Sized;
+    #[define_opaque(Opaque)]
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
         let _: Opaque = dyn_hoops::<u8>(0);
@@ -48,6 +52,7 @@ mod typeck {
 mod borrowck {
     use super::*;
     type Opaque = impl Sized;
+    #[define_opaque(Opaque)]
     fn define() -> Option<Opaque> {
         let _: Opaque = dyn_hoops::<_>(0);
         None
diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs
index 131f8d999d8..112ee4d5571 100644
--- a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs
+++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.rs
@@ -9,6 +9,7 @@ trait Foo<T> {
 struct DefinesOpaque;
 impl Foo<DefinesOpaque> for () {
     type Assoc = impl Sized;
+    //~^ ERROR: unconstrained opaque type
 
     // This test's return type is `u32`, *not* the opaque that is defined above.
     // Previously we were only checking that the self type of the assoc matched,
diff --git a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
index d4528fb76fe..1d1b14e1463 100644
--- a/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
+++ b/tests/ui/type-alias-impl-trait/not-matching-trait-refs-isnt-defining.stderr
@@ -1,5 +1,13 @@
+error: unconstrained opaque type
+  --> $DIR/not-matching-trait-refs-isnt-defining.rs:11:18
+   |
+LL |     type Assoc = impl Sized;
+   |                  ^^^^^^^^^^
+   |
+   = note: `Assoc` must be used in combination with a concrete type within the same impl
+
 error[E0308]: mismatched types
-  --> $DIR/not-matching-trait-refs-isnt-defining.rs:17:54
+  --> $DIR/not-matching-trait-refs-isnt-defining.rs:18:54
    |
 LL |     type Assoc = impl Sized;
    |                  ---------- the expected opaque type
@@ -11,12 +19,7 @@ LL |         let _: <Self as Foo<DefinesOpaque>>::Assoc = "";
    |
    = note: expected opaque type `<() as Foo<DefinesOpaque>>::Assoc`
                 found reference `&'static str`
-note: this item must have the opaque type in its signature in order to be able to register hidden types
-  --> $DIR/not-matching-trait-refs-isnt-defining.rs:16:8
-   |
-LL |     fn test() -> <() as Foo<NoOpaques>>::Assoc {
-   |        ^^^^
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
index b5ef1470629..d20622dc2e0 100644
--- a/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
+++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.rs
@@ -6,6 +6,7 @@ fn main() {}
 
 type Two<T, U> = impl Debug;
 
+#[define_opaque(Two)]
 fn three<T: Debug, U>(t: T) -> Two<T, U> {
     (t, 5i8)
 }
@@ -20,6 +21,7 @@ impl Bar for u32 {
     const FOO: i32 = 42;
 }
 
+#[define_opaque(Two)]
 fn four<T: Debug, U: Bar>(t: T) -> Two<T, U> {
     (t, <U as Bar>::FOO)
     //~^ ERROR concrete type differs
diff --git a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
index b59f9c49b07..d90e4531879 100644
--- a/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
+++ b/tests/ui/type-alias-impl-trait/not_a_defining_use.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/not_a_defining_use.rs:24:5
+  --> $DIR/not_a_defining_use.rs:26:5
    |
 LL |     (t, <U as Bar>::FOO)
    |     ^^^^^^^^^^^^^^^^^^^^ expected `(T, i8)`, got `(T, <U as Bar>::Blub)`
    |
 note: previous use here
-  --> $DIR/not_a_defining_use.rs:10:5
+  --> $DIR/not_a_defining_use.rs:11:5
    |
 LL |     (t, 5i8)
    |     ^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/not_well_formed.rs b/tests/ui/type-alias-impl-trait/not_well_formed.rs
index 0cf8d41c7fd..bd4477dbf0f 100644
--- a/tests/ui/type-alias-impl-trait/not_well_formed.rs
+++ b/tests/ui/type-alias-impl-trait/not_well_formed.rs
@@ -16,6 +16,7 @@ trait Trait<U> {}
 
 impl<W> Trait<W> for () {}
 
+#[define_opaque(Foo)]
 fn foo_desugared<T: TraitWithAssoc>(_: T) -> Foo<T> {
     ()
 }
diff --git a/tests/ui/type-alias-impl-trait/obligation_ice.rs b/tests/ui/type-alias-impl-trait/obligation_ice.rs
index e3698b23be8..134255e1eb2 100644
--- a/tests/ui/type-alias-impl-trait/obligation_ice.rs
+++ b/tests/ui/type-alias-impl-trait/obligation_ice.rs
@@ -8,6 +8,7 @@ trait Trait<'a, 'b: 'a> {}
 impl<'a, 'b: 'a, T> Trait<'a, 'b> for std::iter::Cloned<T> {}
 
 type I<'a, 'b: 'a, A: Trait<'a, 'b>> = Chain<A, impl Iterator<Item = &'static str>>;
+#[define_opaque(I)]
 fn test2<'a, 'b, A: Trait<'a, 'b> + Iterator<Item = &'static str>>(x: A) -> I<'a, 'b, A> {
     x.chain(once("5"))
 }
diff --git a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
index 2c6f44d5416..b1711e9eab8 100644
--- a/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
+++ b/tests/ui/type-alias-impl-trait/outlives-bound-var.rs
@@ -5,11 +5,9 @@
 //@ check-pass
 #![feature(type_alias_impl_trait)]
 
-mod tait {
-    pub type Ty<'a> = impl Sized + 'a;
-    fn define<'a>() -> Ty<'a> {}
-}
-use tait::Ty;
+pub type Ty<'a> = impl Sized + 'a;
+#[define_opaque(Ty)]
+fn define<'a>() -> Ty<'a> {}
 
 // Ty<'^0>: 'static
 fn test1(_: &'static fn(Ty<'_>)) {}
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch.rs b/tests/ui/type-alias-impl-trait/param_mismatch.rs
index c7465030713..4e4e06acfd4 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch.rs
@@ -8,6 +8,7 @@ fn id(s: &str) -> &str {
 }
 type Opaque<'a> = impl Sized + 'a;
 // The second `Opaque<'_>` has a higher kinded lifetime, not a generic parameter
+#[define_opaque(Opaque)]
 fn test(s: &str) -> (Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
     (s, id)
     //~^ ERROR: expected generic lifetime parameter, found `'_`
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch.stderr b/tests/ui/type-alias-impl-trait/param_mismatch.stderr
index 09ec550d718..07a8ce38f98 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/param_mismatch.rs:12:5
+  --> $DIR/param_mismatch.rs:13:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch2.rs b/tests/ui/type-alias-impl-trait/param_mismatch2.rs
index c7d5eaa16aa..f6a99711411 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch2.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch2.rs
@@ -9,6 +9,7 @@ fn id(s: &str) -> &str {
 
 type Opaque<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque)]
 fn test(s: &str) -> (impl Fn(&str) -> Opaque<'_>, impl Fn(&str) -> Opaque<'_>) {
     (id, id) //~ ERROR: expected generic lifetime parameter, found `'_`
 }
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch2.stderr b/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
index 1ecdd7c2b54..f5ecade2f02 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch2.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/param_mismatch2.rs:13:5
+  --> $DIR/param_mismatch2.rs:14:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch3.rs b/tests/ui/type-alias-impl-trait/param_mismatch3.rs
index 03c133d5d3c..17b6f8bce2a 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch3.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch3.rs
@@ -9,6 +9,7 @@ fn id2<'a, 'b>(s: (&'a str, &'b str)) -> (&'a str, &'b str) {
 
 type Opaque<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque)]
 fn test() -> impl for<'a, 'b> Fn((&'a str, &'b str)) -> (Opaque<'a>, Opaque<'b>) {
     id2 //~ ERROR expected generic lifetime parameter, found `'a`
 }
@@ -19,6 +20,7 @@ fn id(s: &str) -> &str {
 
 type Opaque2<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque2)]
 fn test2(s: &str) -> (impl Fn(&str) -> Opaque2<'_>, Opaque2<'_>) {
     (id, s) //~ ERROR: expected generic lifetime parameter, found `'_`
 }
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch3.stderr b/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
index b8805f9b7f6..7565bbfc6ff 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch3.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'a`
-  --> $DIR/param_mismatch3.rs:13:5
+  --> $DIR/param_mismatch3.rs:14:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
@@ -8,7 +8,7 @@ LL |     id2
    |     ^^^
 
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/param_mismatch3.rs:23:5
+  --> $DIR/param_mismatch3.rs:25:5
    |
 LL | type Opaque2<'a> = impl Sized + 'a;
    |              -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.rs b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
index e072f3ab8e0..bc32143d0eb 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch4.rs
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.rs
@@ -8,6 +8,7 @@ type Opq<'a> = impl Sized;
 // Two defining uses: Opq<'{empty}> and Opq<'a>.
 // This used to ICE.
 // issue: #122782
+#[define_opaque(Opq)]
 fn build<'a>() -> Opq<'a> {
     let _: Opq<'_> = ();
     //~^ ERROR expected generic lifetime parameter, found `'_`
diff --git a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
index d3fdea25a3d..647637ae32a 100644
--- a/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
+++ b/tests/ui/type-alias-impl-trait/param_mismatch4.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/param_mismatch4.rs:12:12
+  --> $DIR/param_mismatch4.rs:13:12
    |
 LL | type Opq<'a> = impl Sized;
    |          -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/path_resolution_taint.rs b/tests/ui/type-alias-impl-trait/path_resolution_taint.rs
new file mode 100644
index 00000000000..b320e88450b
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/path_resolution_taint.rs
@@ -0,0 +1,16 @@
+//! This test used to ICE #131298
+
+#![feature(type_alias_impl_trait)]
+
+fn dyn_hoops<T>() -> *const dyn Iterator<Item = impl Captures> {
+    //~^ ERROR: cannot find trait `Captures` in this scope
+    loop {}
+}
+
+type Opaque = impl Sized;
+#[define_opaque(Opaque)]
+fn define() -> Opaque {
+    let _: Opaque = dyn_hoops::<u8>();
+}
+
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/path_resolution_taint.stderr b/tests/ui/type-alias-impl-trait/path_resolution_taint.stderr
new file mode 100644
index 00000000000..122c7c1ffbf
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/path_resolution_taint.stderr
@@ -0,0 +1,9 @@
+error[E0405]: cannot find trait `Captures` in this scope
+  --> $DIR/path_resolution_taint.rs:5:54
+   |
+LL | fn dyn_hoops<T>() -> *const dyn Iterator<Item = impl Captures> {
+   |                                                      ^^^^^^^^ not found in this scope
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0405`.
diff --git a/tests/ui/type-alias-impl-trait/privacy.rs b/tests/ui/type-alias-impl-trait/privacy.rs
index a5386bbec0d..4fbb9c7313f 100644
--- a/tests/ui/type-alias-impl-trait/privacy.rs
+++ b/tests/ui/type-alias-impl-trait/privacy.rs
@@ -3,6 +3,7 @@
 #![feature(type_alias_impl_trait)]
 
 type Foo = (impl Sized, u8);
+#[define_opaque(Foo)]
 pub fn foo() -> Foo {
     //~^ WARNING type alias `Foo` is more private than the item `foo`
     (42, 42)
diff --git a/tests/ui/type-alias-impl-trait/privacy.stderr b/tests/ui/type-alias-impl-trait/privacy.stderr
index 50870905c30..eeb49b1a4ac 100644
--- a/tests/ui/type-alias-impl-trait/privacy.stderr
+++ b/tests/ui/type-alias-impl-trait/privacy.stderr
@@ -1,5 +1,5 @@
 warning: type alias `Foo` is more private than the item `foo`
-  --> $DIR/privacy.rs:6:1
+  --> $DIR/privacy.rs:7:1
    |
 LL | pub fn foo() -> Foo {
    | ^^^^^^^^^^^^^^^^^^^ function `foo` is reachable at visibility `pub`
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
index 3d1759097d6..cfd7e1bf382 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.rs
@@ -3,10 +3,12 @@
 
 pub type Diff = impl Fn(usize) -> usize;
 
+#[define_opaque(Diff)]
 pub fn lift() -> Diff {
     |_: usize |loop {}
 }
 
+#[define_opaque(Diff)]
 pub fn add(
     n: Diff,
     m: Diff,
diff --git a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
index e8925b9b489..1a8ab219404 100644
--- a/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-fn-tait.stderr
@@ -1,11 +1,11 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-fn-tait.rs:14:5
+  --> $DIR/recursive-fn-tait.rs:16:5
    |
 LL |     move |x: usize| m(n(x))
-   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:7:5: 7:16}`, got `{closure@$DIR/recursive-fn-tait.rs:14:5: 14:20}`
+   |     ^^^^^^^^^^^^^^^^^^^^^^^ expected `{closure@$DIR/recursive-fn-tait.rs:8:5: 8:16}`, got `{closure@$DIR/recursive-fn-tait.rs:16:5: 16:20}`
    |
 note: previous use here
-  --> $DIR/recursive-fn-tait.rs:7:5
+  --> $DIR/recursive-fn-tait.rs:8:5
    |
 LL |     |_: usize |loop {}
    |     ^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
index 10588398c9d..26ffd5c16a2 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.rs
@@ -3,11 +3,15 @@
 #![feature(type_alias_impl_trait)]
 
 type Op = impl std::fmt::Display;
-fn foo() -> Op { &"hello world" }
+#[define_opaque(Op)]
+fn foo() -> Op {
+    &"hello world"
+}
 
 fn transform<S>() -> impl std::fmt::Display {
     &0usize
 }
+#[define_opaque(Op)]
 fn bad() -> Op {
     transform::<Op>()
     //~^ ERROR concrete type differs from previous defining opaque type use
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
index eec35548c55..259f3b2b9f3 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn-2.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-tait-conflicting-defn-2.rs:12:5
+  --> $DIR/recursive-tait-conflicting-defn-2.rs:16:5
    |
 LL |     transform::<Op>()
    |     ^^^^^^^^^^^^^^^^^ expected `&'static &'static str`, got `impl std::fmt::Display`
    |
 note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn-2.rs:6:18
+  --> $DIR/recursive-tait-conflicting-defn-2.rs:8:5
    |
-LL | fn foo() -> Op { &"hello world" }
-   |                  ^^^^^^^^^^^^^^
+LL |     &"hello world"
+   |     ^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
index 38fb493b498..c9e2773905d 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.rs
@@ -14,24 +14,23 @@ struct B<T> {
 
 impl<T: Test> Test for B<T> {}
 
-mod helper {
-    use super::*;
-    pub type TestImpl = impl Test;
+pub type TestImpl = impl Test;
 
-    pub fn test() -> TestImpl {
-        A
-    }
+#[define_opaque(TestImpl)]
+pub fn test() -> TestImpl {
+    A
+}
 
-    fn make_option2() -> Option<TestImpl> {
-        let inner = make_option().unwrap();
+#[define_opaque(TestImpl)]
+fn make_option2() -> Option<TestImpl> {
+    let inner = make_option().unwrap();
 
-        Some(B { inner })
-        //~^ ERROR concrete type differs from previous defining opaque type use
-    }
+    Some(B { inner })
+    //~^ ERROR concrete type differs from previous defining opaque type use
 }
 
-fn make_option() -> Option<helper::TestImpl> {
-    Some(helper::test())
+fn make_option() -> Option<TestImpl> {
+    Some(test())
 }
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
index 252c5d7dfa7..47471c9728c 100644
--- a/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
+++ b/tests/ui/type-alias-impl-trait/recursive-tait-conflicting-defn.stderr
@@ -1,14 +1,14 @@
 error: concrete type differs from previous defining opaque type use
-  --> $DIR/recursive-tait-conflicting-defn.rs:28:9
+  --> $DIR/recursive-tait-conflicting-defn.rs:28:5
    |
-LL |         Some(B { inner })
-   |         ^^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
+LL |     Some(B { inner })
+   |     ^^^^^^^^^^^^^^^^^ expected `A`, got `B<TestImpl>`
    |
 note: previous use here
-  --> $DIR/recursive-tait-conflicting-defn.rs:22:9
+  --> $DIR/recursive-tait-conflicting-defn.rs:21:5
    |
-LL |         A
-   |         ^
+LL |     A
+   |     ^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.rs b/tests/ui/type-alias-impl-trait/reveal_local.rs
index 34f3788e234..1e1e118937b 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.rs
+++ b/tests/ui/type-alias-impl-trait/reveal_local.rs
@@ -7,12 +7,13 @@ type Foo = impl Debug;
 fn is_send<T: Send>() {}
 
 fn not_good() {
-    // Error: this function does not constrain `Foo` to any particular
-    // hidden type, so it cannot rely on `Send` being true.
+    // This function does not define `Foo`,
+    // so it can actually check auto traits on the hidden type without
+    // risking cycle errors.
     is_send::<Foo>();
-    //~^ ERROR: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
 }
 
+#[define_opaque(Foo)]
 fn not_gooder() -> Foo {
     // Constrain `Foo = u32`
     let x: Foo = 22_u32;
diff --git a/tests/ui/type-alias-impl-trait/reveal_local.stderr b/tests/ui/type-alias-impl-trait/reveal_local.stderr
index 9829c58cf73..bd082888591 100644
--- a/tests/ui/type-alias-impl-trait/reveal_local.stderr
+++ b/tests/ui/type-alias-impl-trait/reveal_local.stderr
@@ -1,23 +1,5 @@
-error: cannot check whether the hidden type of `reveal_local[9507]::Foo::{opaque#0}` satisfies auto traits
-  --> $DIR/reveal_local.rs:12:15
-   |
-LL |     is_send::<Foo>();
-   |               ^^^
-   |
-   = note: fetching the hidden types of an opaque inside of the defining scope is not supported. You can try moving the opaque type and the item that actually registers a hidden type into a new submodule
-note: opaque type is declared here
-  --> $DIR/reveal_local.rs:5:12
-   |
-LL | type Foo = impl Debug;
-   |            ^^^^^^^^^^
-note: required by a bound in `is_send`
-  --> $DIR/reveal_local.rs:7:15
-   |
-LL | fn is_send<T: Send>() {}
-   |               ^^^^ required by this bound in `is_send`
-
 error[E0283]: type annotations needed: cannot satisfy `Foo: Send`
-  --> $DIR/reveal_local.rs:22:15
+  --> $DIR/reveal_local.rs:23:15
    |
 LL |     is_send::<Foo>();
    |               ^^^
@@ -29,6 +11,6 @@ note: required by a bound in `is_send`
 LL | fn is_send<T: Send>() {}
    |               ^^^^ required by this bound in `is_send`
 
-error: aborting due to 2 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0283`.
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
index 37d84feee4b..242a4b3cd3e 100644
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
+++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query.rs
@@ -12,19 +12,16 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod helper {
-    pub type Opaque = impl Sized;
+pub type Opaque = impl Sized;
 
-    pub fn get_rpit() -> impl Clone {}
+pub fn get_rpit() -> impl Clone {}
 
-    fn test() -> Opaque {
-        super::query(get_rpit);
-        get_rpit()
-    }
+#[define_opaque(Opaque)]
+fn test() -> Opaque {
+    query(get_rpit);
+    get_rpit()
 }
 
-use helper::*;
-
 fn query(_: impl FnOnce() -> Opaque) {}
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs
index 80f1b1502d3..dc489c0d6fb 100644
--- a/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs
+++ b/tests/ui/type-alias-impl-trait/rpit_tait_equality_in_canonical_query_2.rs
@@ -5,16 +5,14 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod helper {
-    pub type Opaque = impl Sized;
+pub type Opaque = impl Sized;
 
-    pub fn get_rpit() -> impl Sized {}
+pub fn get_rpit() -> impl Sized {}
 
-    fn test(_: Opaque) {
-        super::query(get_rpit);
-    }
+#[define_opaque(Opaque)]
+fn test() {
+    query(get_rpit);
 }
-use helper::*;
 
 fn query(_: impl FnOnce() -> Opaque) {}
 
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
index e4399f2d8f4..dca3ae05bb0 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.current.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `i32` with `Foo`
-  --> $DIR/self-referential-2.rs:10:13
+  --> $DIR/self-referential-2.rs:11:13
    |
 LL | fn bar() -> Bar {
    |             ^^^ no implementation for `i32 == Foo`
diff --git a/tests/ui/type-alias-impl-trait/self-referential-2.rs b/tests/ui/type-alias-impl-trait/self-referential-2.rs
index f96364ccfcd..d3effe817b8 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-2.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-2.rs
@@ -7,6 +7,7 @@
 type Foo = impl std::fmt::Debug;
 type Bar = impl PartialEq<Foo>;
 
+#[define_opaque(Bar)]
 fn bar() -> Bar {
     42_i32 //[current]~^ ERROR can't compare `i32` with `Foo`
 }
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.rs b/tests/ui/type-alias-impl-trait/self-referential-3.rs
index 18f09b54867..b5562532893 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-3.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.rs
@@ -2,6 +2,7 @@
 
 type Bar<'a, 'b> = impl PartialEq<Bar<'a, 'b>> + std::fmt::Debug;
 
+#[define_opaque(Bar)]
 fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
     //~^ ERROR can't compare `&i32` with `Bar<'a, 'b>`
     i
diff --git a/tests/ui/type-alias-impl-trait/self-referential-3.stderr b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
index 15ebcdafca6..d0b1d46c29e 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-3.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-3.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `&i32` with `Bar<'a, 'b>`
-  --> $DIR/self-referential-3.rs:5:31
+  --> $DIR/self-referential-3.rs:6:31
    |
 LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == Bar<'a, 'b>`
diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.rs b/tests/ui/type-alias-impl-trait/self-referential-4.rs
index 36742c8ad57..36df087dfcb 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-4.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential-4.rs
@@ -2,18 +2,21 @@
 
 type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'static>> + std::fmt::Debug;
 
+#[define_opaque(Bar)]
 fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
     i //~^ ERROR can't compare `&i32` with `Bar<'b, 'static>`
 }
 
 type Foo<'a, 'b> = impl PartialEq<Foo<'static, 'b>> + std::fmt::Debug;
 
+#[define_opaque(Foo)]
 fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
     i //~^ ERROR can't compare `&i32` with `Foo<'static, 'b>`
 }
 
 type Moo<'a, 'b> = impl PartialEq<Moo<'static, 'a>> + std::fmt::Debug;
 
+#[define_opaque(Moo)]
 fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
     i //~^ ERROR can't compare `&i32` with `Moo<'static, 'a>`
 }
diff --git a/tests/ui/type-alias-impl-trait/self-referential-4.stderr b/tests/ui/type-alias-impl-trait/self-referential-4.stderr
index 98c762e3d38..92534981eb9 100644
--- a/tests/ui/type-alias-impl-trait/self-referential-4.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential-4.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `&i32` with `Bar<'b, 'static>`
-  --> $DIR/self-referential-4.rs:5:31
+  --> $DIR/self-referential-4.rs:6:31
    |
 LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'static>`
@@ -10,7 +10,7 @@ LL |     i
    = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `Foo<'static, 'b>`
-  --> $DIR/self-referential-4.rs:11:31
+  --> $DIR/self-referential-4.rs:13:31
    |
 LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == Foo<'static, 'b>`
@@ -21,7 +21,7 @@ LL |     i
    = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `Moo<'static, 'a>`
-  --> $DIR/self-referential-4.rs:17:31
+  --> $DIR/self-referential-4.rs:20:31
    |
 LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == Moo<'static, 'a>`
diff --git a/tests/ui/type-alias-impl-trait/self-referential.rs b/tests/ui/type-alias-impl-trait/self-referential.rs
index b899b12cc4a..a1d3b275b19 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.rs
+++ b/tests/ui/type-alias-impl-trait/self-referential.rs
@@ -2,6 +2,7 @@
 
 type Bar<'a, 'b> = impl PartialEq<Bar<'b, 'a>> + std::fmt::Debug;
 
+#[define_opaque(Bar)]
 fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
     //~^ ERROR can't compare `&i32` with `Bar<'b, 'a>`
     i
@@ -9,6 +10,7 @@ fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
 
 type Foo<'a, 'b> = (i32, impl PartialEq<Foo<'a, 'b>> + std::fmt::Debug);
 
+#[define_opaque(Foo)]
 fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
     //~^ ERROR can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
     (42, i)
@@ -16,6 +18,7 @@ fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
 
 type Moo<'a, 'b> = (i32, impl PartialEq<Moo<'b, 'a>> + std::fmt::Debug);
 
+#[define_opaque(Moo)]
 fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
     //~^ ERROR can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
     (42, i)
diff --git a/tests/ui/type-alias-impl-trait/self-referential.stderr b/tests/ui/type-alias-impl-trait/self-referential.stderr
index 57d67f69376..4bcf659e8e6 100644
--- a/tests/ui/type-alias-impl-trait/self-referential.stderr
+++ b/tests/ui/type-alias-impl-trait/self-referential.stderr
@@ -1,5 +1,5 @@
 error[E0277]: can't compare `&i32` with `Bar<'b, 'a>`
-  --> $DIR/self-referential.rs:5:31
+  --> $DIR/self-referential.rs:6:31
    |
 LL | fn bar<'a, 'b>(i: &'a i32) -> Bar<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == Bar<'b, 'a>`
@@ -11,7 +11,7 @@ LL |     i
    = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `(i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
-  --> $DIR/self-referential.rs:12:31
+  --> $DIR/self-referential.rs:14:31
    |
 LL | fn foo<'a, 'b>(i: &'a i32) -> Foo<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Foo<'a, 'b>::{opaque#0}<'a, 'b>)`
@@ -23,7 +23,7 @@ LL |     (42, i)
    = help: the trait `PartialEq` is implemented for `i32`
 
 error[E0277]: can't compare `&i32` with `(i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
-  --> $DIR/self-referential.rs:19:31
+  --> $DIR/self-referential.rs:22:31
    |
 LL | fn moo<'a, 'b>(i: &'a i32) -> Moo<'a, 'b> {
    |                               ^^^^^^^^^^^ no implementation for `&i32 == (i32, Moo<'b, 'a>::{opaque#0}<'b, 'a>)`
diff --git a/tests/ui/type-alias-impl-trait/self_implication.rs b/tests/ui/type-alias-impl-trait/self_implication.rs
index 56464af96ed..d7f70159571 100644
--- a/tests/ui/type-alias-impl-trait/self_implication.rs
+++ b/tests/ui/type-alias-impl-trait/self_implication.rs
@@ -20,11 +20,10 @@ struct Foo<'a> {
     x: &'a mut u8,
 }
 // desugared
-mod foo {
-    pub type FooX = impl Sized;
-    impl<'a> super::Foo<'a> {
-        pub fn foo(&self) -> FooX {}
-    }
+pub type FooX = impl Sized;
+impl<'a> Foo<'a> {
+    #[define_opaque(FooX)]
+    pub fn foo(&self) -> FooX {}
 }
 
 fn bar() {
diff --git a/tests/ui/type-alias-impl-trait/static-const-types.rs b/tests/ui/type-alias-impl-trait/static-const-types.rs
deleted file mode 100644
index dad515aaa7b..00000000000
--- a/tests/ui/type-alias-impl-trait/static-const-types.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-#![feature(type_alias_impl_trait)]
-#![allow(dead_code)]
-
-//@ check-pass
-
-use std::fmt::Debug;
-
-type Foo = impl Debug;
-
-static FOO1: Foo = 22_u32;
-const FOO2: Foo = 22_u32;
-
-fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs
index 27f5799c380..a20ae814908 100644
--- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs
+++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.rs
@@ -1,15 +1,15 @@
 #![feature(type_alias_impl_trait)]
 
-mod bar {
-    pub type Bar = impl Send;
+pub type Bar = impl Send;
 
-    // While i32 is structural-match, we do not want to leak this information.
-    // (See https://github.com/rust-lang/rust/issues/72156)
-    pub const fn leak_free() -> Bar {
-        7i32
-    }
+// While i32 is structural-match, we do not want to leak this information.
+// (See https://github.com/rust-lang/rust/issues/72156)
+#[define_opaque(Bar)]
+pub const fn leak_free() -> Bar {
+    7i32
 }
-const LEAK_FREE: bar::Bar = bar::leak_free();
+
+const LEAK_FREE: Bar = leak_free();
 
 fn leak_free_test() {
     match LEAK_FREE {
diff --git a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
index 28f5d6728a9..5067d78d169 100644
--- a/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
+++ b/tests/ui/type-alias-impl-trait/structural-match-no-leak.stderr
@@ -1,8 +1,8 @@
 error: opaque type `Bar` cannot be used in patterns
   --> $DIR/structural-match-no-leak.rs:16:9
    |
-LL | const LEAK_FREE: bar::Bar = bar::leak_free();
-   | ------------------------- constant defined here
+LL | const LEAK_FREE: Bar = leak_free();
+   | -------------------- constant defined here
 ...
 LL |         LEAK_FREE => (),
    |         ^^^^^^^^^ opaque type can't be used in patterns
diff --git a/tests/ui/type-alias-impl-trait/structural-match.rs b/tests/ui/type-alias-impl-trait/structural-match.rs
index 50259591539..68a95560a46 100644
--- a/tests/ui/type-alias-impl-trait/structural-match.rs
+++ b/tests/ui/type-alias-impl-trait/structural-match.rs
@@ -1,22 +1,21 @@
 #![feature(type_alias_impl_trait)]
 
-mod foo {
-    pub type Foo = impl Send;
+pub type Foo = impl Send;
 
-    // This is not structural-match
-    struct A;
+// This is not structural-match
+struct A;
 
-    pub const fn value() -> Foo {
-        A
-    }
+#[define_opaque(Foo)]
+pub const fn value() -> Foo {
+    A
 }
-use foo::*;
+
 const VALUE: Foo = value();
 
 fn test() {
     match VALUE {
         VALUE => (),
-        //~^ `foo::Foo` cannot be used in patterns
+        //~^ `Foo` cannot be used in patterns
         _ => (),
     }
 }
diff --git a/tests/ui/type-alias-impl-trait/structural-match.stderr b/tests/ui/type-alias-impl-trait/structural-match.stderr
index b06b31a060f..a86b7f42ead 100644
--- a/tests/ui/type-alias-impl-trait/structural-match.stderr
+++ b/tests/ui/type-alias-impl-trait/structural-match.stderr
@@ -1,5 +1,5 @@
-error: opaque type `foo::Foo` cannot be used in patterns
-  --> $DIR/structural-match.rs:18:9
+error: opaque type `Foo` cannot be used in patterns
+  --> $DIR/structural-match.rs:17:9
    |
 LL | const VALUE: Foo = value();
    | ---------------- constant defined here
diff --git a/tests/ui/type-alias-impl-trait/taint.rs b/tests/ui/type-alias-impl-trait/taint.rs
index dfb947637c0..3d67c9bca41 100644
--- a/tests/ui/type-alias-impl-trait/taint.rs
+++ b/tests/ui/type-alias-impl-trait/taint.rs
@@ -9,6 +9,7 @@ fn set(x: &mut isize) -> isize {
     *x
 }
 
+#[define_opaque(Two)]
 fn d(x: Two) {
     let c1 = || set(x); //~ ERROR: expected generic lifetime parameter, found `'_`
     c1;
diff --git a/tests/ui/type-alias-impl-trait/taint.stderr b/tests/ui/type-alias-impl-trait/taint.stderr
index 17fcd4b7e93..e2e34a5d1ba 100644
--- a/tests/ui/type-alias-impl-trait/taint.stderr
+++ b/tests/ui/type-alias-impl-trait/taint.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/taint.rs:13:17
+  --> $DIR/taint.rs:14:17
    |
 LL | type Two<'a, 'b> = impl std::fmt::Debug;
    |          -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs
index 109a70c766d..ab33e9e794e 100644
--- a/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs
+++ b/tests/ui/type-alias-impl-trait/tait-in-function-return-type-issue-101903-fixed.rs
@@ -19,6 +19,7 @@ type Sendable = impl Send + Duh;
 
 type Foo = impl Trait<Assoc = Sendable>;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     || 42
 }
diff --git a/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs b/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs
index be743e8e270..488c581247d 100644
--- a/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs
+++ b/tests/ui/type-alias-impl-trait/tait-param-inference-issue-117310.rs
@@ -10,9 +10,11 @@ impl<A, B> Trait for (A, B, u8) where A: Deref, B: Deref<Target = A::Target>, {}
 impl<A, B> Trait for (A, B, i8) {}
 
 type TaitSized = impl Sized;
+#[define_opaque(TaitSized)]
 fn def_tait1() -> TaitSized {}
 
 type TaitCopy = impl Copy;
+#[define_opaque(TaitCopy)]
 fn def_tait2() -> TaitCopy {}
 
 fn impl_trait<T: Trait> () {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs
index 66a6c0a35b5..af787d66cc1 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-dyn.rs
@@ -5,6 +5,7 @@
 
 type Foo = Box<dyn Iterator<Item = impl Send>>;
 
+#[define_opaque(Foo)]
 fn make_foo() -> Foo {
     Box::new(vec![1, 2, 3].into_iter())
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs
index e46d2bd559c..921dc17593d 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-assoc-impl-trait.rs
@@ -5,6 +5,7 @@
 
 type Foo = impl Iterator<Item = impl Send>;
 
+#[define_opaque(Foo)]
 fn make_foo() -> Foo {
     vec![1, 2].into_iter()
 }
@@ -12,6 +13,7 @@ fn make_foo() -> Foo {
 type Bar = impl Send;
 type Baz = impl Iterator<Item = Bar>;
 
+#[define_opaque(Baz)]
 fn make_baz() -> Baz {
     vec!["1", "2"].into_iter()
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
index 6b37552fed1..b5533eeecba 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.rs
@@ -1,11 +1,19 @@
 #![feature(type_alias_impl_trait)]
-//@ check-pass
-// Ensures that `const` items can constrain an opaque `impl Trait`.
+// Ensures that `const` items can not constrain an opaque `impl Trait`.
 
 use std::fmt::Debug;
 
 pub type Foo = impl Debug;
+//~^ ERROR unconstrained opaque type
 
+#[define_opaque(Foo)]
+//~^ ERROR only functions and methods can define opaque types
 const _FOO: Foo = 5;
+//~^ ERROR mismatched types
+
+#[define_opaque(Foo)]
+//~^ ERROR only functions and methods can define opaque types
+static _BAR: Foo = 22_u32;
+//~^ ERROR mismatched types
 
 fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
new file mode 100644
index 00000000000..dc15da665f3
--- /dev/null
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-const.stderr
@@ -0,0 +1,57 @@
+error: only functions and methods can define opaque types
+  --> $DIR/type-alias-impl-trait-const.rs:9:1
+   |
+LL | #[define_opaque(Foo)]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: only functions and methods can define opaque types
+  --> $DIR/type-alias-impl-trait-const.rs:14:1
+   |
+LL | #[define_opaque(Foo)]
+   | ^^^^^^^^^^^^^^^^^^^^^
+
+error: unconstrained opaque type
+  --> $DIR/type-alias-impl-trait-const.rs:6:16
+   |
+LL | pub type Foo = impl Debug;
+   |                ^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same crate
+
+error[E0308]: mismatched types
+  --> $DIR/type-alias-impl-trait-const.rs:11:19
+   |
+LL | pub type Foo = impl Debug;
+   |                ---------- the expected opaque type
+...
+LL | const _FOO: Foo = 5;
+   |                   ^ expected opaque type, found integer
+   |
+   = note: expected opaque type `Foo`
+                     found type `{integer}`
+note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
+  --> $DIR/type-alias-impl-trait-const.rs:11:7
+   |
+LL | const _FOO: Foo = 5;
+   |       ^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/type-alias-impl-trait-const.rs:16:20
+   |
+LL | pub type Foo = impl Debug;
+   |                ---------- the expected opaque type
+...
+LL | static _BAR: Foo = 22_u32;
+   |                    ^^^^^^ expected opaque type, found `u32`
+   |
+   = note: expected opaque type `Foo`
+                     found type `u32`
+note: this item must have a `#[define_opaque(Foo)]` attribute to be able to define hidden types
+  --> $DIR/type-alias-impl-trait-const.rs:16:8
+   |
+LL | static _BAR: Foo = 22_u32;
+   |        ^^^^
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
index cbd91066c49..95d52e1ff96 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.rs
@@ -11,12 +11,14 @@ struct MyStruct {
 
 impl MyTrait for MyStruct {}
 
+#[define_opaque(TE)]
 fn bla() -> TE {
     return MyStruct { v: 1 };
 }
 
+#[define_opaque(TE)]
 fn bla2() -> TE {
-    //~^ ERROR: item does not constrain `TE::{opaque#0}`, but has it in its signature
+    //~^ ERROR: item does not constrain `TE::{opaque#0}`
     bla()
 }
 
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.stderr
index 819bde02183..12aa94386dc 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-fns.stderr
@@ -1,12 +1,12 @@
-error: item does not constrain `TE::{opaque#0}`, but has it in its signature
-  --> $DIR/type-alias-impl-trait-fns.rs:18:4
+error: item does not constrain `TE::{opaque#0}`
+  --> $DIR/type-alias-impl-trait-fns.rs:20:4
    |
 LL | fn bla2() -> TE {
    |    ^^^^
    |
-   = note: consider moving the opaque type's declaration and defining uses into a separate module
-note: this opaque type is in the signature
-  --> $DIR/type-alias-impl-trait-fns.rs:23:11
+   = note: consider removing `#[define_opaque]` or adding an empty `#[define_opaque()]`
+note: this opaque type is supposed to be constrained
+  --> $DIR/type-alias-impl-trait-fns.rs:25:11
    |
 LL | type TE = impl MyTrait;
    |           ^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs
index 188b23732f9..929dec39b2f 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-sized.rs
@@ -3,21 +3,25 @@
 #![feature(type_alias_impl_trait)]
 
 type A = impl Sized;
+#[define_opaque(A)]
 fn f1() -> A {
     0
 }
 
 type B = impl ?Sized;
+#[define_opaque(B)]
 fn f2() -> &'static B {
     &[0]
 }
 
 type C = impl ?Sized + 'static;
+#[define_opaque(C)]
 fn f3() -> &'static C {
     &[0]
 }
 
 type D = impl ?Sized;
+#[define_opaque(D)]
 fn f4() -> &'static D {
     &1
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs
index 1340a4214ee..3fcb40df832 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-struct.rs
@@ -5,6 +5,7 @@
 
 type Foo = Vec<impl Send>;
 
+#[define_opaque(Foo)]
 fn make_foo() -> Foo {
     vec![true, false]
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
index 8e90f969953..32b39c8823d 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-tuple.rs
@@ -6,20 +6,17 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-mod foo {
-    pub trait MyTrait {}
+pub trait MyTrait {}
 
-    impl MyTrait for bool {}
+impl MyTrait for bool {}
 
-    pub type Foo = impl MyTrait;
+pub type Foo = impl MyTrait;
 
-    pub fn make_foo() -> Foo {
-        true
-    }
+#[define_opaque(Foo)]
+pub fn make_foo() -> Foo {
+    true
 }
 
-use foo::*;
-
 struct Blah {
     my_foo: Foo,
     my_u8: u8,
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
index ee8922b673e..ad96a0eeb87 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-1.stderr
@@ -1,9 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<Foo as FnOnce<()>>::Output == Foo`
-  --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:6:21
+error: unconstrained opaque type
+  --> $DIR/type-alias-impl-trait-with-cycle-error-1.rs:4:12
    |
-LL | fn crash(x: Foo) -> Foo {
-   |                     ^^^
+LL | type Foo = impl Fn() -> Foo;
+   |            ^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
index 3d0f1d30ca2..e5bb8163a81 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-2.stderr
@@ -1,9 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<Foo as Bar<Foo>>::Item == Foo`
-  --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:10:21
+error: unconstrained opaque type
+  --> $DIR/type-alias-impl-trait-with-cycle-error-2.rs:8:12
    |
-LL | fn crash(x: Foo) -> Foo {
-   |                     ^^^
+LL | type Foo = impl Bar<Foo, Item = Foo>;
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
index 675689bac42..157310bf623 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-cycle-error-3.stderr
@@ -1,9 +1,10 @@
-error[E0275]: overflow evaluating the requirement `<Foo<'_> as FnOnce<()>>::Output == Foo<'a>`
-  --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:6:40
+error: unconstrained opaque type
+  --> $DIR/type-alias-impl-trait-with-cycle-error-3.rs:4:16
    |
-LL | fn crash<'a>(_: &'a (), x: Foo<'a>) -> Foo<'a> {
-   |                                        ^^^^^^^
+LL | type Foo<'a> = impl Fn() -> Foo<'a>;
+   |                ^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: `Foo` must be used in combination with a concrete type within the same crate
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs
index 8ca279eec92..115df16bd3e 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.rs
@@ -3,6 +3,7 @@
 type Foo = impl 'static;
 //~^ ERROR: at least one trait must be specified
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     "foo"
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr
index 3f7acd33830..da8fc595f6a 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait-with-no-traits.stderr
@@ -5,7 +5,7 @@ LL | type Foo = impl 'static;
    |            ^^^^^^^^^^^^
 
 error: at least one trait must be specified
-  --> $DIR/type-alias-impl-trait-with-no-traits.rs:10:13
+  --> $DIR/type-alias-impl-trait-with-no-traits.rs:11:13
    |
 LL | fn bar() -> impl 'static {
    |             ^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs
index 0fe653ac471..ff11fb4fcaf 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait.rs
@@ -17,6 +17,7 @@ fn main() {
 // single definition
 type Foo = impl std::fmt::Display;
 
+#[define_opaque(Foo)]
 fn foo() -> Foo {
     "foo"
 }
@@ -24,30 +25,36 @@ fn foo() -> Foo {
 // two definitions
 type Bar = impl std::fmt::Display;
 
+#[define_opaque(Bar)]
 fn bar1() -> Bar {
     "bar1"
 }
 
+#[define_opaque(Bar)]
 fn bar2() -> Bar {
     "bar2"
 }
 
 type MyIter<T> = impl Iterator<Item = T>;
 
+#[define_opaque(MyIter)]
 fn my_iter<T>(t: T) -> MyIter<T> {
     std::iter::once(t)
 }
 
+#[define_opaque(MyIter)]
 fn my_iter2<T>(t: T) -> MyIter<T> {
     std::iter::once(t)
 }
 
 // param names should not have an effect!
+#[define_opaque(MyIter)]
 fn my_iter3<U>(u: U) -> MyIter<U> {
     std::iter::once(u)
 }
 
 // param position should not have an effect!
+#[define_opaque(MyIter)]
 fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
     std::iter::once(v)
 }
@@ -55,6 +62,7 @@ fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
 // param names should not have an effect!
 type MyOtherIter<T> = impl Iterator<Item = T>;
 
+#[define_opaque(MyOtherIter)]
 fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
     std::iter::once(u)
 }
@@ -62,18 +70,18 @@ fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
 trait Trait {}
 type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
 
+#[define_opaque(GenericBound)]
 fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
     t
 }
 
-mod pass_through {
-    pub type Passthrough<T: 'static> = impl Sized + 'static;
+pub type Passthrough<T: 'static> = impl Sized + 'static;
 
-    fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
-        t
-    }
+#[define_opaque(Passthrough)]
+fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
+    t
 }
 
-fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> {
+fn use_passthrough(x: Passthrough<u32>) -> Passthrough<u32> {
     x
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
index 65e2feaf795..e87fda8159b 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-impl-trait2.rs
@@ -14,71 +14,74 @@ fn main() {
     assert_eq!(my_iter(42u8).collect::<Vec<u8>>(), vec![42u8]);
 }
 
-use defining_use_scope::*;
+// single definition
+pub type Foo = impl std::fmt::Display;
 
-mod defining_use_scope {
-    // single definition
-    pub type Foo = impl std::fmt::Display;
-
-    pub fn foo() -> Foo {
-        "foo"
-    }
-
-    // two definitions
-    pub type Bar = impl std::fmt::Display;
+#[define_opaque(Foo)]
+pub fn foo() -> Foo {
+    "foo"
+}
 
-    pub fn bar1() -> Bar {
-        "bar1"
-    }
+// two definitions
+pub type Bar = impl std::fmt::Display;
 
-    pub fn bar2() -> Bar {
-        "bar2"
-    }
+#[define_opaque(Bar)]
+pub fn bar1() -> Bar {
+    "bar1"
+}
 
-    pub type MyIter<T> = impl Iterator<Item = T>;
+#[define_opaque(Bar)]
+pub fn bar2() -> Bar {
+    "bar2"
+}
 
-    pub fn my_iter<T>(t: T) -> MyIter<T> {
-        std::iter::once(t)
-    }
+pub type MyIter<T> = impl Iterator<Item = T>;
 
-    fn my_iter2<T>(t: T) -> MyIter<T> {
-        std::iter::once(t)
-    }
+#[define_opaque(MyIter)]
+pub fn my_iter<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
 
-    // param names should not have an effect!
-    fn my_iter3<U>(u: U) -> MyIter<U> {
-        std::iter::once(u)
-    }
+#[define_opaque(MyIter)]
+fn my_iter2<T>(t: T) -> MyIter<T> {
+    std::iter::once(t)
+}
 
-    // param position should not have an effect!
-    fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
-        std::iter::once(v)
-    }
+// param names should not have an effect!
+#[define_opaque(MyIter)]
+fn my_iter3<U>(u: U) -> MyIter<U> {
+    std::iter::once(u)
+}
 
-    // param names should not have an effect!
-    type MyOtherIter<T> = impl Iterator<Item = T>;
+// param position should not have an effect!
+#[define_opaque(MyIter)]
+fn my_iter4<U, V>(_: U, v: V) -> MyIter<V> {
+    std::iter::once(v)
+}
 
-    fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
-        std::iter::once(u)
-    }
+// param names should not have an effect!
+type MyOtherIter<T> = impl Iterator<Item = T>;
 
-    trait Trait {}
-    type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
+#[define_opaque(MyOtherIter)]
+fn my_other_iter<U>(u: U) -> MyOtherIter<U> {
+    std::iter::once(u)
+}
 
-    fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
-        t
-    }
+trait Trait {}
+type GenericBound<'a, T: Trait + 'a> = impl Sized + 'a;
 
-    mod pass_through {
-        pub type Passthrough<T: 'static> = impl Sized + 'static;
+#[define_opaque(GenericBound)]
+fn generic_bound<'a, T: Trait + 'a>(t: T) -> GenericBound<'a, T> {
+    t
+}
 
-        fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
-            t
-        }
-    }
+pub type Passthrough<T: 'static> = impl Sized + 'static;
 
-    fn use_passthrough(x: pass_through::Passthrough<u32>) -> pass_through::Passthrough<u32> {
-        x
-    }
+#[define_opaque(Passthrough)]
+fn define_passthrough<T: 'static>(t: T) -> Passthrough<T> {
+    t
+}
 
+fn use_passthrough(x: Passthrough<u32>) -> Passthrough<u32> {
+    x
 }
diff --git a/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
index af575a4ff36..20209c7b28c 100644
--- a/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
+++ b/tests/ui/type-alias-impl-trait/type-alias-nested-impl-trait.rs
@@ -2,9 +2,10 @@
 
 #![feature(type_alias_impl_trait)]
 
-use std::iter::{once, Chain};
+use std::iter::{Chain, once};
 
 type I<A> = Chain<A, impl Iterator<Item = &'static str>>;
+#[define_opaque(I)]
 fn test2<A: Iterator<Item = &'static str>>(x: A) -> I<A> {
     x.chain(once("5"))
 }
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
index 7cf2fe42da8..d4a2c23f7a7 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.current.stderr
@@ -1,5 +1,5 @@
 error[E0382]: use of moved value: `x`
-  --> $DIR/type_of_a_let.rs:21:16
+  --> $DIR/type_of_a_let.rs:23:16
    |
 LL |     let x: Foo = 22_u32;
    |         - move occurs because `x` has type `Foo`, which does not implement the `Copy` trait
@@ -9,7 +9,7 @@ LL |     same_type((x, y));
    |                ^ value used here after move
 
 error[E0382]: use of moved value: `y`
-  --> $DIR/type_of_a_let.rs:22:6
+  --> $DIR/type_of_a_let.rs:24:6
    |
 LL |     let y: Foo = x;
    |         - move occurs because `y` has type `Foo`, which does not implement the `Copy` trait
diff --git a/tests/ui/type-alias-impl-trait/type_of_a_let.rs b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
index cc8caf886cf..9479b1084df 100644
--- a/tests/ui/type-alias-impl-trait/type_of_a_let.rs
+++ b/tests/ui/type-alias-impl-trait/type_of_a_let.rs
@@ -10,11 +10,13 @@ use std::fmt::Debug;
 
 type Foo = impl Debug;
 
+#[define_opaque(Foo)]
 fn foo1() -> (u32, Foo) {
     let x: Foo = 22_u32;
     (x, todo!())
 }
 
+#[define_opaque(Foo)]
 fn foo2() -> (u32, Foo) {
     let x: Foo = 22_u32;
     let y: Foo = x;
diff --git a/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs
index 09ff006acbd..063c4deaf06 100644
--- a/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs
+++ b/tests/ui/type-alias-impl-trait/unbounded_opaque_type.rs
@@ -2,12 +2,9 @@
 
 #![feature(type_alias_impl_trait)]
 
-mod opaque {
-    pub type Opaque<T> = impl Sized;
-    fn defining<T>() -> Opaque<T> {}
-}
-
-use opaque::Opaque;
+pub type Opaque<T> = impl Sized;
+#[define_opaque(Opaque)]
+fn defining<T>() -> Opaque<T> {}
 
 struct Ss<'a, T>(&'a Opaque<T>);
 
diff --git a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.rs b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.rs
index ae3d317ab46..3f4d9d244ec 100644
--- a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.rs
+++ b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.rs
@@ -3,6 +3,7 @@
 type Tait = impl Copy;
 // Make sure that this TAIT isn't considered unconstrained...
 
+#[define_opaque(Tait)]
 fn empty_opaque() -> Tait {
     if false {
         match empty_opaque() {}
diff --git a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr
index 5c9a4688105..549e3bc8dc1 100644
--- a/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr
+++ b/tests/ui/type-alias-impl-trait/unconstrained-due-to-bad-pattern.stderr
@@ -1,5 +1,5 @@
 error[E0004]: non-exhaustive patterns: type `Tait` is non-empty
-  --> $DIR/unconstrained-due-to-bad-pattern.rs:8:15
+  --> $DIR/unconstrained-due-to-bad-pattern.rs:9:15
    |
 LL |         match empty_opaque() {}
    |               ^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs
index b3510067047..415021a1808 100644
--- a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs
+++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.rs
@@ -3,6 +3,7 @@
 use std::fmt::Display;
 
 type Opaque<X> = impl Sized + 'static;
+#[define_opaque(Opaque)]
 fn define<X>() -> Opaque<X> {}
 
 trait Trait {
diff --git a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
index 6206f169c5b..7a86685787c 100644
--- a/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
+++ b/tests/ui/type-alias-impl-trait/unconstrained-impl-param.stderr
@@ -1,5 +1,5 @@
 error[E0207]: the lifetime parameter `'a` is not constrained by the impl trait, self type, or predicates
-  --> $DIR/unconstrained-impl-param.rs:11:6
+  --> $DIR/unconstrained-impl-param.rs:12:6
    |
 LL | impl<'a> Trait for Opaque<&'a str> {
    |      ^^ unconstrained lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/under-binder.rs b/tests/ui/type-alias-impl-trait/under-binder.rs
index caf21d64027..bf8635b7d81 100644
--- a/tests/ui/type-alias-impl-trait/under-binder.rs
+++ b/tests/ui/type-alias-impl-trait/under-binder.rs
@@ -2,6 +2,7 @@
 
 type Opaque<'a> = impl Sized + 'a;
 
+#[define_opaque(Opaque)]
 fn test(f: fn(u8)) -> fn(Opaque<'_>) {
     f //~ ERROR E0792
 }
diff --git a/tests/ui/type-alias-impl-trait/under-binder.stderr b/tests/ui/type-alias-impl-trait/under-binder.stderr
index f4a121ce440..0589f9ae11c 100644
--- a/tests/ui/type-alias-impl-trait/under-binder.stderr
+++ b/tests/ui/type-alias-impl-trait/under-binder.stderr
@@ -1,5 +1,5 @@
 error[E0792]: expected generic lifetime parameter, found `'_`
-  --> $DIR/under-binder.rs:6:5
+  --> $DIR/under-binder.rs:7:5
    |
 LL | type Opaque<'a> = impl Sized + 'a;
    |             -- this generic parameter must be used with a generic lifetime parameter
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.rs b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs
index aa537dfc917..dc2d37b9d05 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_generic.rs
+++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.rs
@@ -18,11 +18,10 @@ impl<X: Trait> ProofForConversion<X> for () {
 
 type Converter<T> = impl ProofForConversion<T>;
 
+#[define_opaque(Converter)]
 fn _defining_use<T: Trait>() -> Converter<T> {
     ()
     //~^ ERROR the trait bound `T: Trait` is not satisfied
 }
 
-
-fn main() {
-}
+fn main() {}
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
index e50949ed8f3..e05c3094d53 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_generic.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the trait bound `T: Trait` is not satisfied
-  --> $DIR/underconstrained_generic.rs:22:5
+  --> $DIR/underconstrained_generic.rs:23:5
    |
 LL |     ()
    |     ^^ the trait `Trait` is not implemented for `T`
@@ -17,7 +17,7 @@ note: required by a bound in an opaque type
 LL | type Converter<T> = impl ProofForConversion<T>;
    |                          ^^^^^^^^^^^^^^^^^^^^^
 note: this definition site has more where clauses than the opaque type
-  --> $DIR/underconstrained_generic.rs:21:1
+  --> $DIR/underconstrained_generic.rs:22:1
    |
 LL | fn _defining_use<T: Trait>() -> Converter<T> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
index e8e7dd0ea08..f4611f33d23 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
+++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.rs
@@ -15,6 +15,7 @@ impl<'a, 'b> ProofForConversion<'a, 'b> for &'b &'a () {
 type Converter<'a, 'b> = impl ProofForConversion<'a, 'b>;
 
 // Even _defining_use with an explicit `'a: 'b` compiles fine, too.
+#[define_opaque(Converter)]
 fn _defining_use<'a, 'b>(x: &'b &'a ()) -> Converter<'a, 'b> {
     x
     //~^ ERROR reference has a longer lifetime than the data it references
diff --git a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
index 7c07578d887..6a1f2b49397 100644
--- a/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
+++ b/tests/ui/type-alias-impl-trait/underconstrained_lifetime.stderr
@@ -1,5 +1,5 @@
 error[E0491]: in type `&'b &'a ()`, reference has a longer lifetime than the data it references
-  --> $DIR/underconstrained_lifetime.rs:19:5
+  --> $DIR/underconstrained_lifetime.rs:20:5
    |
 LL |     x
    |     ^
diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs
index 56d975355c3..2dab81cba6f 100644
--- a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs
+++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.rs
@@ -5,6 +5,7 @@ mod foo {
     pub trait T {}
 
     pub type Alias<'a> = impl T;
+    //~^ ERROR: unconstrained opaque type
     fn bar() {
         super::with_positive(|&n| ());
         //~^ ERROR mismatched types
diff --git a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr
index 279bd3bca5a..b58eae67120 100644
--- a/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr
+++ b/tests/ui/type-alias-impl-trait/underef-index-out-of-bounds-121472.stderr
@@ -1,9 +1,17 @@
+error: unconstrained opaque type
+  --> $DIR/underef-index-out-of-bounds-121472.rs:7:26
+   |
+LL |     pub type Alias<'a> = impl T;
+   |                          ^^^^^^
+   |
+   = note: `Alias` must be used in combination with a concrete type within the same crate
+
 error[E0308]: mismatched types
-  --> $DIR/underef-index-out-of-bounds-121472.rs:9:31
+  --> $DIR/underef-index-out-of-bounds-121472.rs:10:31
    |
 LL |     pub type Alias<'a> = impl T;
    |                          ------ the expected opaque type
-LL |     fn bar() {
+...
 LL |         super::with_positive(|&n| ());
    |                               ^^
    |                               |
@@ -18,6 +26,6 @@ LL -         super::with_positive(|&n| ());
 LL +         super::with_positive(|n| ());
    |
 
-error: aborting due to 1 previous error
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.rs b/tests/ui/type-alias-impl-trait/unnameable_type.rs
index 5813f529dea..0b97cc2941f 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.rs
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.rs
@@ -16,6 +16,7 @@ use private::Trait;
 // downstream
 type MyPrivate = impl Sized;
 impl Trait for u32 {
+    #[define_opaque(MyPrivate)]
     fn dont_define_this(private: MyPrivate) {
         //~^ ERROR: incompatible type for trait
         let _: () = private;
diff --git a/tests/ui/type-alias-impl-trait/unnameable_type.stderr b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
index 25dc41df419..6e4e024ce69 100644
--- a/tests/ui/type-alias-impl-trait/unnameable_type.stderr
+++ b/tests/ui/type-alias-impl-trait/unnameable_type.stderr
@@ -1,9 +1,9 @@
 error[E0053]: method `dont_define_this` has an incompatible type for trait
-  --> $DIR/unnameable_type.rs:19:34
+  --> $DIR/unnameable_type.rs:20:34
    |
 LL | type MyPrivate = impl Sized;
    |                  ---------- the found opaque type
-LL | impl Trait for u32 {
+...
 LL |     fn dont_define_this(private: MyPrivate) {
    |                                  ^^^^^^^^^ expected `Private`, found opaque type
    |
diff --git a/tests/ui/type-alias-impl-trait/unused_generic_param.rs b/tests/ui/type-alias-impl-trait/unused_generic_param.rs
index b675bc2e622..556e70d1c96 100644
--- a/tests/ui/type-alias-impl-trait/unused_generic_param.rs
+++ b/tests/ui/type-alias-impl-trait/unused_generic_param.rs
@@ -7,16 +7,19 @@ fn main() {}
 
 type PartiallyDefined<T> = impl Sized;
 
+#[define_opaque(PartiallyDefined)]
 fn partially_defined<T: std::fmt::Debug>(_: T) -> PartiallyDefined<T> {
     4u32
 }
 
 type PartiallyDefined2<T> = impl Sized;
 
+#[define_opaque(PartiallyDefined2)]
 fn partially_defined2<T: std::fmt::Debug>(_: T) -> PartiallyDefined2<T> {
     4u32
 }
 
+#[define_opaque(PartiallyDefined2)]
 fn partially_defined22<T>(_: T) -> PartiallyDefined2<T> {
     4u32
 }
diff --git a/tests/ui/type-alias-impl-trait/variance.rs b/tests/ui/type-alias-impl-trait/variance.rs
index 40e8ec0129a..ecd7158223c 100644
--- a/tests/ui/type-alias-impl-trait/variance.rs
+++ b/tests/ui/type-alias-impl-trait/variance.rs
@@ -72,6 +72,7 @@ type NestedDeeply<'a> =
             >,
         >,
     >;
+#[define_opaque(NestedDeeply)]
 fn test<'a>() -> NestedDeeply<'a> {
     &()
 }
diff --git a/tests/ui/type-alias-impl-trait/variance.stderr b/tests/ui/type-alias-impl-trait/variance.stderr
index 79ce8148f19..138e4080c29 100644
--- a/tests/ui/type-alias-impl-trait/variance.stderr
+++ b/tests/ui/type-alias-impl-trait/variance.stderr
@@ -28,7 +28,7 @@ error: unconstrained opaque type
 LL | type NotCapturedEarly<'a> = impl Sized;
    |                             ^^^^^^^^^^
    |
-   = note: `NotCapturedEarly` must be used in combination with a concrete type within the same module
+   = note: `NotCapturedEarly` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/variance.rs:11:26
@@ -36,7 +36,7 @@ error: unconstrained opaque type
 LL | type CapturedEarly<'a> = impl Sized + Captures<'a>;
    |                          ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `CapturedEarly` must be used in combination with a concrete type within the same module
+   = note: `CapturedEarly` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/variance.rs:14:56
@@ -44,7 +44,7 @@ error: unconstrained opaque type
 LL | type NotCapturedLate<'a> = dyn for<'b> Iterator<Item = impl Sized>;
    |                                                        ^^^^^^^^^^
    |
-   = note: `NotCapturedLate` must be used in combination with a concrete type within the same module
+   = note: `NotCapturedLate` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/variance.rs:18:49
@@ -52,7 +52,7 @@ error: unconstrained opaque type
 LL | type Captured<'a> = dyn for<'b> Iterator<Item = impl Sized + Captures<'a>>;
    |                                                 ^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: `Captured` must be used in combination with a concrete type within the same module
+   = note: `Captured` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/variance.rs:22:27
@@ -60,7 +60,7 @@ error: unconstrained opaque type
 LL | type Bar<'a, 'b: 'b, T> = impl Sized;
    |                           ^^^^^^^^^^
    |
-   = note: `Bar` must be used in combination with a concrete type within the same module
+   = note: `Bar` must be used in combination with a concrete type within the same crate
 
 error: unconstrained opaque type
   --> $DIR/variance.rs:34:32
diff --git a/tests/ui/type-alias-impl-trait/weird-return-types.rs b/tests/ui/type-alias-impl-trait/weird-return-types.rs
index 29d4faa7ba9..05668c836f9 100644
--- a/tests/ui/type-alias-impl-trait/weird-return-types.rs
+++ b/tests/ui/type-alias-impl-trait/weird-return-types.rs
@@ -4,11 +4,12 @@
 #![feature(type_alias_impl_trait)]
 #![allow(dead_code)]
 
-use std::future::Future;
 use std::fmt::Debug;
+use std::future::Future;
 
 type Foo = impl Debug;
 
+#[define_opaque(Foo)]
 fn f() -> impl Future<Output = Foo> {
     async move { 22_u32 }
 }
diff --git a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
index 19dd4c17936..fd5edcc89ee 100644
--- a/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
+++ b/tests/ui/type-alias-impl-trait/wf-check-definition-site.rs
@@ -14,6 +14,7 @@
 struct Static<T: 'static>(T);
 
 type OpaqueRet<'a> = impl Sized + 'a;
+#[define_opaque(OpaqueRet)]
 fn test_return<'a>(msg: Static<&'static u8>) -> OpaqueRet<'a> {
     msg
 }
@@ -23,9 +24,9 @@ fn test_rpit<'a>(msg: Static<&'static u8>) -> impl Sized + 'a {
 }
 
 type OpaqueAssign<'a> = impl Sized + 'a;
-fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
+#[define_opaque(OpaqueAssign)]
+fn test_assign<'a>(msg: Static<&'static u8>) {
     let _: OpaqueAssign<'a> = msg;
-    None
 }
 
 // `OpaqueRef<'a, T> = Ref<'a, T>`, vs
@@ -33,6 +34,7 @@ fn test_assign<'a>(msg: Static<&'static u8>) -> Option<OpaqueAssign<'a>> {
 trait RefAt<'a>: 'a {}
 struct Ref<'a, T: RefAt<'a>>(&'a T);
 type OpaqueRef<'a, T: RefAt<'static>> = impl Sized + 'a;
+#[define_opaque(OpaqueRef)]
 fn test_trait<'a, T: RefAt<'static>>(msg: Ref<'static, T>) -> OpaqueRef<'a, T> {
     msg
 }
diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs
index 449e9fbd0d8..6de2c0ccc37 100644
--- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs
+++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.rs
@@ -6,8 +6,11 @@ trait Bar {
 
 type FooFn<B> = impl FnOnce(B);
 
+#[define_opaque(FooFn)]
 fn foo<B: Bar>() -> FooFn<B> {
-    fn mop<B: Bar>(bar: B) { bar.bar() }
+    fn mop<B: Bar>(bar: B) {
+        bar.bar()
+    }
     mop // NOTE: no function pointer, but function zst item
     //~^ ERROR the trait bound `B: Bar` is not satisfied
 }
diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
index 9046a8a76b8..b52ed3f43f4 100644
--- a/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-check-fn-def.stderr
@@ -1,13 +1,13 @@
 error[E0277]: the trait bound `B: Bar` is not satisfied
-  --> $DIR/wf-check-fn-def.rs:11:5
+  --> $DIR/wf-check-fn-def.rs:14:5
    |
 LL |     mop // NOTE: no function pointer, but function zst item
    |     ^^^ the trait `Bar` is not implemented for `B`
    |
 note: required by a bound in `mop`
-  --> $DIR/wf-check-fn-def.rs:10:15
+  --> $DIR/wf-check-fn-def.rs:11:15
    |
-LL |     fn mop<B: Bar>(bar: B) { bar.bar() }
+LL |     fn mop<B: Bar>(bar: B) {
    |               ^^^ required by this bound in `mop`
 help: consider restricting type parameter `B` with trait `Bar`
    |
diff --git a/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs
index 1484d9fd073..fd9ed533756 100644
--- a/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs
+++ b/tests/ui/type-alias-impl-trait/wf-check-fn-ptrs.rs
@@ -8,8 +8,11 @@ trait Bar {
 
 type FooFn<B> = impl FnOnce(B);
 
+#[define_opaque(FooFn)]
 fn foo<B: Bar>() -> FooFn<B> {
-    fn mop<B: Bar>(bar: B) { bar.bar() }
+    fn mop<B: Bar>(bar: B) {
+        bar.bar()
+    }
     mop as fn(B)
     // function pointers don't have any obligations on them,
     // thus the above compiles. It's obviously unsound to just
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.rs b/tests/ui/type-alias-impl-trait/wf-nested.rs
index 56c524c6db0..074ea8703a4 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.rs
+++ b/tests/ui/type-alias-impl-trait/wf-nested.rs
@@ -19,7 +19,6 @@ impl<T> Trait<&'static T> for () {
     type Out = IsStatic<T>;
 }
 
-
 // We could theoretically allow this (and previously did), as even
 // though the nested opaque is not well-formed, it can only be
 // used by normalizing the projection
@@ -27,6 +26,7 @@ impl<T> Trait<&'static T> for () {
 // Assuming that we check that this projection is well-formed, the wf
 // of the nested opaque is implied.
 type OuterOpaque1<T> = impl Trait<&'static T, Out = impl Sized>;
+#[define_opaque(OuterOpaque1)]
 fn define<T>() -> OuterOpaque1<T> {}
 //~^ ERROR `T` may not live long enough
 
@@ -38,6 +38,7 @@ fn define_rpit<T>() -> impl Trait<&'static T, Out = impl Sized> {}
 // soundness.
 type InnerOpaque<T> = impl Sized;
 type OuterOpaque2<T> = impl Trait<&'static T, Out = InnerOpaque<T>>;
+#[define_opaque(OuterOpaque2)]
 fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
 //~^ ERROR the parameter type `T` may not live long enough
 
diff --git a/tests/ui/type-alias-impl-trait/wf-nested.stderr b/tests/ui/type-alias-impl-trait/wf-nested.stderr
index 6d50e11c5da..d7ac5146c1e 100644
--- a/tests/ui/type-alias-impl-trait/wf-nested.stderr
+++ b/tests/ui/type-alias-impl-trait/wf-nested.stderr
@@ -27,7 +27,7 @@ LL | fn define_rpit<T: 'static>() -> impl Trait<&'static T, Out = impl Sized> {}
    |                 +++++++++
 
 error[E0310]: the parameter type `T` may not live long enough
-  --> $DIR/wf-nested.rs:41:47
+  --> $DIR/wf-nested.rs:42:47
    |
 LL | fn define_nested_rpit<T>() -> OuterOpaque2<T> {}
    |                                               ^^
diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.rs b/tests/ui/type-alias-impl-trait/wf_check_closures.rs
index 2c70696ffcf..c633909f513 100644
--- a/tests/ui/type-alias-impl-trait/wf_check_closures.rs
+++ b/tests/ui/type-alias-impl-trait/wf_check_closures.rs
@@ -6,8 +6,9 @@ trait Bar {
 
 type FooFn<B> = impl FnOnce();
 
+#[define_opaque(FooFn)]
 fn foo<B: Bar>(bar: B) -> FooFn<B> {
-    move || { bar.bar() }
+    move || bar.bar()
     //~^ ERROR the trait bound `B: Bar` is not satisfied
 }
 
diff --git a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
index 4156f0ca96a..57e40445c87 100644
--- a/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
+++ b/tests/ui/type-alias-impl-trait/wf_check_closures.stderr
@@ -1,11 +1,11 @@
 error[E0277]: the trait bound `B: Bar` is not satisfied
-  --> $DIR/wf_check_closures.rs:10:5
+  --> $DIR/wf_check_closures.rs:11:5
    |
-LL |     move || { bar.bar() }
-   |     ^^^^^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
+LL |     move || bar.bar()
+   |     ^^^^^^^^^^^^^^^^^ the trait `Bar` is not implemented for `B`
    |
 note: required by a bound in `foo`
-  --> $DIR/wf_check_closures.rs:9:11
+  --> $DIR/wf_check_closures.rs:10:11
    |
 LL | fn foo<B: Bar>(bar: B) -> FooFn<B> {
    |           ^^^ required by this bound in `foo`
diff --git a/tests/ui/type/pattern_types/literals.rs b/tests/ui/type/pattern_types/literals.rs
new file mode 100644
index 00000000000..97a918645f3
--- /dev/null
+++ b/tests/ui/type/pattern_types/literals.rs
@@ -0,0 +1,136 @@
+//! Check where literals can be used to initialize pattern types and where not.
+
+#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
+#![feature(pattern_type_macro)]
+
+use std::pat::pattern_type;
+
+fn out_of_range() -> pattern_type!(u32 is 1..) {
+    0
+    //~^ mismatched types
+}
+
+fn at_range_start() -> pattern_type!(u32 is 1..) {
+    1
+}
+
+fn in_range() -> pattern_type!(u32 is 1..) {
+    2
+}
+
+fn negative_lit_on_unsigned_ty() -> pattern_type!(u32 is 1..) {
+    -3
+    //~^ ERROR: cannot apply unary operator `-` to type `(u32) is 1..`
+}
+
+fn negative_lit_in_range() -> pattern_type!(i8 is -5..5) {
+    -2
+    //~^ ERROR: cannot apply unary operator `-` to type `(i8) is -5..=4`
+}
+
+fn positive_lit_in_range_of_signed() -> pattern_type!(i8 is -5..5) {
+    2
+}
+
+fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) {
+    -5
+    //~^ mismatched types
+}
+
+fn positive_lit_at_range_end() -> pattern_type!(i8 is -5..5) {
+    4
+}
+
+fn lit_one_beyond_range_end() -> pattern_type!(i8 is -5..5) {
+    5
+    //~^ mismatched types
+}
+
+fn wrong_lit_kind() -> pattern_type!(u32 is 1..) {
+    '3'
+    //~^ mismatched types
+}
+
+fn char_lit_in_range() -> pattern_type!(char is 'a'..'z') {
+    'b'
+    //~^ mismatched types
+}
+
+fn char_lit_out_of_range() -> pattern_type!(char is 'a'..'z') {
+    'A'
+    //~^ mismatched types
+}
+
+fn lit_at_unsigned_range_inclusive_end() -> pattern_type!(u32 is 0..=1) {
+    1
+}
+
+fn single_element_range() -> pattern_type!(u32 is 0..=0) {
+    0
+}
+
+fn lit_oob_single_element_range() -> pattern_type!(u32 is 0..=0) {
+    1
+    //~^ mismatched types
+}
+
+fn lit_oob_single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
+    1
+    //~^ mismatched types
+}
+
+fn single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
+    0
+}
+
+fn empty_range_at_base_type_min() -> pattern_type!(u32 is 0..0) {
+    //~^ evaluation of constant value failed
+    0
+}
+
+fn empty_range_at_base_type_min2() -> pattern_type!(u32 is 0..0) {
+    //~^ evaluation of constant value failed
+    1
+}
+
+fn empty_range() -> pattern_type!(u32 is 1..1) {
+    0
+    //~^ mismatched types
+}
+
+fn empty_range2() -> pattern_type!(u32 is 1..1) {
+    1
+    //~^ mismatched types
+}
+
+fn wraparound_range_at_base_ty_end() -> pattern_type!(u32 is 1..0) {
+    //~^ evaluation of constant value failed
+    1
+}
+
+fn wraparound_range_at_base_ty_end2() -> pattern_type!(u32 is 1..0) {
+    //~^ evaluation of constant value failed
+    0
+}
+
+fn wraparound_range_at_base_ty_end3() -> pattern_type!(u32 is 1..0) {
+    //~^ evaluation of constant value failed
+    2
+}
+
+fn wraparound_range() -> pattern_type!(u32 is 2..1) {
+    1
+    //~^ mismatched types
+}
+
+fn lit_in_wraparound_range() -> pattern_type!(u32 is 2..1) {
+    0
+    //~^ mismatched types
+}
+
+fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) {
+    2
+    //~^ mismatched types
+}
+
+fn main() {}
diff --git a/tests/ui/type/pattern_types/literals.stderr b/tests/ui/type/pattern_types/literals.stderr
new file mode 100644
index 00000000000..5c926742f3c
--- /dev/null
+++ b/tests/ui/type/pattern_types/literals.stderr
@@ -0,0 +1,193 @@
+error[E0080]: evaluation of constant value failed
+  --> $DIR/literals.rs:86:62
+   |
+LL | fn empty_range_at_base_type_min() -> pattern_type!(u32 is 0..0) {
+   |                                                              ^ evaluation panicked: exclusive range end at minimum value of type
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/literals.rs:91:63
+   |
+LL | fn empty_range_at_base_type_min2() -> pattern_type!(u32 is 0..0) {
+   |                                                               ^ evaluation panicked: exclusive range end at minimum value of type
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/literals.rs:106:65
+   |
+LL | fn wraparound_range_at_base_ty_end() -> pattern_type!(u32 is 1..0) {
+   |                                                                 ^ evaluation panicked: exclusive range end at minimum value of type
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/literals.rs:111:66
+   |
+LL | fn wraparound_range_at_base_ty_end2() -> pattern_type!(u32 is 1..0) {
+   |                                                                  ^ evaluation panicked: exclusive range end at minimum value of type
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/literals.rs:116:66
+   |
+LL | fn wraparound_range_at_base_ty_end3() -> pattern_type!(u32 is 1..0) {
+   |                                                                  ^ evaluation panicked: exclusive range end at minimum value of type
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:9:5
+   |
+LL | fn out_of_range() -> pattern_type!(u32 is 1..) {
+   |                      ------------------------- expected `(u32) is 1..` because of return type
+LL |     0
+   |     ^ expected `(u32) is 1..`, found integer
+   |
+   = note: expected pattern type `(u32) is 1..`
+                      found type `{integer}`
+
+error[E0600]: cannot apply unary operator `-` to type `(u32) is 1..`
+  --> $DIR/literals.rs:22:5
+   |
+LL |     -3
+   |     ^^ cannot apply unary operator `-`
+
+error[E0600]: cannot apply unary operator `-` to type `(i8) is -5..=4`
+  --> $DIR/literals.rs:27:5
+   |
+LL |     -2
+   |     ^^ cannot apply unary operator `-`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:36:5
+   |
+LL | fn negative_lit_at_range_start() -> pattern_type!(i8 is -5..5) {
+   |                                     -------------------------- expected `(i8) is -5..=4` because of return type
+LL |     -5
+   |     ^^ expected `(i8) is -5..=4`, found integer
+   |
+   = note: expected pattern type `(i8) is -5..=4`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:45:5
+   |
+LL | fn lit_one_beyond_range_end() -> pattern_type!(i8 is -5..5) {
+   |                                  -------------------------- expected `(i8) is -5..=4` because of return type
+LL |     5
+   |     ^ expected `(i8) is -5..=4`, found integer
+   |
+   = note: expected pattern type `(i8) is -5..=4`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:50:5
+   |
+LL | fn wrong_lit_kind() -> pattern_type!(u32 is 1..) {
+   |                        ------------------------- expected `(u32) is 1..` because of return type
+LL |     '3'
+   |     ^^^ expected `(u32) is 1..`, found `char`
+   |
+   = note: expected pattern type `(u32) is 1..`
+                      found type `char`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:55:5
+   |
+LL | fn char_lit_in_range() -> pattern_type!(char is 'a'..'z') {
+   |                           ------------------------------- expected `(char) is 'a'..='y'` because of return type
+LL |     'b'
+   |     ^^^ expected `(char) is 'a'..='y'`, found `char`
+   |
+   = note: expected pattern type `(char) is 'a'..='y'`
+                      found type `char`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:60:5
+   |
+LL | fn char_lit_out_of_range() -> pattern_type!(char is 'a'..'z') {
+   |                               ------------------------------- expected `(char) is 'a'..='y'` because of return type
+LL |     'A'
+   |     ^^^ expected `(char) is 'a'..='y'`, found `char`
+   |
+   = note: expected pattern type `(char) is 'a'..='y'`
+                      found type `char`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:73:5
+   |
+LL | fn lit_oob_single_element_range() -> pattern_type!(u32 is 0..=0) {
+   |                                      --------------------------- expected `(u32) is 0..=0` because of return type
+LL |     1
+   |     ^ expected `(u32) is 0..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 0..=0`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:78:5
+   |
+LL | fn lit_oob_single_element_range_exclusive() -> pattern_type!(u32 is 0..1) {
+   |                                                -------------------------- expected `(u32) is 0..=0` because of return type
+LL |     1
+   |     ^ expected `(u32) is 0..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 0..=0`
+                      found type `{integer}`
+
+error: pattern type ranges cannot wrap: 1..=0
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:97:5
+   |
+LL | fn empty_range() -> pattern_type!(u32 is 1..1) {
+   |                     -------------------------- expected `(u32) is 1..=0` because of return type
+LL |     0
+   |     ^ expected `(u32) is 1..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 1..=0`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:102:5
+   |
+LL | fn empty_range2() -> pattern_type!(u32 is 1..1) {
+   |                      -------------------------- expected `(u32) is 1..=0` because of return type
+LL |     1
+   |     ^ expected `(u32) is 1..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 1..=0`
+                      found type `{integer}`
+
+error: pattern type ranges cannot wrap: 2..=0
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:122:5
+   |
+LL | fn wraparound_range() -> pattern_type!(u32 is 2..1) {
+   |                          -------------------------- expected `(u32) is 2..=0` because of return type
+LL |     1
+   |     ^ expected `(u32) is 2..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 2..=0`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:127:5
+   |
+LL | fn lit_in_wraparound_range() -> pattern_type!(u32 is 2..1) {
+   |                                 -------------------------- expected `(u32) is 2..=0` because of return type
+LL |     0
+   |     ^ expected `(u32) is 2..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 2..=0`
+                      found type `{integer}`
+
+error[E0308]: mismatched types
+  --> $DIR/literals.rs:132:5
+   |
+LL | fn lit_at_wraparound_range_start() -> pattern_type!(u32 is 2..1) {
+   |                                       -------------------------- expected `(u32) is 2..=0` because of return type
+LL |     2
+   |     ^ expected `(u32) is 2..=0`, found integer
+   |
+   = note: expected pattern type `(u32) is 2..=0`
+                      found type `{integer}`
+
+error: aborting due to 22 previous errors
+
+Some errors have detailed explanations: E0080, E0308, E0600.
+For more information about an error, try `rustc --explain E0080`.
diff --git a/tests/ui/type/pattern_types/nested.rs b/tests/ui/type/pattern_types/nested.rs
index 0d8cd22190e..fd950d73291 100644
--- a/tests/ui/type/pattern_types/nested.rs
+++ b/tests/ui/type/pattern_types/nested.rs
@@ -1,6 +1,6 @@
 //! Check that pattern types can only have specific base types
 
-#![feature(pattern_types)]
+#![feature(pattern_types, const_trait_impl, pattern_type_range_trait)]
 #![feature(pattern_type_macro)]
 
 use std::pat::pattern_type;
@@ -14,7 +14,7 @@ const BAD_NESTING: pattern_type!(pattern_type!(u32 is 1..) is 0..) = todo!();
 // We want to get the most narrowest version that a pattern could be
 const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
 //~^ ERROR: not a valid base type for range patterns
-//~| ERROR: mismatched types
+//~| ERROR: cannot apply unary operator `-` to type `(i32) is 1..`
 
 const BAD_NESTING3: pattern_type!(pattern_type!(i32 is 1..) is ..0) = todo!();
 //~^ ERROR: not a valid base type for range patterns
diff --git a/tests/ui/type/pattern_types/nested.stderr b/tests/ui/type/pattern_types/nested.stderr
index f79d12bc3f3..bb206d9db3d 100644
--- a/tests/ui/type/pattern_types/nested.stderr
+++ b/tests/ui/type/pattern_types/nested.stderr
@@ -43,14 +43,11 @@ LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = tod
              u128
            and 5 others
 
-error[E0308]: mismatched types
+error[E0600]: cannot apply unary operator `-` to type `(i32) is 1..`
   --> $DIR/nested.rs:15:67
    |
 LL | const BAD_NESTING2: pattern_type!(pattern_type!(i32 is 1..) is ..=-1) = todo!();
-   |                                                                   ^^ expected `(i32) is 1..`, found integer
-   |
-   = note: expected pattern type `(i32) is 1..`
-                      found type `{integer}`
+   |                                                                   ^^ cannot apply unary operator `-`
 
 error[E0277]: `(i32) is 1..` is not a valid base type for range patterns
   --> $DIR/nested.rs:19:35
@@ -180,5 +177,5 @@ LL | const BAD_NESTING5: pattern_type!(f32 is 1.0 .. 2.0) = todo!();
 
 error: aborting due to 11 previous errors
 
-Some errors have detailed explanations: E0277, E0308.
+Some errors have detailed explanations: E0277, E0308, E0600.
 For more information about an error, try `rustc --explain E0277`.
diff --git a/tests/ui/type/pattern_types/range_patterns.rs b/tests/ui/type/pattern_types/range_patterns.rs
index 446a33195c8..dda7eb0ae4e 100644
--- a/tests/ui/type/pattern_types/range_patterns.rs
+++ b/tests/ui/type/pattern_types/range_patterns.rs
@@ -1,4 +1,4 @@
-#![feature(pattern_types, rustc_attrs)]
+#![feature(pattern_types, rustc_attrs, const_trait_impl, pattern_type_range_trait)]
 #![feature(pattern_type_macro)]
 #![allow(incomplete_features)]
 
@@ -18,6 +18,25 @@ type A = Option<std::num::NonZeroU32>; //~ ERROR layout_of
 #[rustc_layout(debug)]
 struct NonZeroU32New(pattern_type!(u32 is 1..)); //~ ERROR layout_of
 
+#[rustc_layout(debug)]
+type EMPTY = pattern_type!(u32 is 1..1); //~ ERROR unknown layout
+
+#[rustc_layout(debug)]
+type WRAP = pattern_type!(u32 is 1..0); //~ ERROR unknown layout
+//~^ ERROR: evaluation of constant value failed
+
+#[rustc_layout(debug)]
+type WRAP2 = pattern_type!(u32 is 5..2); //~ ERROR unknown layout
+
+#[rustc_layout(debug)]
+type SIGN = pattern_type!(i8 is -10..=10); //~ ERROR layout_of
+
+#[rustc_layout(debug)]
+type MIN = pattern_type!(i8 is -128..=0); //~ ERROR layout_of
+
+#[rustc_layout(debug)]
+type SignedWrap = pattern_type!(i8 is 120..=-120); //~ ERROR unknown layout
+
 fn main() {
     let x: pattern_type!(u32 is 1..) = unsafe { std::mem::transmute(42_u32) };
 }
diff --git a/tests/ui/type/pattern_types/range_patterns.stderr b/tests/ui/type/pattern_types/range_patterns.stderr
index cb24a303404..a05995a33f9 100644
--- a/tests/ui/type/pattern_types/range_patterns.stderr
+++ b/tests/ui/type/pattern_types/range_patterns.stderr
@@ -357,5 +357,120 @@ error: layout_of(NonZeroU32New) = Layout {
 LL | struct NonZeroU32New(pattern_type!(u32 is 1..));
    | ^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: pattern type ranges cannot wrap: 1..=0
 
+error: the type has an unknown layout
+  --> $DIR/range_patterns.rs:22:1
+   |
+LL | type EMPTY = pattern_type!(u32 is 1..1);
+   | ^^^^^^^^^^
+
+error[E0080]: evaluation of constant value failed
+  --> $DIR/range_patterns.rs:25:37
+   |
+LL | type WRAP = pattern_type!(u32 is 1..0);
+   |                                     ^ evaluation panicked: exclusive range end at minimum value of type
+
+error: the type has an unknown layout
+  --> $DIR/range_patterns.rs:25:1
+   |
+LL | type WRAP = pattern_type!(u32 is 1..0);
+   | ^^^^^^^^^
+
+error: pattern type ranges cannot wrap: 5..=1
+
+error: the type has an unknown layout
+  --> $DIR/range_patterns.rs:29:1
+   |
+LL | type WRAP2 = pattern_type!(u32 is 5..2);
+   | ^^^^^^^^^^
+
+error: layout_of((i8) is -10..=10) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $SOME_ALIGN,
+           },
+           backend_repr: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       true,
+                   ),
+                   valid_range: (..=10) | (246..),
+               },
+           ),
+           fields: Primitive,
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       true,
+                   ),
+                   valid_range: (..=10) | (246..),
+               },
+           ),
+           uninhabited: false,
+           variants: Single {
+               index: 0,
+           },
+           max_repr_align: None,
+           unadjusted_abi_align: Align(1 bytes),
+           randomization_seed: $SEED,
+       }
+  --> $DIR/range_patterns.rs:32:1
+   |
+LL | type SIGN = pattern_type!(i8 is -10..=10);
+   | ^^^^^^^^^
+
+error: layout_of((i8) is i8::MIN..=0) = Layout {
+           size: Size(1 bytes),
+           align: AbiAndPrefAlign {
+               abi: Align(1 bytes),
+               pref: $SOME_ALIGN,
+           },
+           backend_repr: Scalar(
+               Initialized {
+                   value: Int(
+                       I8,
+                       true,
+                   ),
+                   valid_range: (..=0) | (128..),
+               },
+           ),
+           fields: Primitive,
+           largest_niche: Some(
+               Niche {
+                   offset: Size(0 bytes),
+                   value: Int(
+                       I8,
+                       true,
+                   ),
+                   valid_range: (..=0) | (128..),
+               },
+           ),
+           uninhabited: false,
+           variants: Single {
+               index: 0,
+           },
+           max_repr_align: None,
+           unadjusted_abi_align: Align(1 bytes),
+           randomization_seed: $SEED,
+       }
+  --> $DIR/range_patterns.rs:35:1
+   |
+LL | type MIN = pattern_type!(i8 is -128..=0);
+   | ^^^^^^^^
+
+error: pattern type ranges cannot wrap: 120..=-120
+
+error: the type has an unknown layout
+  --> $DIR/range_patterns.rs:38:1
+   |
+LL | type SignedWrap = pattern_type!(i8 is 120..=-120);
+   | ^^^^^^^^^^^^^^^
+
+error: aborting due to 15 previous errors
+
+For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.rs b/tests/ui/typeck/typeck_type_placeholder_item.rs
index 9f1bfd7909e..d7351f2e51a 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.rs
+++ b/tests/ui/typeck/typeck_type_placeholder_item.rs
@@ -181,6 +181,7 @@ trait Trait<T> {}
 impl Trait<usize> for Struct {}
 type Y = impl Trait<_>;
 //~^ ERROR the placeholder `_` is not allowed within types on item signatures for type aliases
+#[define_opaque(Y)]
 fn foo() -> Y {
     Struct
 }
diff --git a/tests/ui/typeck/typeck_type_placeholder_item.stderr b/tests/ui/typeck/typeck_type_placeholder_item.stderr
index c5bf9a47e91..2a4a5a62ab4 100644
--- a/tests/ui/typeck/typeck_type_placeholder_item.stderr
+++ b/tests/ui/typeck/typeck_type_placeholder_item.stderr
@@ -29,7 +29,7 @@ LL | struct BadStruct2<_, T>(_, T);
    |                   ^ expected identifier, found reserved identifier
 
 error: associated constant in `impl` without body
-  --> $DIR/typeck_type_placeholder_item.rs:206:5
+  --> $DIR/typeck_type_placeholder_item.rs:207:5
    |
 LL |     const C: _;
    |     ^^^^^^^^^^-
@@ -578,13 +578,13 @@ LL | type Y = impl Trait<_>;
    |                     ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:206:14
+  --> $DIR/typeck_type_placeholder_item.rs:207:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:194:14
+  --> $DIR/typeck_type_placeholder_item.rs:195:14
    |
 LL |     const D: _ = 42;
    |              ^ not allowed in type signatures
@@ -596,13 +596,13 @@ LL +     const D: i32 = 42;
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:209:14
+  --> $DIR/typeck_type_placeholder_item.rs:210:14
    |
 LL |     const D: _ = 42;
    |              ^ not allowed in type signatures
 
 error[E0046]: not all trait items implemented, missing: `F`
-  --> $DIR/typeck_type_placeholder_item.rs:200:1
+  --> $DIR/typeck_type_placeholder_item.rs:201:1
    |
 LL |     type F: std::ops::Fn(_);
    |     ----------------------- `F` from trait
@@ -611,7 +611,7 @@ LL | impl Qux for Struct {
    | ^^^^^^^^^^^^^^^^^^^ missing `F` in implementation
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:217:31
+  --> $DIR/typeck_type_placeholder_item.rs:218:31
    |
 LL | fn value() -> Option<&'static _> {
    |               ----------------^-
@@ -620,7 +620,7 @@ LL | fn value() -> Option<&'static _> {
    |               help: replace with the correct return type: `Option<&'static u8>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:222:17
+  --> $DIR/typeck_type_placeholder_item.rs:223:17
    |
 LL | const _: Option<_> = map(value);
    |                 ^ not allowed in type signatures
@@ -632,7 +632,7 @@ LL + const _: Option<u8> = map(value);
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for return types
-  --> $DIR/typeck_type_placeholder_item.rs:226:31
+  --> $DIR/typeck_type_placeholder_item.rs:227:31
    |
 LL | fn evens_squared(n: usize) -> _ {
    |                               ^
@@ -641,13 +641,13 @@ LL | fn evens_squared(n: usize) -> _ {
    |                               help: replace with an appropriate return type: `impl Iterator<Item = usize>`
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for constants
-  --> $DIR/typeck_type_placeholder_item.rs:231:10
+  --> $DIR/typeck_type_placeholder_item.rs:232:10
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |          ^ not allowed in type signatures
    |
-note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:231:29}>, {closure@typeck_type_placeholder_item.rs:231:49}>` cannot be named
-  --> $DIR/typeck_type_placeholder_item.rs:231:14
+note: however, the inferred type `Map<Filter<Range<i32>, {closure@typeck_type_placeholder_item.rs:232:29}>, {closure@typeck_type_placeholder_item.rs:232:49}>` cannot be named
+  --> $DIR/typeck_type_placeholder_item.rs:232:14
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -695,53 +695,53 @@ LL +         fn fn_test10<T>(&self, _x : T) { }
    |
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:202:14
+  --> $DIR/typeck_type_placeholder_item.rs:203:14
    |
 LL |     type A = _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:204:14
+  --> $DIR/typeck_type_placeholder_item.rs:205:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:190:14
+  --> $DIR/typeck_type_placeholder_item.rs:191:14
    |
 LL |     type B = _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated constants
-  --> $DIR/typeck_type_placeholder_item.rs:192:14
+  --> $DIR/typeck_type_placeholder_item.rs:193:14
    |
 LL |     const C: _;
    |              ^ not allowed in type signatures
 
 error[E0121]: the placeholder `_` is not allowed within types on item signatures for associated types
-  --> $DIR/typeck_type_placeholder_item.rs:197:26
+  --> $DIR/typeck_type_placeholder_item.rs:198:26
    |
 LL |     type F: std::ops::Fn(_);
    |                          ^ not allowed in type signatures
 
 error[E0015]: cannot call non-const function `map::<u8>` in constants
-  --> $DIR/typeck_type_placeholder_item.rs:222:22
+  --> $DIR/typeck_type_placeholder_item.rs:223:22
    |
 LL | const _: Option<_> = map(value);
    |                      ^^^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}>` in constants
-  --> $DIR/typeck_type_placeholder_item.rs:231:22
+error[E0015]: cannot call non-const method `<std::ops::Range<i32> as Iterator>::filter::<{closure@$DIR/typeck_type_placeholder_item.rs:232:29: 232:32}>` in constants
+  --> $DIR/typeck_type_placeholder_item.rs:232:22
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |                      ^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: calls in constants are limited to constant functions, tuple structs and tuple variants
 
-error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:231:29: 231:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:231:49: 231:52}>` in constants
-  --> $DIR/typeck_type_placeholder_item.rs:231:45
+error[E0015]: cannot call non-const method `<Filter<std::ops::Range<i32>, {closure@$DIR/typeck_type_placeholder_item.rs:232:29: 232:32}> as Iterator>::map::<i32, {closure@$DIR/typeck_type_placeholder_item.rs:232:49: 232:52}>` in constants
+  --> $DIR/typeck_type_placeholder_item.rs:232:45
    |
 LL | const _: _ = (1..10).filter(|x| x % 2 == 0).map(|x| x * x);
    |                                             ^^^^^^^^^^^^^^
diff --git a/tests/ui/unpretty/deprecated-attr.rs b/tests/ui/unpretty/deprecated-attr.rs
index 24a32d8a9ac..dda362a595e 100644
--- a/tests/ui/unpretty/deprecated-attr.rs
+++ b/tests/ui/unpretty/deprecated-attr.rs
@@ -1,8 +1,6 @@
 //@ compile-flags: -Zunpretty=hir
 //@ check-pass
 
-// FIXME(jdonszelmann): the pretty printing output for deprecated (and possibly more attrs) is
-// slightly broken.
 #[deprecated]
 pub struct PlainDeprecated;
 
diff --git a/tests/ui/unpretty/deprecated-attr.stdout b/tests/ui/unpretty/deprecated-attr.stdout
index 675351351a0..42de7b4533e 100644
--- a/tests/ui/unpretty/deprecated-attr.stdout
+++ b/tests/ui/unpretty/deprecated-attr.stdout
@@ -5,24 +5,21 @@ extern crate std;
 //@ compile-flags: -Zunpretty=hir
 //@ check-pass
 
-// FIXME(jdonszelmann): the pretty printing output for deprecated (and possibly more attrs) is
-// slightly broken.
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-suggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified}}]
 struct PlainDeprecated;
 
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified, note:
+"here's why this is deprecated"}}]
 struct DirectNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: Unspecifiednote:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: Unspecified, note:
+"here's why this is deprecated"}}]
 struct ExplicitNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: NonStandard(1.2.3)note:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"),
+note: "here's why this is deprecated"}}]
 struct SinceAndNote;
 
-#[attr="Deprecation{deprecation: Deprecation{since: NonStandard(1.2.3)note:
-here's why this is deprecatedsuggestion: }span: }")]
+#[attr = Deprecation {deprecation: Deprecation {since: NonStandard("1.2.3"),
+note: "here's why this is deprecated"}}]
 struct FlippedOrder;
diff --git a/triagebot.toml b/triagebot.toml
index e4231b2966b..84aae8a5179 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -274,7 +274,7 @@ trigger_files = [
 [autolabel."A-rustdoc-search"]
 trigger_files = [
     "src/librustdoc/html/static/js/search.js",
-    "tests/rustdoc-js",
+    "tests/rustdoc-js/",
     "tests/rustdoc-js-std",
 ]
 
@@ -958,6 +958,9 @@ If appropriate, please update `CONFIG_CHANGE_HISTORY` in `src/bootstrap/src/util
 [mentions."src/bootstrap/src/core/build_steps/llvm.rs"]
 message = "This PR changes how LLVM is built. Consider updating src/bootstrap/download-ci-llvm-stamp."
 
+[mentions."src/bootstrap/src/core/build_steps/gcc.rs"]
+message = "This PR changes how GCC is built. Consider updating src/bootstrap/download-ci-gcc-stamp."
+
 [mentions."tests/crashes"]
 message = "This PR changes a file inside `tests/crashes`. If a crash was fixed, please move into the corresponding `ui` subdir and add 'Fixes #<issueNr>' to the PR description to autoclose the issue upon merge."