about summary refs log tree commit diff
path: root/tests
diff options
context:
space:
mode:
authorRalf Jung <post@ralfj.de>2023-12-10 09:03:54 +0100
committerRalf Jung <post@ralfj.de>2023-12-10 09:03:54 +0100
commit035d86594ddcaec12b59c35f8de1a99c3b8b81fb (patch)
tree0a9542f67746bf7a90b8bb4881b56de39b138cb9 /tests
parente8a25b0723b2d4e693881ecd4c1d4c7f8ba8eb51 (diff)
parent43714edb6f291892f571875b42235208f075884f (diff)
downloadrust-035d86594ddcaec12b59c35f8de1a99c3b8b81fb.tar.gz
rust-035d86594ddcaec12b59c35f8de1a99c3b8b81fb.zip
Merge from rustc
Diffstat (limited to 'tests')
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs34
-rw-r--r--tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs32
-rw-r--r--tests/coverage/if_not.cov-map39
-rw-r--r--tests/coverage/if_not.coverage38
-rw-r--r--tests/coverage/if_not.rs37
-rw-r--r--tests/coverage/lazy_boolean.cov-map8
-rw-r--r--tests/coverage/lazy_boolean.coverage2
-rw-r--r--tests/coverage/no_spans.cov-map8
-rw-r--r--tests/coverage/no_spans.coverage30
-rw-r--r--tests/coverage/no_spans.rs29
-rw-r--r--tests/mir-opt/const_prop/address_of_pair.rs15
-rw-r--r--tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir49
-rw-r--r--tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir49
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir36
-rw-r--r--tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir36
-rw-r--r--tests/mir-opt/const_prop/aggregate.rs18
-rw-r--r--tests/mir-opt/const_prop/array_index.rs6
-rw-r--r--tests/mir-opt/const_prop/bad_op_div_by_zero.rs10
-rw-r--r--tests/mir-opt/const_prop/bad_op_mod_by_zero.rs9
-rw-r--r--tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs5
-rw-r--r--tests/mir-opt/const_prop/boolean_identities.rs12
-rw-r--r--tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff32
-rw-r--r--tests/mir-opt/const_prop/boxes.rs6
-rw-r--r--tests/mir-opt/const_prop/cast.rs7
-rw-r--r--tests/mir-opt/const_prop/checked_add.rs5
-rw-r--r--tests/mir-opt/const_prop/const_prop_fails_gracefully.rs12
-rw-r--r--tests/mir-opt/const_prop/discriminant.rs15
-rw-r--r--tests/mir-opt/const_prop/indirect.rs4
-rw-r--r--tests/mir-opt/const_prop/inherit_overflow.rs9
-rw-r--r--tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff11
-rw-r--r--tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff11
-rw-r--r--tests/mir-opt/const_prop/issue_66971.rs4
-rw-r--r--tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff3
-rw-r--r--tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff3
-rw-r--r--tests/mir-opt/const_prop/issue_67019.rs4
-rw-r--r--tests/mir-opt/const_prop/mult_by_zero.rs7
-rw-r--r--tests/mir-opt/const_prop/mutable_variable.rs7
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate.rs7
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs9
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs8
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_no_prop.rs9
-rw-r--r--tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs14
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff (renamed from tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-abort.diff)0
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff (renamed from tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff)0
-rw-r--r--tests/mir-opt/const_prop/pointer_expose_address.rs18
-rw-r--r--tests/mir-opt/const_prop/read_immutable_static.rs4
-rw-r--r--tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff5
-rw-r--r--tests/mir-opt/const_prop/ref_deref.rs8
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff5
-rw-r--r--tests/mir-opt/const_prop/ref_deref_project.rs9
-rw-r--r--tests/mir-opt/const_prop/reify_fn_ptr.rs5
-rw-r--r--tests/mir-opt/const_prop/repeat.rs4
-rw-r--r--tests/mir-opt/const_prop/return_place.rs3
-rw-r--r--tests/mir-opt/const_prop/scalar_literal_propagation.rs4
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff5
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff5
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff5
-rw-r--r--tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff5
-rw-r--r--tests/mir-opt/const_prop/slice_len.rs9
-rw-r--r--tests/mir-opt/const_prop/switch_int.rs9
-rw-r--r--tests/mir-opt/const_prop/tuple_literal_propagation.rs5
-rw-r--r--tests/mir-opt/const_prop/while_let_loops.rs3
-rw-r--r--tests/run-make/jobserver-error/cannot_open_fd.stderr2
-rw-r--r--tests/run-make/jobserver-error/not_a_pipe.stderr2
-rw-r--r--tests/rustdoc-gui/item-info.goml15
-rw-r--r--tests/rustdoc-gui/src/lib2/Cargo.toml7
-rw-r--r--tests/rustdoc-gui/src/lib2/lib.rs9
-rw-r--r--tests/ui-fulldeps/pprust-expr-roundtrip.rs2
-rw-r--r--tests/ui-fulldeps/stable-mir/check_allocation.rs144
-rw-r--r--tests/ui/abi/riscv-discoverability-guidance.rs4
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-ambiguity.rs19
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr38
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-missing.rs13
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-missing.stderr20
-rw-r--r--tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs21
-rw-r--r--tests/ui/associated-consts/assoc-const-ty-mismatch.rs20
-rw-r--r--tests/ui/associated-consts/assoc-const-ty-mismatch.stderr36
-rw-r--r--tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr4
-rw-r--r--tests/ui/associated-consts/shadowed-const.rs2
-rw-r--r--tests/ui/associated-consts/shadowed-const.stderr12
-rw-r--r--tests/ui/associated-type-bounds/consts.rs2
-rw-r--r--tests/ui/associated-type-bounds/consts.stderr12
-rw-r--r--tests/ui/associated-type-bounds/issue-99828.rs2
-rw-r--r--tests/ui/associated-type-bounds/issue-99828.stderr10
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/missing.rs2
-rw-r--r--tests/ui/associated-type-bounds/return-type-notation/missing.stderr5
-rw-r--r--tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr4
-rw-r--r--tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr4
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs2
-rw-r--r--tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr13
-rw-r--r--tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr8
-rw-r--r--tests/ui/box/issue-82446.stderr4
-rw-r--r--tests/ui/check-cfg/compact-values.rs2
-rw-r--r--tests/ui/check-cfg/compact-values.stderr6
-rw-r--r--tests/ui/check-cfg/values-target-json.rs4
-rw-r--r--tests/ui/check-cfg/values-target-json.stderr13
-rw-r--r--tests/ui/check-cfg/well-known-values.rs107
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr240
-rw-r--r--tests/ui/closure-expected-type/expect-fn-supply-fn.stderr12
-rw-r--r--tests/ui/closures/multiple-fn-bounds.stderr4
-rw-r--r--tests/ui/const-generics/assoc_const_eq_diagnostic.rs6
-rw-r--r--tests/ui/const-generics/assoc_const_eq_diagnostic.stderr28
-rw-r--r--tests/ui/consts/precise-drop-with-promoted.rs7
-rw-r--r--tests/ui/consts/precise-drop-with-promoted.stderr6
-rw-r--r--tests/ui/coroutine/async_gen_fn.e2024.stderr12
-rw-r--r--tests/ui/coroutine/async_gen_fn.none.stderr18
-rw-r--r--tests/ui/coroutine/async_gen_fn.rs12
-rw-r--r--tests/ui/coroutine/async_gen_fn.stderr8
-rw-r--r--tests/ui/coroutine/async_gen_fn_iter.rs100
-rw-r--r--tests/ui/error-codes/E0221.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-never_patterns.rs2
-rw-r--r--tests/ui/feature-gates/feature-gate-never_patterns.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr13
-rw-r--r--tests/ui/feature-gates/feature-gate-return_type_notation.rs2
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.rs12
-rw-r--r--tests/ui/fn/fn-pointer-mismatch.stderr16
-rw-r--r--tests/ui/generic-associated-types/issue-88360.stderr4
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.rs2
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions1.stderr4
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.rs2
-rw-r--r--tests/ui/half-open-range-patterns/range_pat_interactions2.stderr4
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr4
-rw-r--r--tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr4
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr4
-rw-r--r--tests/ui/impl-trait/in-trait/specialization-broken.stderr4
-rw-r--r--tests/ui/impl-trait/recursive-type-alias-impl-trait-declaration-too-subtle.stderr8
-rw-r--r--tests/ui/implied-bounds/auxiliary/bevy_ecs.rs18
-rw-r--r--tests/ui/implied-bounds/bevy_world_query.rs11
-rw-r--r--tests/ui/implied-bounds/from-trait-impl.rs24
-rw-r--r--tests/ui/implied-bounds/gluon_salsa.rs31
-rw-r--r--tests/ui/implied-bounds/issue-100690.stderr4
-rw-r--r--tests/ui/implied-bounds/normalization-nested.lifetime.stderr29
-rw-r--r--tests/ui/implied-bounds/normalization-nested.rs4
-rw-r--r--tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr28
-rw-r--r--tests/ui/implied-bounds/normalization-preserve-equality.rs28
-rw-r--r--tests/ui/implied-bounds/sod_service_chain.rs37
-rw-r--r--tests/ui/issues/issue-17905-2.stderr8
-rw-r--r--tests/ui/issues/issue-20225.stderr12
-rw-r--r--tests/ui/issues/issue-24322.stderr4
-rw-r--r--tests/ui/issues/issue-37884.stderr4
-rw-r--r--tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr8
-rw-r--r--tests/ui/lifetimes/issue-79187-2.stderr8
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr4
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr4
-rw-r--r--tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr4
-rw-r--r--tests/ui/macros/issue-118048.rs10
-rw-r--r--tests/ui/macros/issue-118048.stderr21
-rw-r--r--tests/ui/mir/field-projection-mutating-context.stderr4
-rw-r--r--tests/ui/mismatched_types/closure-arg-type-mismatch.stderr4
-rw-r--r--tests/ui/mismatched_types/issue-36053-2.stderr4
-rw-r--r--tests/ui/mismatched_types/normalize-fn-sig.stderr4
-rw-r--r--tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr4
-rw-r--r--tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr8
-rw-r--r--tests/ui/nll/relate_tys/universe-violation.stderr4
-rw-r--r--tests/ui/nll/trait-associated-constant.stderr4
-rw-r--r--tests/ui/or-patterns/inconsistent-modes.stderr4
-rw-r--r--tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs6
-rw-r--r--tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr12
-rw-r--r--tests/ui/parser/issues/issue-24375.rs2
-rw-r--r--tests/ui/parser/issues/issue-24375.stderr4
-rw-r--r--tests/ui/parser/macro/macro-expand-to-match-arm.rs8
-rw-r--r--tests/ui/parser/macro/macro-expand-to-match-arm.stderr18
-rw-r--r--tests/ui/parser/match-arm-without-body.rs79
-rw-r--r--tests/ui/parser/match-arm-without-body.stderr116
-rw-r--r--tests/ui/parser/pat-lt-bracket-1.rs2
-rw-r--r--tests/ui/parser/pat-lt-bracket-1.stderr4
-rw-r--r--tests/ui/pattern/never_patterns.rs30
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr63
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr62
-rw-r--r--tests/ui/pattern/usefulness/empty-match-check-notes.rs52
-rw-r--r--tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr284
-rw-r--r--tests/ui/pattern/usefulness/empty-match.normal.stderr283
-rw-r--r--tests/ui/pattern/usefulness/empty-match.rs178
-rw-r--r--tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr393
-rw-r--r--tests/ui/pattern/usefulness/empty-types.normal.stderr617
-rw-r--r--tests/ui/pattern/usefulness/empty-types.rs665
-rw-r--r--tests/ui/pattern/usefulness/slice_of_empty.rs6
-rw-r--r--tests/ui/pattern/usefulness/slice_of_empty.stderr31
-rw-r--r--tests/ui/privacy/auxiliary/issue-117997.rs35
-rw-r--r--tests/ui/privacy/issue-117997.rs8
-rw-r--r--tests/ui/privacy/private-in-public.rs2
-rw-r--r--tests/ui/privacy/private-in-public.stderr50
-rw-r--r--tests/ui/range/issue-73553-misinterp-range-literal.stderr4
-rw-r--r--tests/ui/regions/issue-101280.stderr4
-rw-r--r--tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr4
-rw-r--r--tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr4
-rw-r--r--tests/ui/regions/regions-lifetime-bounds-on-fns.stderr4
-rw-r--r--tests/ui/resolve/resolve-inconsistent-binding-mode.stderr4
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.rs33
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/check.stderr35
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/parse.rs71
-rw-r--r--tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr44
-rw-r--r--tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs4
-rw-r--r--tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr20
-rw-r--r--tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rsbin594 -> 738 bytes
-rw-r--r--tests/ui/simd/masked-load-store-build-fail.rs74
-rw-r--r--tests/ui/simd/masked-load-store-build-fail.stderr83
-rw-r--r--tests/ui/simd/masked-load-store-check-fail.rs32
-rw-r--r--tests/ui/simd/masked-load-store-check-fail.stderr59
-rw-r--r--tests/ui/simd/masked-load-store.rs33
-rw-r--r--tests/ui/static/static-reference-to-fn-1.stderr4
-rw-r--r--tests/ui/suggestions/as-ref.stderr12
-rw-r--r--tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr4
-rw-r--r--tests/ui/suggestions/method-access-to-range-literal-typo.stderr4
-rw-r--r--tests/ui/suggestions/mut-ref-reassignment.stderr4
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed30
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs30
-rw-r--r--tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr79
-rw-r--r--tests/ui/thir-print/thir-flat-const-variant.stdout61
-rw-r--r--tests/ui/thir-print/thir-flat.stdout13
-rw-r--r--tests/ui/thir-print/thir-tree-match.stdout365
-rw-r--r--tests/ui/thir-print/thir-tree.stdout30
-rw-r--r--tests/ui/traits/impl-method-mismatch.stderr4
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.rs2
-rw-r--r--tests/ui/traits/new-solver/alias-bound-unsound.stderr2
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs8
-rw-r--r--tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr4
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs33
-rw-r--r--tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr16
-rw-r--r--tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs2
-rw-r--r--tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr10
-rw-r--r--tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs3
-rw-r--r--tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs14
-rw-r--r--tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs29
-rw-r--r--tests/ui/traits/new-solver/specialization-transmute.stderr6
-rw-r--r--tests/ui/traits/wrong-mul-method-signature.stderr4
-rw-r--r--tests/ui/type/type-check/point-at-inference-2.stderr8
-rw-r--r--tests/ui/type/type-mismatch.stderr24
-rw-r--r--tests/ui/typeck/bad-index-due-to-nested.stderr8
-rw-r--r--tests/ui/typeck/mismatched-map-under-self.stderr4
-rw-r--r--tests/ui/ufcs/ufcs-explicit-self-bad.rs8
-rw-r--r--tests/ui/ufcs/ufcs-explicit-self-bad.stderr20
-rw-r--r--tests/ui/uninhabited/uninhabited-patterns.rs12
-rw-r--r--tests/ui/uninhabited/uninhabited-patterns.stderr26
-rw-r--r--tests/ui/unsafe/unsafe-trait-impl.rs4
-rw-r--r--tests/ui/unsafe/unsafe-trait-impl.stderr4
-rw-r--r--tests/ui/wf/unnormalized-projection-guides-inference.rs24
239 files changed, 5117 insertions, 1581 deletions
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs
new file mode 100644
index 00000000000..7b1fb320894
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-load.rs
@@ -0,0 +1,34 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec2<T>(pub T, pub T);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+}
+
+// CHECK-LABEL: @load_f32x2
+#[no_mangle]
+pub unsafe fn load_f32x2(mask: Vec2<i32>, pointer: *const f32,
+                         values: Vec2<f32>) -> Vec2<f32> {
+    // CHECK: call <2 x float> @llvm.masked.load.v2f32.p0(ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}}, <2 x float> {{.*}})
+    simd_masked_load(mask, pointer, values)
+}
+
+// CHECK-LABEL: @load_pf32x4
+#[no_mangle]
+pub unsafe fn load_pf32x4(mask: Vec4<i32>, pointer: *const *const f32,
+                          values: Vec4<*const f32>) -> Vec4<*const f32> {
+    // CHECK: call <4 x ptr> @llvm.masked.load.v4p0.p0(ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}}, <4 x ptr> {{.*}})
+    simd_masked_load(mask, pointer, values)
+}
diff --git a/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs
new file mode 100644
index 00000000000..d8a37020f23
--- /dev/null
+++ b/tests/codegen/simd-intrinsic/simd-intrinsic-generic-masked-store.rs
@@ -0,0 +1,32 @@
+// compile-flags: -C no-prepopulate-passes
+
+#![crate_type = "lib"]
+
+#![feature(repr_simd, platform_intrinsics)]
+#![allow(non_camel_case_types)]
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec2<T>(pub T, pub T);
+
+#[repr(simd)]
+#[derive(Copy, Clone, PartialEq, Debug)]
+pub struct Vec4<T>(pub T, pub T, pub T, pub T);
+
+extern "platform-intrinsic" {
+    fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
+}
+
+// CHECK-LABEL: @store_f32x2
+#[no_mangle]
+pub unsafe fn store_f32x2(mask: Vec2<i32>, pointer: *mut f32, values: Vec2<f32>) {
+    // CHECK: call void @llvm.masked.store.v2f32.p0(<2 x float> {{.*}}, ptr {{.*}}, i32 {{.*}}, <2 x i1> {{.*}})
+    simd_masked_store(mask, pointer, values)
+}
+
+// CHECK-LABEL: @store_pf32x4
+#[no_mangle]
+pub unsafe fn store_pf32x4(mask: Vec4<i32>, pointer: *mut *const f32, values: Vec4<*const f32>) {
+    // CHECK: call void @llvm.masked.store.v4p0.p0(<4 x ptr> {{.*}}, ptr {{.*}}, i32 {{.*}}, <4 x i1> {{.*}})
+    simd_masked_store(mask, pointer, values)
+}
diff --git a/tests/coverage/if_not.cov-map b/tests/coverage/if_not.cov-map
new file mode 100644
index 00000000000..fb893e37960
--- /dev/null
+++ b/tests/coverage/if_not.cov-map
@@ -0,0 +1,39 @@
+Function name: if_not::if_not
+Raw bytes (86): 0x[01, 01, 10, 01, 05, 05, 02, 3f, 09, 05, 02, 09, 3a, 3f, 09, 05, 02, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0d, 32, 37, 0d, 09, 3a, 3f, 09, 05, 02, 0a, 01, 04, 01, 03, 0d, 02, 04, 05, 02, 06, 05, 02, 06, 00, 07, 3f, 03, 09, 01, 0d, 3a, 02, 05, 02, 06, 09, 02, 06, 00, 07, 37, 03, 09, 01, 0d, 32, 02, 05, 02, 06, 0d, 02, 0c, 02, 06, 2f, 03, 01, 00, 02]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 16
+- expression 0 operands: lhs = Counter(0), rhs = Counter(1)
+- expression 1 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 2 operands: lhs = Expression(15, Add), rhs = Counter(2)
+- expression 3 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 4 operands: lhs = Counter(2), rhs = Expression(14, Sub)
+- expression 5 operands: lhs = Expression(15, Add), rhs = Counter(2)
+- expression 6 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 7 operands: lhs = Expression(13, Add), rhs = Counter(3)
+- expression 8 operands: lhs = Counter(2), rhs = Expression(14, Sub)
+- expression 9 operands: lhs = Expression(15, Add), rhs = Counter(2)
+- expression 10 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+- expression 11 operands: lhs = Counter(3), rhs = Expression(12, Sub)
+- expression 12 operands: lhs = Expression(13, Add), rhs = Counter(3)
+- expression 13 operands: lhs = Counter(2), rhs = Expression(14, Sub)
+- expression 14 operands: lhs = Expression(15, Add), rhs = Counter(2)
+- expression 15 operands: lhs = Counter(1), rhs = Expression(0, Sub)
+Number of file 0 mappings: 10
+- Code(Counter(0)) at (prev + 4, 1) to (start + 3, 13)
+- Code(Expression(0, Sub)) at (prev + 4, 5) to (start + 2, 6)
+    = (c0 - c1)
+- Code(Counter(1)) at (prev + 2, 6) to (start + 0, 7)
+- Code(Expression(15, Add)) at (prev + 3, 9) to (start + 1, 13)
+    = (c1 + (c0 - c1))
+- Code(Expression(14, Sub)) at (prev + 2, 5) to (start + 2, 6)
+    = ((c1 + (c0 - c1)) - c2)
+- Code(Counter(2)) at (prev + 2, 6) to (start + 0, 7)
+- Code(Expression(13, Add)) at (prev + 3, 9) to (start + 1, 13)
+    = (c2 + ((c1 + (c0 - c1)) - c2))
+- Code(Expression(12, Sub)) at (prev + 2, 5) to (start + 2, 6)
+    = ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)
+- Code(Counter(3)) at (prev + 2, 12) to (start + 2, 6)
+- Code(Expression(11, Add)) at (prev + 3, 1) to (start + 0, 2)
+    = (c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3))
+
diff --git a/tests/coverage/if_not.coverage b/tests/coverage/if_not.coverage
new file mode 100644
index 00000000000..41838b8513f
--- /dev/null
+++ b/tests/coverage/if_not.coverage
@@ -0,0 +1,38 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// edition: 2021
+   LL|       |
+   LL|     12|fn if_not(cond: bool) {
+   LL|     12|    if
+   LL|     12|        !
+   LL|     12|        cond
+   LL|      4|    {
+   LL|      4|        println!("cond was false");
+   LL|      8|    }
+   LL|       |
+   LL|       |    if
+   LL|     12|        !
+   LL|     12|        cond
+   LL|      4|    {
+   LL|      4|        println!("cond was false");
+   LL|      8|    }
+   LL|       |
+   LL|       |    if
+   LL|     12|        !
+   LL|     12|        cond
+   LL|      4|    {
+   LL|      4|        println!("cond was false");
+   LL|      8|    } else {
+   LL|      8|        println!("cond was true");
+   LL|      8|    }
+   LL|     12|}
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    for _ in 0..8 {
+   LL|       |        if_not(std::hint::black_box(true));
+   LL|       |    }
+   LL|       |    for _ in 0..4 {
+   LL|       |        if_not(std::hint::black_box(false));
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/coverage/if_not.rs b/tests/coverage/if_not.rs
new file mode 100644
index 00000000000..4f45ae0b3d4
--- /dev/null
+++ b/tests/coverage/if_not.rs
@@ -0,0 +1,37 @@
+#![feature(coverage_attribute)]
+// edition: 2021
+
+fn if_not(cond: bool) {
+    if
+        !
+        cond
+    {
+        println!("cond was false");
+    }
+
+    if
+        !
+        cond
+    {
+        println!("cond was false");
+    }
+
+    if
+        !
+        cond
+    {
+        println!("cond was false");
+    } else {
+        println!("cond was true");
+    }
+}
+
+#[coverage(off)]
+fn main() {
+    for _ in 0..8 {
+        if_not(std::hint::black_box(true));
+    }
+    for _ in 0..4 {
+        if_not(std::hint::black_box(false));
+    }
+}
diff --git a/tests/coverage/lazy_boolean.cov-map b/tests/coverage/lazy_boolean.cov-map
index 0ad393c40fa..2d1ff24e62d 100644
--- a/tests/coverage/lazy_boolean.cov-map
+++ b/tests/coverage/lazy_boolean.cov-map
@@ -1,5 +1,5 @@
 Function name: lazy_boolean::main
-Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 04, 09, 00, 10, ea, 04, 01, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 09, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02]
+Raw bytes (636): 0x[01, 01, a4, 01, 01, 05, 09, 8a, 05, 8f, 05, 09, 05, 02, 05, 02, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 09, 8a, 05, 8f, 05, 09, 05, 02, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 25, d2, 04, d7, 04, 25, 21, da, 04, df, 04, 21, 1d, e2, 04, e7, 04, 1d, 19, ea, 04, ef, 04, 19, 15, f2, 04, f7, 04, 15, 11, fa, 04, ff, 04, 11, 0d, 82, 05, 87, 05, 0d, 09, 8a, 05, 8f, 05, 09, 05, 02, 1c, 01, 03, 01, 07, 0f, 05, 07, 10, 04, 06, 02, 04, 06, 00, 07, 87, 05, 02, 09, 00, 11, 8f, 05, 02, 0d, 00, 12, 8a, 05, 02, 0d, 00, 12, ff, 04, 03, 09, 00, 11, 87, 05, 02, 0d, 00, 12, 82, 05, 02, 0d, 00, 12, f7, 04, 02, 09, 00, 11, ff, 04, 00, 14, 00, 19, 11, 00, 1d, 00, 22, ef, 04, 01, 09, 00, 11, f7, 04, 00, 14, 00, 19, 15, 00, 1d, 00, 22, ef, 04, 03, 09, 01, 10, ea, 04, 02, 05, 03, 06, 19, 03, 06, 00, 07, e7, 04, 03, 09, 00, 10, 1d, 01, 05, 03, 06, e2, 04, 05, 05, 03, 06, df, 04, 05, 08, 00, 10, da, 04, 00, 11, 02, 06, 21, 02, 06, 00, 07, d7, 04, 02, 08, 00, 0f, 25, 00, 10, 02, 06, d2, 04, 02, 0c, 02, 06, cf, 04, 03, 01, 00, 02]
 Number of files: 1
 - file 0 => global file 1
 Number of expressions: 164
@@ -194,9 +194,9 @@ Number of file 0 mappings: 28
 - Code(Expression(157, Add)) at (prev + 0, 20) to (start + 0, 25)
     = (c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4))
 - Code(Counter(5)) at (prev + 0, 29) to (start + 0, 34)
-- Code(Expression(155, Add)) at (prev + 4, 9) to (start + 0, 16)
+- Code(Expression(155, Add)) at (prev + 3, 9) to (start + 1, 16)
     = (c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5))
-- Code(Expression(154, Sub)) at (prev + 1, 5) to (start + 3, 6)
+- Code(Expression(154, Sub)) at (prev + 2, 5) to (start + 3, 6)
     = ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)
 - Code(Counter(6)) at (prev + 3, 6) to (start + 0, 7)
 - Code(Expression(153, Add)) at (prev + 3, 9) to (start + 0, 16)
@@ -204,7 +204,7 @@ Number of file 0 mappings: 28
 - Code(Counter(7)) at (prev + 1, 5) to (start + 3, 6)
 - Code(Expression(152, Sub)) at (prev + 5, 5) to (start + 3, 6)
     = ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)
-- Code(Expression(151, Add)) at (prev + 5, 9) to (start + 0, 16)
+- Code(Expression(151, Add)) at (prev + 5, 8) to (start + 0, 16)
     = (c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7))
 - Code(Expression(150, Sub)) at (prev + 0, 17) to (start + 2, 6)
     = ((c7 + ((c6 + ((c5 + ((c4 + ((c3 + ((c2 + ((c1 + (c0 - c1)) - c2)) - c3)) - c4)) - c5)) - c6)) - c7)) - c8)
diff --git a/tests/coverage/lazy_boolean.coverage b/tests/coverage/lazy_boolean.coverage
index 8f14082ef68..2d927a08356 100644
--- a/tests/coverage/lazy_boolean.coverage
+++ b/tests/coverage/lazy_boolean.coverage
@@ -32,7 +32,7 @@
                                           ^0
    LL|       |
    LL|       |    if
-   LL|       |        !
+   LL|      1|        !
    LL|      1|        is_true
    LL|      0|    {
    LL|      0|        a = 2
diff --git a/tests/coverage/no_spans.cov-map b/tests/coverage/no_spans.cov-map
new file mode 100644
index 00000000000..9915fc52e6d
--- /dev/null
+++ b/tests/coverage/no_spans.cov-map
@@ -0,0 +1,8 @@
+Function name: no_spans::affected_function::{closure#0}
+Raw bytes (9): 0x[01, 01, 00, 01, 01, 1b, 0c, 00, 0e]
+Number of files: 1
+- file 0 => global file 1
+Number of expressions: 0
+Number of file 0 mappings: 1
+- Code(Counter(0)) at (prev + 27, 12) to (start + 0, 14)
+
diff --git a/tests/coverage/no_spans.coverage b/tests/coverage/no_spans.coverage
new file mode 100644
index 00000000000..e55177698a2
--- /dev/null
+++ b/tests/coverage/no_spans.coverage
@@ -0,0 +1,30 @@
+   LL|       |#![feature(coverage_attribute)]
+   LL|       |// edition: 2021
+   LL|       |
+   LL|       |// If the span extractor can't find any relevant spans for a function, the
+   LL|       |// refinement loop will terminate with nothing in its `prev` slot. If the
+   LL|       |// subsequent code tries to unwrap `prev`, it will panic.
+   LL|       |//
+   LL|       |// This scenario became more likely after #118525 started discarding spans that
+   LL|       |// can't be un-expanded back to within the function body.
+   LL|       |//
+   LL|       |// Regression test for "invalid attempt to unwrap a None some_prev", as seen
+   LL|       |// in issues such as #118643 and #118662.
+   LL|       |
+   LL|       |#[coverage(off)]
+   LL|       |fn main() {
+   LL|       |    affected_function()();
+   LL|       |}
+   LL|       |
+   LL|       |macro_rules! macro_that_defines_a_function {
+   LL|       |    (fn $name:ident () $body:tt) => {
+   LL|       |        fn $name () -> impl Fn() $body
+   LL|       |    }
+   LL|       |}
+   LL|       |
+   LL|       |macro_that_defines_a_function! {
+   LL|       |    fn affected_function() {
+   LL|      1|        || ()
+   LL|       |    }
+   LL|       |}
+
diff --git a/tests/coverage/no_spans.rs b/tests/coverage/no_spans.rs
new file mode 100644
index 00000000000..a5234bc6b60
--- /dev/null
+++ b/tests/coverage/no_spans.rs
@@ -0,0 +1,29 @@
+#![feature(coverage_attribute)]
+// edition: 2021
+
+// If the span extractor can't find any relevant spans for a function, the
+// refinement loop will terminate with nothing in its `prev` slot. If the
+// subsequent code tries to unwrap `prev`, it will panic.
+//
+// This scenario became more likely after #118525 started discarding spans that
+// can't be un-expanded back to within the function body.
+//
+// Regression test for "invalid attempt to unwrap a None some_prev", as seen
+// in issues such as #118643 and #118662.
+
+#[coverage(off)]
+fn main() {
+    affected_function()();
+}
+
+macro_rules! macro_that_defines_a_function {
+    (fn $name:ident () $body:tt) => {
+        fn $name () -> impl Fn() $body
+    }
+}
+
+macro_that_defines_a_function! {
+    fn affected_function() {
+        || ()
+    }
+}
diff --git a/tests/mir-opt/const_prop/address_of_pair.rs b/tests/mir-opt/const_prop/address_of_pair.rs
index 169469a0739..730ebe2ca63 100644
--- a/tests/mir-opt/const_prop/address_of_pair.rs
+++ b/tests/mir-opt/const_prop/address_of_pair.rs
@@ -1,8 +1,21 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 // EMIT_MIR address_of_pair.fn0.ConstProp.diff
 pub fn fn0() -> bool {
+    // CHECK-LABEL: fn fn0(
+    // CHECK: debug pair => [[pair:_.*]];
+    // CHECK: debug ptr => [[ptr:_.*]];
+    // CHECK: debug ret => [[ret:_.*]];
+    // CHECK: (*[[ptr]]) = const true;
+    // CHECK-NOT: = const false;
+    // CHECK-NOT: = const true;
+    // CHECK: [[tmp:_.*]] = ([[pair]].1: bool);
+    // CHECK-NOT: = const false;
+    // CHECK-NOT: = const true;
+    // CHECK: [[ret]] = Not(move [[tmp]]);
+    // CHECK-NOT: = const false;
+    // CHECK-NOT: = const true;
+    // CHECK: _0 = [[ret]];
     let mut pair = (1, false);
     let ptr = core::ptr::addr_of_mut!(pair.1);
     pair = (1, false);
diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir
deleted file mode 100644
index b9c5859cade..00000000000
--- a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-abort.mir
+++ /dev/null
@@ -1,49 +0,0 @@
-// MIR for `foo` after PreCodegen
-
-fn foo(_1: u8) -> () {
-    debug x => _1;
-    let mut _0: ();
-    let _2: i32;
-    let mut _3: i32;
-    let mut _4: (i32, u8);
-    let mut _5: u8;
-    let mut _7: i32;
-    let mut _8: (u8, i32);
-    let mut _9: u8;
-    scope 1 {
-        debug first => _2;
-        let _6: i32;
-        scope 2 {
-            debug second => _6;
-        }
-    }
-
-    bb0: {
-        StorageLive(_2);
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        _5 = _1;
-        _4 = (const 0_i32, move _5);
-        StorageDead(_5);
-        _3 = const 0_i32;
-        _2 = const 1_i32;
-        StorageDead(_3);
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        StorageLive(_8);
-        StorageLive(_9);
-        _9 = _1;
-        _8 = (move _9, const 1_i32);
-        StorageDead(_9);
-        _7 = const 1_i32;
-        _6 = const 3_i32;
-        StorageDead(_7);
-        StorageDead(_8);
-        _0 = const ();
-        StorageDead(_6);
-        StorageDead(_2);
-        return;
-    }
-}
diff --git a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir
deleted file mode 100644
index b9c5859cade..00000000000
--- a/tests/mir-opt/const_prop/aggregate.foo.PreCodegen.after.panic-unwind.mir
+++ /dev/null
@@ -1,49 +0,0 @@
-// MIR for `foo` after PreCodegen
-
-fn foo(_1: u8) -> () {
-    debug x => _1;
-    let mut _0: ();
-    let _2: i32;
-    let mut _3: i32;
-    let mut _4: (i32, u8);
-    let mut _5: u8;
-    let mut _7: i32;
-    let mut _8: (u8, i32);
-    let mut _9: u8;
-    scope 1 {
-        debug first => _2;
-        let _6: i32;
-        scope 2 {
-            debug second => _6;
-        }
-    }
-
-    bb0: {
-        StorageLive(_2);
-        StorageLive(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        _5 = _1;
-        _4 = (const 0_i32, move _5);
-        StorageDead(_5);
-        _3 = const 0_i32;
-        _2 = const 1_i32;
-        StorageDead(_3);
-        StorageDead(_4);
-        StorageLive(_6);
-        StorageLive(_7);
-        StorageLive(_8);
-        StorageLive(_9);
-        _9 = _1;
-        _8 = (move _9, const 1_i32);
-        StorageDead(_9);
-        _7 = const 1_i32;
-        _6 = const 3_i32;
-        StorageDead(_7);
-        StorageDead(_8);
-        _0 = const ();
-        StorageDead(_6);
-        StorageDead(_2);
-        return;
-    }
-}
diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir
deleted file mode 100644
index 44a85a5636b..00000000000
--- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-abort.mir
+++ /dev/null
@@ -1,36 +0,0 @@
-// MIR for `main` after PreCodegen
-
-fn main() -> () {
-    let mut _0: ();
-    let _1: u8;
-    let mut _2: u8;
-    let mut _3: (i32, u8, i32);
-    let _4: ();
-    let mut _5: u8;
-    scope 1 {
-        debug x => _1;
-    }
-
-    bb0: {
-        StorageLive(_1);
-        StorageLive(_2);
-        StorageLive(_3);
-        _3 = (const 0_i32, const 1_u8, const 2_i32);
-        _2 = const 1_u8;
-        _1 = const 1_u8;
-        StorageDead(_2);
-        StorageDead(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        _5 = const 1_u8;
-        _4 = foo(const 1_u8) -> [return: bb1, unwind unreachable];
-    }
-
-    bb1: {
-        StorageDead(_5);
-        StorageDead(_4);
-        _0 = const ();
-        StorageDead(_1);
-        return;
-    }
-}
diff --git a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir b/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir
deleted file mode 100644
index 2c7bdbb5055..00000000000
--- a/tests/mir-opt/const_prop/aggregate.main.PreCodegen.after.panic-unwind.mir
+++ /dev/null
@@ -1,36 +0,0 @@
-// MIR for `main` after PreCodegen
-
-fn main() -> () {
-    let mut _0: ();
-    let _1: u8;
-    let mut _2: u8;
-    let mut _3: (i32, u8, i32);
-    let _4: ();
-    let mut _5: u8;
-    scope 1 {
-        debug x => _1;
-    }
-
-    bb0: {
-        StorageLive(_1);
-        StorageLive(_2);
-        StorageLive(_3);
-        _3 = (const 0_i32, const 1_u8, const 2_i32);
-        _2 = const 1_u8;
-        _1 = const 1_u8;
-        StorageDead(_2);
-        StorageDead(_3);
-        StorageLive(_4);
-        StorageLive(_5);
-        _5 = const 1_u8;
-        _4 = foo(const 1_u8) -> [return: bb1, unwind continue];
-    }
-
-    bb1: {
-        StorageDead(_5);
-        StorageDead(_4);
-        _0 = const ();
-        StorageDead(_1);
-        return;
-    }
-}
diff --git a/tests/mir-opt/const_prop/aggregate.rs b/tests/mir-opt/const_prop/aggregate.rs
index 2e043af08bf..fa716b0843d 100644
--- a/tests/mir-opt/const_prop/aggregate.rs
+++ b/tests/mir-opt/const_prop/aggregate.rs
@@ -1,19 +1,29 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 // compile-flags: -O
 
 // EMIT_MIR aggregate.main.ConstProp.diff
-// EMIT_MIR aggregate.main.PreCodegen.after.mir
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK-NOT: = Add(
+    // CHECK: [[x]] = const 1_u8;
+    // CHECK-NOT: = Add(
+    // CHECK: foo(const 1_u8)
     let x = (0, 1, 2).1 + 0;
     foo(x);
 }
 
+// Verify that we still propagate if part of the aggregate is not known.
 // EMIT_MIR aggregate.foo.ConstProp.diff
-// EMIT_MIR aggregate.foo.PreCodegen.after.mir
 fn foo(x: u8) {
-    // Verify that we still propagate if part of the aggregate is not known.
+    // CHECK-LABEL: fn foo(
+    // CHECK: debug first => [[first:_.*]];
+    // CHECK: debug second => [[second:_.*]];
+    // CHECK-NOT: = Add(
+    // CHECK: [[first]] = const 1_i32;
+    // CHECK-NOT: = Add(
+    // CHECK: [[second]] = const 3_i32;
     let first = (0, x).0 + 1;
     let second = (x, 1).1 + 2;
 }
diff --git a/tests/mir-opt/const_prop/array_index.rs b/tests/mir-opt/const_prop/array_index.rs
index 3bd2321653d..c4c46d78f75 100644
--- a/tests/mir-opt/const_prop/array_index.rs
+++ b/tests/mir-opt/const_prop/array_index.rs
@@ -1,9 +1,11 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR array_index.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: [[x]] = const 2_u32;
     let x: u32 = [0, 1, 2, 3][2];
 }
diff --git a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
index ab41f64a573..0e8765a0771 100644
--- a/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_div_by_zero.rs
@@ -1,9 +1,15 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 // EMIT_MIR bad_op_div_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: debug _z => [[z:_.*]];
+    // CHECK: assert(!const true, "attempt to divide `{}` by zero", const 1_i32)
+    // CHECK: assert(!const false, "attempt to compute `{} / {}`, which would overflow", const 1_i32, const 0_i32)
+    // CHECK: [[z]] = Div(const 1_i32, const 0_i32);
     let y = 0;
     let _z = 1 / y;
 }
diff --git a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
index e747b21cf9b..d895d9e2155 100644
--- a/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
+++ b/tests/mir-opt/const_prop/bad_op_mod_by_zero.rs
@@ -1,9 +1,16 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 // EMIT_MIR bad_op_mod_by_zero.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: debug _z => [[z:_.*]];
+    // CHECK: assert(!const true, "attempt to calculate the remainder of `{}` with a divisor of
+    // zero", const 1_i32)
+    // CHECK: assert(!const false, "attempt to compute the remainder of `{} % {}`, which would overflow", const 1_i32, const 0_i32)
+    // CHECK: [[z]] = Rem(const 1_i32, const 0_i32);
     let y = 0;
     let _z = 1 % y;
 }
diff --git a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
index 38c97a4cf0e..266105c11f2 100644
--- a/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
+++ b/tests/mir-opt/const_prop/bad_op_unsafe_oob_for_slices.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
@@ -6,6 +5,10 @@
 // EMIT_MIR bad_op_unsafe_oob_for_slices.main.ConstProp.diff
 #[allow(unconditional_panic)]
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: debug _b => [[b:_.*]];
+    // CHECK: [[b]] = (*[[a]])[3 of 4];
     let a: *const [_] = &[1, 2, 3];
     unsafe {
         let _b = (*a)[3];
diff --git a/tests/mir-opt/const_prop/boolean_identities.rs b/tests/mir-opt/const_prop/boolean_identities.rs
index 781cce8c7dd..2aa038034d8 100644
--- a/tests/mir-opt/const_prop/boolean_identities.rs
+++ b/tests/mir-opt/const_prop/boolean_identities.rs
@@ -1,10 +1,16 @@
-// skip-filecheck
 // unit-test: ConstProp
-// compile-flags: -O -Zmir-opt-level=4
 
 // EMIT_MIR boolean_identities.test.ConstProp.diff
 pub fn test(x: bool, y: bool) -> bool {
-    (y | true) & (x & false)
+    // CHECK-LABEL: fn test(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: debug b => [[b:_.*]];
+    // CHECK: [[a]] = const true;
+    // CHECK: [[b]] = const false;
+    // CHECK: _0 = const false;
+    let a = (y | true);
+    let b = (x & false);
+    a & b
 }
 
 fn main() {
diff --git a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
index d805341991d..41e1acdff59 100644
--- a/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
+++ b/tests/mir-opt/const_prop/boolean_identities.test.ConstProp.diff
@@ -5,20 +5,42 @@
       debug x => _1;
       debug y => _2;
       let mut _0: bool;
-      let mut _3: bool;
+      let _3: bool;
       let mut _4: bool;
-      let mut _5: bool;
       let mut _6: bool;
+      let mut _7: bool;
+      let mut _8: bool;
+      scope 1 {
+          debug a => _3;
+          let _5: bool;
+          scope 2 {
+              debug b => _5;
+          }
+      }
   
       bb0: {
           StorageLive(_3);
--         _3 = BitOr(_2, const true);
+          StorageLive(_4);
+          _4 = _2;
+-         _3 = BitOr(move _4, const true);
 +         _3 = const true;
+          StorageDead(_4);
           StorageLive(_5);
--         _5 = BitAnd(_1, const false);
--         _0 = BitAnd(move _3, move _5);
+          StorageLive(_6);
+          _6 = _1;
+-         _5 = BitAnd(move _6, const false);
 +         _5 = const false;
+          StorageDead(_6);
+          StorageLive(_7);
+-         _7 = _3;
++         _7 = const true;
+          StorageLive(_8);
+-         _8 = _5;
+-         _0 = BitAnd(move _7, move _8);
++         _8 = const false;
 +         _0 = const false;
+          StorageDead(_8);
+          StorageDead(_7);
           StorageDead(_5);
           StorageDead(_3);
           return;
diff --git a/tests/mir-opt/const_prop/boxes.rs b/tests/mir-opt/const_prop/boxes.rs
index c6807ece199..90a8e33e823 100644
--- a/tests/mir-opt/const_prop/boxes.rs
+++ b/tests/mir-opt/const_prop/boxes.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // unit-test: ConstProp
 // compile-flags: -O
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
@@ -9,6 +8,11 @@
 
 // EMIT_MIR boxes.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: (*{{_.*}}) = const 42_i32;
+    // CHECK: [[tmp:_.*]] = (*{{_.*}});
+    // CHECK: [[x]] = Add(move [[tmp]], const 0_i32);
     let x = *(#[rustc_box]
     Box::new(42))
         + 0;
diff --git a/tests/mir-opt/const_prop/cast.rs b/tests/mir-opt/const_prop/cast.rs
index 3d543badace..b81c2740a73 100644
--- a/tests/mir-opt/const_prop/cast.rs
+++ b/tests/mir-opt/const_prop/cast.rs
@@ -1,9 +1,12 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR cast.main.ConstProp.diff
 
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = const 42_u32;
+    // CHECK: [[y]] = const 42_u8;
     let x = 42u8 as u32;
-
     let y = 42u32 as u8;
 }
diff --git a/tests/mir-opt/const_prop/checked_add.rs b/tests/mir-opt/const_prop/checked_add.rs
index 6a53aced091..571a5cc4e4d 100644
--- a/tests/mir-opt/const_prop/checked_add.rs
+++ b/tests/mir-opt/const_prop/checked_add.rs
@@ -1,9 +1,12 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR checked_add.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: assert(!const false,
+    // CHECK: [[x]] = const 2_u32;
     let x: u32 = 1 + 1;
 }
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs b/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
deleted file mode 100644
index 5bd4731bf08..00000000000
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.rs
+++ /dev/null
@@ -1,12 +0,0 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
-// unit-test: ConstProp
-#[inline(never)]
-fn read(_: usize) { }
-
-// EMIT_MIR const_prop_fails_gracefully.main.ConstProp.diff
-fn main() {
-    const FOO: &i32 = &1;
-    let x = FOO as *const i32 as usize;
-    read(x);
-}
diff --git a/tests/mir-opt/const_prop/discriminant.rs b/tests/mir-opt/const_prop/discriminant.rs
index 11405f38bdc..0ed683d629c 100644
--- a/tests/mir-opt/const_prop/discriminant.rs
+++ b/tests/mir-opt/const_prop/discriminant.rs
@@ -1,6 +1,4 @@
-// skip-filecheck
 // unit-test: ConstProp
-// compile-flags: -O
 
 // FIXME(wesleywiser): Ideally, we could const-prop away all of this and just be left with
 // `let x = 42` but that doesn't work because const-prop doesn't support `Operand::Indirect`
@@ -10,5 +8,18 @@
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 // EMIT_MIR discriminant.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: bb0: {
+    // CHECK: switchInt(const 1_isize) -> [1: bb1, otherwise: bb3];
+    // CHECK: bb1: {
+    // CHECK: switchInt(const true) -> [0: bb3, otherwise: bb2];
+    // CHECK: bb2: {
+    // CHECK: [[tmp:_.*]] = const 42_i32;
+    // CHECK: goto -> bb4;
+    // CHECK: bb3: {
+    // CHECK: [[tmp]] = const 10_i32;
+    // CHECK: goto -> bb4;
+    // CHECK: bb4: {
+    // CHECK: {{_.*}} = Add(move [[tmp]], const 0_i32);
     let x = (if let Some(true) = Some(true) { 42 } else { 10 }) + 0;
 }
diff --git a/tests/mir-opt/const_prop/indirect.rs b/tests/mir-opt/const_prop/indirect.rs
index 0e6e1d78d1e..d3c42e3eb0b 100644
--- a/tests/mir-opt/const_prop/indirect.rs
+++ b/tests/mir-opt/const_prop/indirect.rs
@@ -1,9 +1,11 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 // compile-flags: -C overflow-checks=on
 
 // EMIT_MIR indirect.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: [[x]] = const 3_u8;
     let x = (2u32 as u8) + 1;
 }
diff --git a/tests/mir-opt/const_prop/inherit_overflow.rs b/tests/mir-opt/const_prop/inherit_overflow.rs
index 41989462deb..5b561ae14ad 100644
--- a/tests/mir-opt/const_prop/inherit_overflow.rs
+++ b/tests/mir-opt/const_prop/inherit_overflow.rs
@@ -1,11 +1,14 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+Inline
 
+// After inlining, this will contain a `CheckedBinaryOp`.
+// Propagating the overflow is ok as codegen will just skip emitting the panic.
 // EMIT_MIR inherit_overflow.main.ConstProp.diff
 fn main() {
-    // After inlining, this will contain a `CheckedBinaryOp`.
-    // Propagating the overflow is ok as codegen will just skip emitting the panic.
+    // CHECK-LABEL: fn main(
+    // CHECK: {{_.*}} = const (0_u8, true);
+    // CHECK: assert(!const true,
+    // CHECK: {{_.*}} = const 0_u8;
     let _ = <u8 as std::ops::Add>::add(255, 1);
 }
diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff
index 6484b4b67af..ff93c85e586 100644
--- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff
+++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-abort.diff
@@ -5,17 +5,24 @@
       let mut _0: ();
       let _1: ();
       let mut _2: ((), u8, u8);
+      let mut _3: ();
   
       bb0: {
+          StorageLive(_1);
           StorageLive(_2);
--         _2 = (const (), const 0_u8, const 0_u8);
--         _1 = encode(move _2) -> [return: bb1, unwind unreachable];
+          StorageLive(_3);
+          _3 = ();
+-         _2 = (move _3, const 0_u8, const 0_u8);
 +         _2 = const ((), 0_u8, 0_u8);
+          StorageDead(_3);
+-         _1 = encode(move _2) -> [return: bb1, unwind unreachable];
 +         _1 = encode(const ((), 0_u8, 0_u8)) -> [return: bb1, unwind unreachable];
       }
   
       bb1: {
           StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
           return;
       }
 + }
diff --git a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff
index b02f0407839..8790aad4559 100644
--- a/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/issue_66971.main.ConstProp.panic-unwind.diff
@@ -5,17 +5,24 @@
       let mut _0: ();
       let _1: ();
       let mut _2: ((), u8, u8);
+      let mut _3: ();
   
       bb0: {
+          StorageLive(_1);
           StorageLive(_2);
--         _2 = (const (), const 0_u8, const 0_u8);
--         _1 = encode(move _2) -> [return: bb1, unwind continue];
+          StorageLive(_3);
+          _3 = ();
+-         _2 = (move _3, const 0_u8, const 0_u8);
 +         _2 = const ((), 0_u8, 0_u8);
+          StorageDead(_3);
+-         _1 = encode(move _2) -> [return: bb1, unwind continue];
 +         _1 = encode(const ((), 0_u8, 0_u8)) -> [return: bb1, unwind continue];
       }
   
       bb1: {
           StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
           return;
       }
 + }
diff --git a/tests/mir-opt/const_prop/issue_66971.rs b/tests/mir-opt/const_prop/issue_66971.rs
index 386c95b5b69..49d598ff230 100644
--- a/tests/mir-opt/const_prop/issue_66971.rs
+++ b/tests/mir-opt/const_prop/issue_66971.rs
@@ -1,7 +1,5 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
-// compile-flags: -Z mir-opt-level=3
 
 // Due to a bug in propagating scalar pairs the assertion below used to fail. In the expected
 // outputs below, after ConstProp this is how _2 would look like with the bug:
@@ -16,5 +14,7 @@ fn encode(this: ((), u8, u8)) {
 
 // EMIT_MIR issue_66971.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: = encode(const ((), 0_u8, 0_u8))
     encode(((), 0, 0));
 }
diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff
index c1ef453e9df..3de9cdd79bc 100644
--- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff
+++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-abort.diff
@@ -8,6 +8,7 @@
       let mut _3: (u8, u8);
   
       bb0: {
+          StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
 -         _3 = (const 1_u8, const 2_u8);
@@ -21,6 +22,8 @@
   
       bb1: {
           StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
           return;
       }
 + }
diff --git a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff
index 53cdcc18167..72cf48b5cba 100644
--- a/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/issue_67019.main.ConstProp.panic-unwind.diff
@@ -8,6 +8,7 @@
       let mut _3: (u8, u8);
   
       bb0: {
+          StorageLive(_1);
           StorageLive(_2);
           StorageLive(_3);
 -         _3 = (const 1_u8, const 2_u8);
@@ -21,6 +22,8 @@
   
       bb1: {
           StorageDead(_2);
+          StorageDead(_1);
+          _0 = const ();
           return;
       }
 + }
diff --git a/tests/mir-opt/const_prop/issue_67019.rs b/tests/mir-opt/const_prop/issue_67019.rs
index 2f61298bb98..f0a09e6e852 100644
--- a/tests/mir-opt/const_prop/issue_67019.rs
+++ b/tests/mir-opt/const_prop/issue_67019.rs
@@ -1,7 +1,5 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
-// compile-flags: -Z mir-opt-level=3
 
 // This used to ICE in const-prop
 
@@ -11,5 +9,7 @@ fn test(this: ((u8, u8),)) {
 
 // EMIT_MIR issue_67019.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: = test(const ((1_u8, 2_u8),))
     test(((1, 2),));
 }
diff --git a/tests/mir-opt/const_prop/mult_by_zero.rs b/tests/mir-opt/const_prop/mult_by_zero.rs
index 47e15205ea9..2e9c63a1ca1 100644
--- a/tests/mir-opt/const_prop/mult_by_zero.rs
+++ b/tests/mir-opt/const_prop/mult_by_zero.rs
@@ -1,9 +1,10 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 // EMIT_MIR mult_by_zero.test.ConstProp.diff
-fn test(x : i32) -> i32 {
-  x * 0
+fn test(x: i32) -> i32 {
+    // CHECK: fn test(
+    // CHECK: _0 = const 0_i32;
+    x * 0
 }
 
 fn main() {
diff --git a/tests/mir-opt/const_prop/mutable_variable.rs b/tests/mir-opt/const_prop/mutable_variable.rs
index 175d63d46f5..6c74ea5b9f4 100644
--- a/tests/mir-opt/const_prop/mutable_variable.rs
+++ b/tests/mir-opt/const_prop/mutable_variable.rs
@@ -1,8 +1,13 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 // EMIT_MIR mutable_variable.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = const 42_i32;
+    // CHECK: [[x]] = const 99_i32;
+    // CHECK: [[y]] = const 99_i32;
     let mut x = 42;
     x = 99;
     let y = x;
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs
index f926771ae38..a3829650290 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate.rs
@@ -1,8 +1,13 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 // EMIT_MIR mutable_variable_aggregate.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = const (42_i32, 43_i32);
+    // CHECK: ([[x]].1: i32) = const 99_i32;
+    // CHECK: [[y]] = const (42_i32, 99_i32);
     let mut x = (42, 43);
     x.1 = 99;
     let y = x;
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
index a81aa7b4979..60f414ae286 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_mut_ref.rs
@@ -1,8 +1,15 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 // EMIT_MIR mutable_variable_aggregate_mut_ref.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug z => [[z:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = (const 42_i32, const 43_i32);
+    // CHECK: [[z]] = &mut [[x]];
+    // CHECK: ((*[[z]]).1: i32) = const 99_i32;
+    // CHECK: [[y]] = [[x]];
     let mut x = (42, 43);
     let z = &mut x;
     z.1 = 99;
diff --git a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
index 54a5d922321..888fcde2de6 100644
--- a/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_aggregate_partial_read.rs
@@ -1,9 +1,15 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 
 // EMIT_MIR mutable_variable_aggregate_partial_read.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = foo()
+    // CHECK: ([[x]].1: i32) = const 99_i32;
+    // CHECK: ([[x]].0: i32) = const 42_i32;
+    // CHECK: [[y]] = const 99_i32;
     let mut x: (i32, i32) = foo();
     x.1 = 99;
     x.0 = 42;
diff --git a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
index a7aeeccd861..49e9a701581 100644
--- a/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_no_prop.rs
@@ -1,10 +1,17 @@
-// skip-filecheck
 // unit-test: ConstProp
 
+// Verify that we do not propagate the contents of this mutable static.
 static mut STATIC: u32 = 0x42424242;
 
 // EMIT_MIR mutable_variable_no_prop.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: [[x]] = const 42_u32;
+    // CHECK: [[tmp:_.*]] = (*{{_.*}});
+    // CHECK: [[x]] = move [[tmp]];
+    // CHECK: [[y]] = [[x]];
     let mut x = 42;
     unsafe {
         x = STATIC;
diff --git a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
index 6bdb136a949..04e347fc03d 100644
--- a/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
+++ b/tests/mir-opt/const_prop/mutable_variable_unprop_assign.rs
@@ -1,14 +1,24 @@
-// skip-filecheck
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 
 // EMIT_MIR mutable_variable_unprop_assign.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: debug y => [[y:_.*]];
+    // CHECK: debug z => [[z:_.*]];
+    // CHECK: [[a]] = foo()
+    // CHECK: [[x]] = const (1_i32, 2_i32);
+    // CHECK: [[tmp:_.*]] = [[a]];
+    // CHECK: ([[x]].1: i32) = move [[tmp]];
+    // CHECK: [[y]] = ([[x]].1: i32);
+    // CHECK: [[z]] = const 1_i32;
     let a = foo();
     let mut x: (i32, i32) = (1, 2);
     x.1 = a;
     let y = x.1;
-    let z = x.0; // this could theoretically be allowed, but we can't handle it right now
+    let z = x.0;
 }
 
 #[inline(never)]
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-abort.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff
index bd1de7476a2..bd1de7476a2 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-abort.diff
+++ b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-abort.diff
diff --git a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff
index 850b743feb1..850b743feb1 100644
--- a/tests/mir-opt/const_prop/const_prop_fails_gracefully.main.ConstProp.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/pointer_expose_address.main.ConstProp.panic-unwind.diff
diff --git a/tests/mir-opt/const_prop/pointer_expose_address.rs b/tests/mir-opt/const_prop/pointer_expose_address.rs
new file mode 100644
index 00000000000..631aac901b9
--- /dev/null
+++ b/tests/mir-opt/const_prop/pointer_expose_address.rs
@@ -0,0 +1,18 @@
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+// unit-test: ConstProp
+
+#[inline(never)]
+fn read(_: usize) { }
+
+// EMIT_MIR pointer_expose_address.main.ConstProp.diff
+fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: [[ptr:_.*]] = const _;
+    // CHECK: [[ref:_.*]] = &raw const (*[[ptr]]);
+    // CHECK: [[x:_.*]] = move [[ref]] as usize (PointerExposeAddress);
+    // CHECK: [[arg:_.*]] = [[x]];
+    // CHECK: = read(move [[arg]])
+    const FOO: &i32 = &1;
+    let x = FOO as *const i32 as usize;
+    read(x);
+}
diff --git a/tests/mir-opt/const_prop/read_immutable_static.rs b/tests/mir-opt/const_prop/read_immutable_static.rs
index a8d8cfacc7c..0fa18dd101a 100644
--- a/tests/mir-opt/const_prop/read_immutable_static.rs
+++ b/tests/mir-opt/const_prop/read_immutable_static.rs
@@ -1,9 +1,11 @@
-// skip-filecheck
 // unit-test: ConstProp
 
 static FOO: u8 = 2;
 
 // EMIT_MIR read_immutable_static.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: [[x]] = const 4_u8;
     let x = FOO + FOO;
 }
diff --git a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
index 6b897a88181..a54ae8d2fdd 100644
--- a/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/ref_deref.main.ConstProp.diff
@@ -7,6 +7,9 @@
       let mut _2: &i32;
       let _3: i32;
       let mut _4: &i32;
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -15,8 +18,8 @@
           _2 = &(*_4);
           _1 = (*_2);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/ref_deref.rs b/tests/mir-opt/const_prop/ref_deref.rs
index f2fa024f722..5bceae749ff 100644
--- a/tests/mir-opt/const_prop/ref_deref.rs
+++ b/tests/mir-opt/const_prop/ref_deref.rs
@@ -1,7 +1,9 @@
-// skip-filecheck
 // unit-test: ConstProp
-// EMIT_MIR ref_deref.main.ConstProp.diff
 
+// EMIT_MIR ref_deref.main.ConstProp.diff
 fn main() {
-    *(&4);
+    // CHECK-LABEL: fn main(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: [[a]] = (*{{_.*}});
+    let a = *(&4);
 }
diff --git a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
index 7f616166573..05a4e17742d 100644
--- a/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
+++ b/tests/mir-opt/const_prop/ref_deref_project.main.ConstProp.diff
@@ -7,6 +7,9 @@
       let mut _2: &i32;
       let _3: (i32, i32);
       let mut _4: &(i32, i32);
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -15,8 +18,8 @@
           _2 = &((*_4).1: i32);
           _1 = (*_2);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/ref_deref_project.rs b/tests/mir-opt/const_prop/ref_deref_project.rs
index 1b9e0acb2c0..4b5c6730316 100644
--- a/tests/mir-opt/const_prop/ref_deref_project.rs
+++ b/tests/mir-opt/const_prop/ref_deref_project.rs
@@ -1,7 +1,10 @@
-// skip-filecheck
+// This does not currently propagate (#67862)
 // unit-test: ConstProp
-// EMIT_MIR ref_deref_project.main.ConstProp.diff
 
+// EMIT_MIR ref_deref_project.main.ConstProp.diff
 fn main() {
-    *(&(4, 5).1); // This does not currently propagate (#67862)
+    // CHECK-LABEL: fn main(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: [[a]] = (*{{_.*}});
+    let a = *(&(4, 5).1);
 }
diff --git a/tests/mir-opt/const_prop/reify_fn_ptr.rs b/tests/mir-opt/const_prop/reify_fn_ptr.rs
index da7de80c5f4..33fdd4142c1 100644
--- a/tests/mir-opt/const_prop/reify_fn_ptr.rs
+++ b/tests/mir-opt/const_prop/reify_fn_ptr.rs
@@ -1,7 +1,10 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR reify_fn_ptr.main.ConstProp.diff
 
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: [[ptr:_.*]] = main as fn() (PointerCoercion(ReifyFnPointer));
+    // CHECK: [[addr:_.*]] = move [[ptr]] as usize (PointerExposeAddress);
+    // CHECK: [[back:_.*]] = move [[addr]] as *const fn() (PointerFromExposedAddress);
     let _ = main as usize as *const fn();
 }
diff --git a/tests/mir-opt/const_prop/repeat.rs b/tests/mir-opt/const_prop/repeat.rs
index 92194d6bb58..9f688bbb53e 100644
--- a/tests/mir-opt/const_prop/repeat.rs
+++ b/tests/mir-opt/const_prop/repeat.rs
@@ -1,9 +1,11 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR repeat.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: debug x => [[x:_.*]];
+    // CHECK: [[x]] = const 42_u32;
     let x: u32 = [42; 8][2] + 0;
 }
diff --git a/tests/mir-opt/const_prop/return_place.rs b/tests/mir-opt/const_prop/return_place.rs
index 1263de7931f..286543abb99 100644
--- a/tests/mir-opt/const_prop/return_place.rs
+++ b/tests/mir-opt/const_prop/return_place.rs
@@ -1,4 +1,3 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // compile-flags: -C overflow-checks=on
@@ -6,6 +5,8 @@
 // EMIT_MIR return_place.add.ConstProp.diff
 // EMIT_MIR return_place.add.PreCodegen.before.mir
 fn add() -> u32 {
+    // CHECK-LABEL: fn add(
+    // CHECK: _0 = const 4_u32;
     2 + 2
 }
 
diff --git a/tests/mir-opt/const_prop/scalar_literal_propagation.rs b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
index 9dcddf7c770..782cd35d422 100644
--- a/tests/mir-opt/const_prop/scalar_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/scalar_literal_propagation.rs
@@ -1,8 +1,10 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 // EMIT_MIR scalar_literal_propagation.main.ConstProp.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: = consume(const 1_u32)
     let x = 1;
     consume(x);
 }
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff
index c2e1288b41e..7d5d036f460 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-abort.diff
@@ -12,6 +12,9 @@
       let mut _7: usize;
       let mut _8: bool;
       let mut _9: &[u32; 3];
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -39,8 +42,8 @@
           StorageDead(_6);
           StorageDead(_4);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff
index 23646c3c976..fa4c5a71be5 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.32bit.panic-unwind.diff
@@ -12,6 +12,9 @@
       let mut _7: usize;
       let mut _8: bool;
       let mut _9: &[u32; 3];
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -39,8 +42,8 @@
           StorageDead(_6);
           StorageDead(_4);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff
index c2e1288b41e..7d5d036f460 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-abort.diff
@@ -12,6 +12,9 @@
       let mut _7: usize;
       let mut _8: bool;
       let mut _9: &[u32; 3];
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -39,8 +42,8 @@
           StorageDead(_6);
           StorageDead(_4);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff
index 23646c3c976..fa4c5a71be5 100644
--- a/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff
+++ b/tests/mir-opt/const_prop/slice_len.main.ConstProp.64bit.panic-unwind.diff
@@ -12,6 +12,9 @@
       let mut _7: usize;
       let mut _8: bool;
       let mut _9: &[u32; 3];
+      scope 1 {
+          debug a => _1;
+      }
   
       bb0: {
           StorageLive(_1);
@@ -39,8 +42,8 @@
           StorageDead(_6);
           StorageDead(_4);
           StorageDead(_2);
-          StorageDead(_1);
           _0 = const ();
+          StorageDead(_1);
           return;
       }
   }
diff --git a/tests/mir-opt/const_prop/slice_len.rs b/tests/mir-opt/const_prop/slice_len.rs
index 3b551b6b173..0bf44272698 100644
--- a/tests/mir-opt/const_prop/slice_len.rs
+++ b/tests/mir-opt/const_prop/slice_len.rs
@@ -1,10 +1,13 @@
-// skip-filecheck
-// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+InstSimplify
+// EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR_FOR_EACH_BIT_WIDTH
 
 // EMIT_MIR slice_len.main.ConstProp.diff
 fn main() {
-    (&[1u32, 2, 3] as &[u32])[1];
+    // CHECK-LABEL: fn main(
+    // CHECK: debug a => [[a:_.*]];
+    // CHECK: assert(const true,
+    // CHECK: [[a]] = const 2_u32;
+    let a = (&[1u32, 2, 3] as &[u32])[1];
 }
diff --git a/tests/mir-opt/const_prop/switch_int.rs b/tests/mir-opt/const_prop/switch_int.rs
index 7ec56e11e85..d1cbaae49aa 100644
--- a/tests/mir-opt/const_prop/switch_int.rs
+++ b/tests/mir-opt/const_prop/switch_int.rs
@@ -1,13 +1,20 @@
-// skip-filecheck
 // unit-test: ConstProp
 // compile-flags: -Zmir-enable-passes=+SimplifyConstCondition-after-const-prop
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
+
 #[inline(never)]
 fn foo(_: i32) { }
 
 // EMIT_MIR switch_int.main.ConstProp.diff
 // EMIT_MIR switch_int.main.SimplifyConstCondition-after-const-prop.diff
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: bb0: {
+    // CHECK-NOT: switchInt(
+    // CHECK: goto -> [[bb:bb.*]];
+    // CHECK: [[bb]]: {
+    // CHECK-NOT: _0 = foo(const -1_i32)
+    // CHECK: _0 = foo(const 0_i32)
     match 1 {
         1 => foo(0),
         _ => foo(-1),
diff --git a/tests/mir-opt/const_prop/tuple_literal_propagation.rs b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
index e0bc6e1be37..dfc4a6f3fbb 100644
--- a/tests/mir-opt/const_prop/tuple_literal_propagation.rs
+++ b/tests/mir-opt/const_prop/tuple_literal_propagation.rs
@@ -1,10 +1,11 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR_FOR_EACH_PANIC_STRATEGY
 // EMIT_MIR tuple_literal_propagation.main.ConstProp.diff
+
 fn main() {
+    // CHECK-LABEL: fn main(
+    // CHECK: = consume(const (1_u32, 2_u32))
     let x = (1, 2);
-
     consume(x);
 }
 
diff --git a/tests/mir-opt/const_prop/while_let_loops.rs b/tests/mir-opt/const_prop/while_let_loops.rs
index 39081c3550a..8b2a73438d6 100644
--- a/tests/mir-opt/const_prop/while_let_loops.rs
+++ b/tests/mir-opt/const_prop/while_let_loops.rs
@@ -1,8 +1,9 @@
-// skip-filecheck
 // unit-test: ConstProp
 // EMIT_MIR while_let_loops.change_loop_body.ConstProp.diff
 
 pub fn change_loop_body() {
+    // CHECK-LABEL: fn change_loop_body(
+    // CHECK: switchInt(const 0_isize)
     let mut _x = 0;
     while let Some(0u32) = None {
         _x = 1;
diff --git a/tests/run-make/jobserver-error/cannot_open_fd.stderr b/tests/run-make/jobserver-error/cannot_open_fd.stderr
index a2f77a94e4f..343de5cd52c 100644
--- a/tests/run-make/jobserver-error/cannot_open_fd.stderr
+++ b/tests/run-make/jobserver-error/cannot_open_fd.stderr
@@ -4,5 +4,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--
 
 error: no input filename given
 
-warning: 1 warning emitted
-
diff --git a/tests/run-make/jobserver-error/not_a_pipe.stderr b/tests/run-make/jobserver-error/not_a_pipe.stderr
index 9158fda6e47..536c04576b9 100644
--- a/tests/run-make/jobserver-error/not_a_pipe.stderr
+++ b/tests/run-make/jobserver-error/not_a_pipe.stderr
@@ -2,5 +2,3 @@ warning: failed to connect to jobserver from environment variable `MAKEFLAGS="--
   |
   = note: the build environment is likely misconfigured
 
-warning: 1 warning emitted
-
diff --git a/tests/rustdoc-gui/item-info.goml b/tests/rustdoc-gui/item-info.goml
index 030ff8f8a3e..b46d4255ee5 100644
--- a/tests/rustdoc-gui/item-info.goml
+++ b/tests/rustdoc-gui/item-info.goml
@@ -8,7 +8,22 @@ assert-size: (".item-info", {"width": 840})
 assert-size: (".item-info .stab", {"width": 289})
 assert-position: (".item-info .stab", {"x": 245})
 
+// We check that the display of the feature elements is not broken. It serves as regression
+// test for <https://github.com/rust-lang/rust/issues/118615>.
+set-window-size: (850, 800)
+store-position: (
+    "//*[@class='stab portability']//code[text()='Win32_System']",
+    {"x": first_line_x, "y": first_line_y},
+)
+store-position: (
+    "//*[@class='stab portability']//code[text()='Win32_System_Diagnostics']",
+    {"x": second_line_x, "y": second_line_y},
+)
+assert: |first_line_x| != |second_line_x| && |first_line_x| == 516 && |second_line_x| == 272
+assert: |first_line_y| != |second_line_y| && |first_line_y| == 688 && |second_line_y| == 711
+
 // Now we ensure that they're not rendered on the same line.
+set-window-size: (1100, 800)
 go-to: "file://" + |DOC_PATH| + "/lib2/trait.Trait.html"
 // We first ensure that there are two item info on the trait.
 assert-count: ("#main-content > .item-info .stab", 2)
diff --git a/tests/rustdoc-gui/src/lib2/Cargo.toml b/tests/rustdoc-gui/src/lib2/Cargo.toml
index 8bca77ff834..6c4ca27d550 100644
--- a/tests/rustdoc-gui/src/lib2/Cargo.toml
+++ b/tests/rustdoc-gui/src/lib2/Cargo.toml
@@ -6,6 +6,13 @@ edition = "2018"
 [lib]
 path = "lib.rs"
 
+[features]
+Win32 = ["Win32_System"]
+Win32_System = ["Win32_System_Diagnostics"]
+Win32_System_Diagnostics = ["Win32_System_Diagnostics_Debug"]
+Win32_System_Diagnostics_Debug = []
+default = ["Win32"]
+
 [dependencies]
 implementors = { path = "./implementors" }
 http = { path = "./http" }
diff --git a/tests/rustdoc-gui/src/lib2/lib.rs b/tests/rustdoc-gui/src/lib2/lib.rs
index a2a3c31878b..b467b044052 100644
--- a/tests/rustdoc-gui/src/lib2/lib.rs
+++ b/tests/rustdoc-gui/src/lib2/lib.rs
@@ -1,6 +1,7 @@
 // ignore-tidy-linelength
 
 #![feature(doc_cfg)]
+#![feature(doc_auto_cfg)]
 
 pub mod another_folder;
 pub mod another_mod;
@@ -28,6 +29,14 @@ impl Foo {
     /// Some documentation
     /// # A Heading
     pub fn a_method(&self) {}
+
+    #[cfg(all(
+        feature = "Win32",
+        feature = "Win32_System",
+        feature = "Win32_System_Diagnostics",
+        feature = "Win32_System_Diagnostics_Debug"
+    ))]
+    pub fn lot_of_features() {}
 }
 
 #[doc(cfg(feature = "foo-method"))]
diff --git a/tests/ui-fulldeps/pprust-expr-roundtrip.rs b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
index 9e581620ec1..fe5333643ed 100644
--- a/tests/ui-fulldeps/pprust-expr-roundtrip.rs
+++ b/tests/ui-fulldeps/pprust-expr-roundtrip.rs
@@ -132,7 +132,7 @@ fn iter_exprs(depth: usize, f: &mut dyn FnMut(P<Expr>)) {
                         binder: ClosureBinder::NotPresent,
                         capture_clause: CaptureBy::Value { move_kw: DUMMY_SP },
                         constness: Const::No,
-                        coro_kind: None,
+                        coroutine_kind: None,
                         movability: Movability::Movable,
                         fn_decl: decl.clone(),
                         body: e,
diff --git a/tests/ui-fulldeps/stable-mir/check_allocation.rs b/tests/ui-fulldeps/stable-mir/check_allocation.rs
index 170b1fd73b1..88c41537d9f 100644
--- a/tests/ui-fulldeps/stable-mir/check_allocation.rs
+++ b/tests/ui-fulldeps/stable-mir/check_allocation.rs
@@ -23,12 +23,16 @@ extern crate stable_mir;
 
 use rustc_middle::ty::TyCtxt;
 use rustc_smir::rustc_internal;
-use stable_mir::{CrateItem, CrateItems, ItemKind};
 use stable_mir::crate_def::CrateDef;
 use stable_mir::mir::alloc::GlobalAlloc;
-use stable_mir::mir::mono::StaticDef;
+use stable_mir::mir::mono::{Instance, InstanceKind, StaticDef};
+use stable_mir::mir::{Body, TerminatorKind};
+use stable_mir::ty::{Allocation, ConstantKind, RigidTy, TyKind};
+use stable_mir::{CrateItem, CrateItems, ItemKind};
 use std::ascii::Char;
 use std::assert_matches::assert_matches;
+use std::cmp::{max, min};
+use std::collections::HashMap;
 use std::io::Write;
 use std::ops::ControlFlow;
 
@@ -40,6 +44,9 @@ fn test_stable_mir(_tcx: TyCtxt<'_>) -> ControlFlow<()> {
     let items = stable_mir::all_local_items();
     check_foo(*get_item(&items, (ItemKind::Static, "FOO")).unwrap());
     check_bar(*get_item(&items, (ItemKind::Static, "BAR")).unwrap());
+    check_len(*get_item(&items, (ItemKind::Static, "LEN")).unwrap());
+    check_other_consts(*get_item(&items, (ItemKind::Fn, "other_consts")).unwrap());
+    check_type_id(*get_item(&items, (ItemKind::Fn, "check_type_id")).unwrap());
     ControlFlow::Continue(())
 }
 
@@ -76,6 +83,110 @@ fn check_bar(item: CrateItem) {
     assert_eq!(allocation.bytes[0].unwrap(), Char::CapitalB.to_u8());
     assert_eq!(allocation.bytes[1].unwrap(), Char::SmallA.to_u8());
     assert_eq!(allocation.bytes[2].unwrap(), Char::SmallR.to_u8());
+    assert_eq!(std::str::from_utf8(&allocation.raw_bytes().unwrap()), Ok("Bar"));
+}
+
+/// Check the allocation data for constants used in `other_consts` function.
+fn check_other_consts(item: CrateItem) {
+    // Instance body will force constant evaluation.
+    let body = Instance::try_from(item).unwrap().body().unwrap();
+    let assigns = collect_consts(&body);
+    assert_eq!(assigns.len(), 9);
+    for (name, alloc) in assigns {
+        match name.as_str() {
+            "_max_u128" => {
+                assert_eq!(alloc.read_uint(), Ok(u128::MAX), "Failed parsing allocation: {alloc:?}")
+            }
+            "_min_i128" => {
+                assert_eq!(alloc.read_int(), Ok(i128::MIN), "Failed parsing allocation: {alloc:?}")
+            }
+            "_max_i8" => {
+                assert_eq!(
+                    alloc.read_int().unwrap() as i8,
+                    i8::MAX,
+                    "Failed parsing allocation: {alloc:?}"
+                )
+            }
+            "_char" => {
+                assert_eq!(
+                    char::from_u32(alloc.read_uint().unwrap() as u32),
+                    Some('x'),
+                    "Failed parsing allocation: {alloc:?}"
+                )
+            }
+            "_false" => {
+                assert_eq!(alloc.read_bool(), Ok(false), "Failed parsing allocation: {alloc:?}")
+            }
+            "_true" => {
+                assert_eq!(alloc.read_bool(), Ok(true), "Failed parsing allocation: {alloc:?}")
+            }
+            "_ptr" => {
+                assert_eq!(alloc.is_null(), Ok(false), "Failed parsing allocation: {alloc:?}")
+            }
+            "_null_ptr" => {
+                assert_eq!(alloc.is_null(), Ok(true), "Failed parsing allocation: {alloc:?}")
+            }
+            "_tuple" => {
+                // The order of fields is not guaranteed.
+                let first = alloc.read_partial_uint(0..4).unwrap();
+                let second = alloc.read_partial_uint(4..8).unwrap();
+                assert_eq!(max(first, second) as u32, u32::MAX);
+                assert_eq!(min(first, second), 10);
+            }
+            _ => {
+                unreachable!("{name} -- {alloc:?}")
+            }
+        }
+    }
+}
+
+/// Check that we can retrieve the type id of char and bool, and that they have different values.
+fn check_type_id(item: CrateItem) {
+    let body = Instance::try_from(item).unwrap().body().unwrap();
+    let mut ids: Vec<u128> = vec![];
+    for term in body.blocks.iter().map(|bb| &bb.terminator) {
+        match &term.kind {
+            TerminatorKind::Call { func, destination, .. } => {
+                let TyKind::RigidTy(ty) = func.ty(body.locals()).unwrap().kind() else {
+                    unreachable!()
+                };
+                let RigidTy::FnDef(def, args) = ty else { unreachable!() };
+                let instance = Instance::resolve(def, &args).unwrap();
+                assert_eq!(instance.kind, InstanceKind::Intrinsic);
+                let dest_ty = destination.ty(body.locals()).unwrap();
+                let alloc = instance.try_const_eval(dest_ty).unwrap();
+                ids.push(alloc.read_uint().unwrap());
+            }
+            _ => { /* Do nothing */ }
+        }
+    }
+    assert_eq!(ids.len(), 2);
+    assert_ne!(ids[0], ids[1]);
+}
+
+/// Collects all the constant assignments.
+pub fn collect_consts(body: &Body) -> HashMap<String, &Allocation> {
+    body.var_debug_info
+        .iter()
+        .filter_map(|info| {
+            info.constant().map(|const_op| {
+                let ConstantKind::Allocated(alloc) = const_op.const_.kind() else { unreachable!() };
+                (info.name.clone(), alloc)
+            })
+        })
+        .collect::<HashMap<_, _>>()
+}
+
+/// Check the allocation data for `LEN`.
+///
+/// ```no_run
+/// static LEN: usize = 2;
+/// ```
+fn check_len(item: CrateItem) {
+    let def = StaticDef::try_from(item).unwrap();
+    let alloc = def.eval_initializer().unwrap();
+    assert!(alloc.provenance.ptrs.is_empty());
+    assert_eq!(alloc.read_uint(), Ok(2));
 }
 
 // Use internal API to find a function in a crate.
@@ -83,9 +194,7 @@ fn get_item<'a>(
     items: &'a CrateItems,
     item: (ItemKind, &str),
 ) -> Option<&'a stable_mir::CrateItem> {
-    items.iter().find(|crate_item| {
-        (item.0 == crate_item.kind()) && crate_item.name() == item.1
-    })
+    items.iter().find(|crate_item| (item.0 == crate_item.kind()) && crate_item.name() == item.1)
 }
 
 /// This test will generate and analyze a dummy crate using the stable mir.
@@ -109,11 +218,36 @@ fn generate_input(path: &str) -> std::io::Result<()> {
     write!(
         file,
         r#"
+    #![feature(core_intrinsics)]
+    use std::intrinsics::type_id;
+
+    static LEN: usize = 2;
     static FOO: [&str; 2] = ["hi", "there"];
     static BAR: &str = "Bar";
+    const NULL: *const u8 = std::ptr::null();
+    const TUPLE: (u32, u32) = (10, u32::MAX);
+
+    fn other_consts() {{
+        let _max_u128 = u128::MAX;
+        let _min_i128 = i128::MIN;
+        let _max_i8 = i8::MAX;
+        let _char = 'x';
+        let _false = false;
+        let _true = true;
+        let _ptr = &BAR;
+        let _null_ptr: *const u8 = NULL;
+        let _tuple = TUPLE;
+    }}
+
+    fn check_type_id() {{
+        let _char_id = type_id::<char>();
+        let _bool_id = type_id::<bool>();
+    }}
 
     pub fn main() {{
         println!("{{FOO:?}}! {{BAR}}");
+        assert_eq!(FOO.len(), LEN);
+        other_consts();
     }}"#
     )?;
     Ok(())
diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs
index f57fcd6044f..361ed8f3d91 100644
--- a/tests/ui/abi/riscv-discoverability-guidance.rs
+++ b/tests/ui/abi/riscv-discoverability-guidance.rs
@@ -2,9 +2,9 @@
 // revisions: riscv32 riscv64
 //
 // [riscv32] needs-llvm-components: riscv
-// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib
+// [riscv32] compile-flags: --target=riscv32i-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib
 // [riscv64] needs-llvm-components: riscv
-// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-unaligned-scalar-mem --crate-type=rlib
+// [riscv64] compile-flags: --target=riscv64gc-unknown-none-elf -C target-feature=-fast-unaligned-access --crate-type=rlib
 #![no_core]
 #![feature(
     no_core,
diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs
new file mode 100644
index 00000000000..ac085864ff0
--- /dev/null
+++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.rs
@@ -0,0 +1,19 @@
+// We used to say "ambiguous associated type" on ambiguous associated consts.
+// Ensure that we now use the correct label.
+
+#![feature(associated_const_equality)]
+
+trait Trait0: Parent0<i32> + Parent0<u32> {}
+trait Parent0<T> { const K: (); }
+
+fn take0(_: impl Trait0<K = { () }>) {}
+//~^ ERROR ambiguous associated constant `K` in bounds of `Trait0`
+
+trait Trait1: Parent1 + Parent2 {}
+trait Parent1 { const C: i32; }
+trait Parent2 { const C: &'static str; }
+
+fn take1(_: impl Trait1<C = "?">) {}
+//~^ ERROR ambiguous associated constant `C` in bounds of `Trait1`
+
+fn main() {}
diff --git a/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr
new file mode 100644
index 00000000000..ba3a8701316
--- /dev/null
+++ b/tests/ui/associated-consts/assoc-const-eq-ambiguity.stderr
@@ -0,0 +1,38 @@
+error[E0222]: ambiguous associated constant `K` in bounds of `Trait0`
+  --> $DIR/assoc-const-eq-ambiguity.rs:9:25
+   |
+LL | trait Parent0<T> { const K: (); }
+   |                    -----------
+   |                    |
+   |                    ambiguous `K` from `Parent0<u32>`
+   |                    ambiguous `K` from `Parent0<i32>`
+LL |
+LL | fn take0(_: impl Trait0<K = { () }>) {}
+   |                         ^^^^^^^^^^ ambiguous associated constant `K`
+   |
+   = help: consider introducing a new type parameter `T` and adding `where` constraints:
+               where
+                   T: Trait0,
+                   T: Parent0<u32>::K = { () },
+                   T: Parent0<i32>::K = { () }
+
+error[E0222]: ambiguous associated constant `C` in bounds of `Trait1`
+  --> $DIR/assoc-const-eq-ambiguity.rs:16:25
+   |
+LL | trait Parent1 { const C: i32; }
+   |                 ------------ ambiguous `C` from `Parent1`
+LL | trait Parent2 { const C: &'static str; }
+   |                 --------------------- ambiguous `C` from `Parent2`
+LL |
+LL | fn take1(_: impl Trait1<C = "?">) {}
+   |                         ^^^^^^^ ambiguous associated constant `C`
+   |
+   = help: consider introducing a new type parameter `T` and adding `where` constraints:
+               where
+                   T: Trait1,
+                   T: Parent2::C = "?",
+                   T: Parent1::C = "?"
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0222`.
diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.rs b/tests/ui/associated-consts/assoc-const-eq-missing.rs
index 5e029a12df2..f384927e4a3 100644
--- a/tests/ui/associated-consts/assoc-const-eq-missing.rs
+++ b/tests/ui/associated-consts/assoc-const-eq-missing.rs
@@ -11,13 +11,12 @@ impl Foo for Bar {
   const N: usize = 3;
 }
 
-
-fn foo1<F: Foo<Z=3>>() {}
-//~^ ERROR associated type
-fn foo2<F: Foo<Z=usize>>() {}
-//~^ ERROR associated type
-fn foo3<F: Foo<Z=5>>() {}
-//~^ ERROR associated type
+fn foo1<F: Foo<Z = 3>>() {}
+//~^ ERROR associated constant `Z` not found for `Foo`
+fn foo2<F: Foo<Z = usize>>() {}
+//~^ ERROR associated type `Z` not found for `Foo`
+fn foo3<F: Foo<Z = 5>>() {}
+//~^ ERROR associated constant `Z` not found for `Foo`
 
 fn main() {
   foo1::<Bar>();
diff --git a/tests/ui/associated-consts/assoc-const-eq-missing.stderr b/tests/ui/associated-consts/assoc-const-eq-missing.stderr
index b4bd6456c85..318c85dcfd6 100644
--- a/tests/ui/associated-consts/assoc-const-eq-missing.stderr
+++ b/tests/ui/associated-consts/assoc-const-eq-missing.stderr
@@ -1,20 +1,20 @@
-error[E0220]: associated type `Z` not found for `Foo`
-  --> $DIR/assoc-const-eq-missing.rs:15:16
+error[E0220]: associated constant `Z` not found for `Foo`
+  --> $DIR/assoc-const-eq-missing.rs:14:16
    |
-LL | fn foo1<F: Foo<Z=3>>() {}
-   |                ^ associated type `Z` not found
+LL | fn foo1<F: Foo<Z = 3>>() {}
+   |                ^ help: there is an associated constant with a similar name: `N`
 
 error[E0220]: associated type `Z` not found for `Foo`
-  --> $DIR/assoc-const-eq-missing.rs:17:16
+  --> $DIR/assoc-const-eq-missing.rs:16:16
    |
-LL | fn foo2<F: Foo<Z=usize>>() {}
+LL | fn foo2<F: Foo<Z = usize>>() {}
    |                ^ associated type `Z` not found
 
-error[E0220]: associated type `Z` not found for `Foo`
-  --> $DIR/assoc-const-eq-missing.rs:19:16
+error[E0220]: associated constant `Z` not found for `Foo`
+  --> $DIR/assoc-const-eq-missing.rs:18:16
    |
-LL | fn foo3<F: Foo<Z=5>>() {}
-   |                ^ associated type `Z` not found
+LL | fn foo3<F: Foo<Z = 5>>() {}
+   |                ^ help: there is an associated constant with a similar name: `N`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs
new file mode 100644
index 00000000000..de9008bfcf9
--- /dev/null
+++ b/tests/ui/associated-consts/assoc-const-eq-ty-alias-noninteracting.rs
@@ -0,0 +1,21 @@
+// Regression test for issue #112560.
+// Respect the fact that (associated) types and constants live in different namespaces and
+// therefore equality bounds involving identically named associated items don't conflict if
+// their kind (type vs. const) differs.
+
+// FIXME(fmease): Extend this test to cover supertraits again
+// once #118040 is fixed. See initial version of PR #118360.
+
+// check-pass
+
+#![feature(associated_const_equality)]
+
+trait Trait {
+    type N;
+
+    const N: usize;
+}
+
+fn take(_: impl Trait<N = 0, N = ()>) {}
+
+fn main() {}
diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs
index c5d78469e95..7211637659b 100644
--- a/tests/ui/associated-consts/assoc-const-ty-mismatch.rs
+++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.rs
@@ -2,30 +2,30 @@
 #![allow(unused)]
 
 pub trait Foo {
-  const N: usize;
+    const N: usize;
 }
 
 pub trait FooTy {
-  type T;
+    type T;
 }
 
 pub struct Bar;
 
 impl Foo for Bar {
-  const N: usize = 3;
+    const N: usize = 3;
 }
 
 impl FooTy for Bar {
-  type T = usize;
+    type T = usize;
 }
 
 
-fn foo<F: Foo<N=usize>>() {}
-//~^ ERROR expected associated constant bound, found type
-fn foo2<F: FooTy<T=3usize>>() {}
-//~^ ERROR expected associated type bound, found constant
+fn foo<F: Foo<N = usize>>() {}
+//~^ ERROR expected constant, found type
+fn foo2<F: FooTy<T = 3usize>>() {}
+//~^ ERROR expected type, found constant
 
 fn main() {
-  foo::<Bar>();
-  foo2::<Bar>();
+    foo::<Bar>();
+    foo2::<Bar>();
 }
diff --git a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr
index 11198729e38..b844cfc4ae4 100644
--- a/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr
+++ b/tests/ui/associated-consts/assoc-const-ty-mismatch.stderr
@@ -1,26 +1,30 @@
-error: expected associated constant bound, found type
-  --> $DIR/assoc-const-ty-mismatch.rs:23:15
+error: expected constant, found type
+  --> $DIR/assoc-const-ty-mismatch.rs:23:19
    |
-LL | fn foo<F: Foo<N=usize>>() {}
-   |               ^^^^^^^
+LL | fn foo<F: Foo<N = usize>>() {}
+   |               -   ^^^^^ unexpected type
+   |               |
+   |               expected a constant because of this associated constant
    |
-note: associated constant defined here
-  --> $DIR/assoc-const-ty-mismatch.rs:5:3
+note: the associated constant is defined here
+  --> $DIR/assoc-const-ty-mismatch.rs:5:5
    |
-LL |   const N: usize;
-   |   ^^^^^^^^^^^^^^
+LL |     const N: usize;
+   |     ^^^^^^^^^^^^^^
 
-error: expected associated type bound, found constant
-  --> $DIR/assoc-const-ty-mismatch.rs:25:18
+error: expected type, found constant
+  --> $DIR/assoc-const-ty-mismatch.rs:25:22
    |
-LL | fn foo2<F: FooTy<T=3usize>>() {}
-   |                  ^^^^^^^^
+LL | fn foo2<F: FooTy<T = 3usize>>() {}
+   |                  -   ^^^^^^ unexpected constant
+   |                  |
+   |                  expected a type because of this associated type
    |
-note: associated type defined here
-  --> $DIR/assoc-const-ty-mismatch.rs:9:3
+note: the associated type is defined here
+  --> $DIR/assoc-const-ty-mismatch.rs:9:5
    |
-LL |   type T;
-   |   ^^^^^^
+LL |     type T;
+   |     ^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
index 6037122a365..1304bef4211 100644
--- a/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
+++ b/tests/ui/associated-consts/associated-const-impl-wrong-lifetime.stderr
@@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait
 LL |     const NAME: &'a str = "unit";
    |     ^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected reference `&'static str`
-              found reference `&'a str`
+   = note: expected reference `&'static _`
+              found reference `&'a _`
 note: the lifetime `'a` as defined here...
   --> $DIR/associated-const-impl-wrong-lifetime.rs:6:6
    |
diff --git a/tests/ui/associated-consts/shadowed-const.rs b/tests/ui/associated-consts/shadowed-const.rs
index cfdb391d39d..d9b565742d4 100644
--- a/tests/ui/associated-consts/shadowed-const.rs
+++ b/tests/ui/associated-consts/shadowed-const.rs
@@ -17,7 +17,7 @@ trait Baz2: Foo {
 trait Baz3 {
   const BAR: usize;
   const QUX: Self::BAR;
-  //~^ ERROR found associated const
+  //~^ ERROR expected type, found constant
 }
 
 fn main() {}
diff --git a/tests/ui/associated-consts/shadowed-const.stderr b/tests/ui/associated-consts/shadowed-const.stderr
index a01a9ae561f..2db645b3c96 100644
--- a/tests/ui/associated-consts/shadowed-const.stderr
+++ b/tests/ui/associated-consts/shadowed-const.stderr
@@ -1,8 +1,14 @@
-error: found associated const `BAR` when type was expected
-  --> $DIR/shadowed-const.rs:19:14
+error: expected type, found constant
+  --> $DIR/shadowed-const.rs:19:20
    |
 LL |   const QUX: Self::BAR;
-   |              ^^^^^^^^^
+   |                    ^^^ unexpected constant
+   |
+note: the associated constant is defined here
+  --> $DIR/shadowed-const.rs:18:3
+   |
+LL |   const BAR: usize;
+   |   ^^^^^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-type-bounds/consts.rs b/tests/ui/associated-type-bounds/consts.rs
index 9b95b1b52c0..8f90c36ed45 100644
--- a/tests/ui/associated-type-bounds/consts.rs
+++ b/tests/ui/associated-type-bounds/consts.rs
@@ -1,7 +1,7 @@
 #![feature(associated_type_bounds)]
 
 pub fn accept(_: impl Trait<K: Copy>) {}
-//~^ ERROR expected associated type, found associated constant
+//~^ ERROR expected type, found constant
 
 pub trait Trait {
     const K: i32;
diff --git a/tests/ui/associated-type-bounds/consts.stderr b/tests/ui/associated-type-bounds/consts.stderr
index eef24c8827b..7f9fe5e500a 100644
--- a/tests/ui/associated-type-bounds/consts.stderr
+++ b/tests/ui/associated-type-bounds/consts.stderr
@@ -1,10 +1,16 @@
-error: expected associated type, found associated constant
+error: expected type, found constant
   --> $DIR/consts.rs:3:29
    |
 LL | pub fn accept(_: impl Trait<K: Copy>) {}
-   |                             ^
+   |                             ^------ bounds are not allowed on associated constants
+   |                             |
+   |                             unexpected constant
    |
-   = note: trait bounds not allowed on associated constant
+note: the associated constant is defined here
+  --> $DIR/consts.rs:7:5
+   |
+LL |     const K: i32;
+   |     ^^^^^^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/associated-type-bounds/issue-99828.rs b/tests/ui/associated-type-bounds/issue-99828.rs
index 7b711283f5b..67ba50f3cbc 100644
--- a/tests/ui/associated-type-bounds/issue-99828.rs
+++ b/tests/ui/associated-type-bounds/issue-99828.rs
@@ -1,5 +1,5 @@
 fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
-    //~^ ERROR expected associated type bound, found constant
+    //~^ ERROR expected type, found constant
     //~| ERROR associated const equality is incomplete
     vec.iter()
 }
diff --git a/tests/ui/associated-type-bounds/issue-99828.stderr b/tests/ui/associated-type-bounds/issue-99828.stderr
index dc93c47dace..8813baf84de 100644
--- a/tests/ui/associated-type-bounds/issue-99828.stderr
+++ b/tests/ui/associated-type-bounds/issue-99828.stderr
@@ -7,13 +7,15 @@ LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
    = note: see issue #92827 <https://github.com/rust-lang/rust/issues/92827> for more information
    = help: add `#![feature(associated_const_equality)]` to the crate attributes to enable
 
-error: expected associated type bound, found constant
-  --> $DIR/issue-99828.rs:1:43
+error: expected type, found constant
+  --> $DIR/issue-99828.rs:1:50
    |
 LL | fn get_iter(vec: &[i32]) -> impl Iterator<Item = {}> + '_ {
-   |                                           ^^^^^^^^^
+   |                                           ----   ^^ unexpected constant
+   |                                           |
+   |                                           expected a type because of this associated type
    |
-note: associated type defined here
+note: the associated type is defined here
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 
 error: aborting due to 2 previous errors
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.rs b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
index 0679b96f6c5..e6270ec3166 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/missing.rs
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.rs
@@ -8,6 +8,6 @@ trait Trait {
 }
 
 fn bar<T: Trait<methid(): Send>>() {}
-//~^ ERROR cannot find associated function `methid` for `Trait`
+//~^ ERROR associated function `methid` not found for `Trait`
 
 fn main() {}
diff --git a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
index 3ca5e66866d..db9cb9f49a3 100644
--- a/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
+++ b/tests/ui/associated-type-bounds/return-type-notation/missing.stderr
@@ -7,11 +7,12 @@ LL | #![feature(return_type_notation)]
    = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: cannot find associated function `methid` for `Trait`
+error[E0220]: associated function `methid` not found for `Trait`
   --> $DIR/missing.rs:10:17
    |
 LL | fn bar<T: Trait<methid(): Send>>() {}
-   |                 ^^^^^^^^^^^^^^
+   |                 ^^^^^^ help: there is an associated function with a similar name: `method`
 
 error: aborting due to 1 previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0220`.
diff --git a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
index 606084aea34..1b4694a2125 100644
--- a/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
+++ b/tests/ui/associated-types/dont-suggest-cyclic-constraint.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     debug_assert_eq!(iter.next(), Some(value));
    |                                   ^^^^^^^^^^^ expected `Option<<I as Iterator>::Item>`, found `Option<&<I as Iterator>::Item>`
    |
-   = note: expected enum `Option<<I as Iterator>::Item>`
-              found enum `Option<&<I as Iterator>::Item>`
+   = note: expected enum `Option<_>`
+              found enum `Option<&_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
index 34aded73da5..54df0edf5a8 100644
--- a/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
+++ b/tests/ui/async-await/in-trait/async-example-desugared-boxed-in-trait.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     fn foo(&self) -> Pin<Box<dyn Future<Output = i32> + '_>>;
    |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected signature `fn(&i32) -> Pin<Box<dyn Future<Output = i32>>>`
-              found signature `fn(&i32) -> impl Future<Output = i32>`
+   = note: expected signature `fn(&_) -> Pin<Box<dyn Future<Output = i32>>>`
+              found signature `fn(&_) -> impl Future<Output = i32>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
index 891b30638ee..73c08531599 100644
--- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
+++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.rs
@@ -23,7 +23,7 @@ impl Foo for () {}
 fn test<T>()
 where
     T: Foo<test(): Send>,
-    //~^ ERROR ambiguous associated function `test` for `Foo`
+    //~^ ERROR ambiguous associated function `test` in bounds of `Foo`
 {
 }
 
diff --git a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr
index 7eaf3b82d98..4003aad6d03 100644
--- a/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr
+++ b/tests/ui/async-await/return-type-notation/super-method-bound-ambig.stderr
@@ -7,13 +7,18 @@ LL | #![feature(return_type_notation)]
    = note: see issue #109417 <https://github.com/rust-lang/rust/issues/109417> for more information
    = note: `#[warn(incomplete_features)]` on by default
 
-error: ambiguous associated function `test` for `Foo`
+error[E0221]: ambiguous associated function `test` in bounds of `Foo`
   --> $DIR/super-method-bound-ambig.rs:25:12
    |
+LL |     async fn test();
+   |     ---------------- ambiguous `test` from `for<'a> Super1<'a>`
+...
+LL |     async fn test();
+   |     ---------------- ambiguous `test` from `Super2`
+...
 LL |     T: Foo<test(): Send>,
-   |            ^^^^^^^^^^^^
-   |
-   = note: `test` is declared in two supertraits: `Super2` and `Super1<'a>`
+   |            ^^^^^^^^^^^^ ambiguous associated function `test`
 
 error: aborting due to 1 previous error; 1 warning emitted
 
+For more information about this error, try `rustc --explain E0221`.
diff --git a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
index 7ebea3c03d3..54d8f26f4ea 100644
--- a/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
+++ b/tests/ui/borrowck/regions-bound-missing-bound-in-impl.stderr
@@ -22,8 +22,8 @@ error[E0308]: method not compatible with trait
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
-              found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+   = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)`
 note: the lifetime `'c` as defined here...
   --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
    |
@@ -41,8 +41,8 @@ error[E0308]: method not compatible with trait
 LL |     fn wrong_bound1<'b,'c,'d:'a+'c>(self, b: Inv<'b>, c: Inv<'c>, d: Inv<'d>) {
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected signature `fn(&'a isize, Inv<'c>, Inv<'c>, Inv<'_>)`
-              found signature `fn(&'a isize, Inv<'_>, Inv<'c>, Inv<'_>)`
+   = note: expected signature `fn(&'a _, Inv<'c>, Inv<'c>, Inv<'_>)`
+              found signature `fn(&'a _, Inv<'_>, Inv<'c>, Inv<'_>)`
 note: the lifetime `'c` as defined here...
   --> $DIR/regions-bound-missing-bound-in-impl.rs:27:24
    |
diff --git a/tests/ui/box/issue-82446.stderr b/tests/ui/box/issue-82446.stderr
index 568d23c2cb7..66daaceffb1 100644
--- a/tests/ui/box/issue-82446.stderr
+++ b/tests/ui/box/issue-82446.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |         val
    |         ^^^ expected `Box<dyn MyTrait>`, found `&Box<dyn MyTrait>`
    |
-   = note: expected struct `Box<(dyn MyTrait + 'static)>`
-           found reference `&Box<(dyn MyTrait + 'static)>`
+   = note: expected struct `Box<_>`
+           found reference `&Box<_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/check-cfg/compact-values.rs b/tests/ui/check-cfg/compact-values.rs
index 13c072fe920..80cf75d2770 100644
--- a/tests/ui/check-cfg/compact-values.rs
+++ b/tests/ui/check-cfg/compact-values.rs
@@ -8,7 +8,7 @@
 #[cfg(target(os = "linux", arch = "arm"))]
 pub fn expected() {}
 
-#[cfg(target(os = "linux", arch = "X"))]
+#[cfg(target(os = "linux", pointer_width = "X"))]
 //~^ WARNING unexpected `cfg` condition value
 pub fn unexpected() {}
 
diff --git a/tests/ui/check-cfg/compact-values.stderr b/tests/ui/check-cfg/compact-values.stderr
index bb2f4915b5e..819b789c3e5 100644
--- a/tests/ui/check-cfg/compact-values.stderr
+++ b/tests/ui/check-cfg/compact-values.stderr
@@ -1,10 +1,10 @@
 warning: unexpected `cfg` condition value: `X`
   --> $DIR/compact-values.rs:11:28
    |
-LL | #[cfg(target(os = "linux", arch = "X"))]
-   |                            ^^^^^^^^^^
+LL | #[cfg(target(os = "linux", pointer_width = "X"))]
+   |                            ^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
+   = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
 warning: 1 warning emitted
diff --git a/tests/ui/check-cfg/values-target-json.rs b/tests/ui/check-cfg/values-target-json.rs
index e4c1b54cccc..47ac79e0dbf 100644
--- a/tests/ui/check-cfg/values-target-json.rs
+++ b/tests/ui/check-cfg/values-target-json.rs
@@ -10,10 +10,6 @@
 #[lang = "sized"]
 trait Sized {}
 
-#[cfg(target_os = "linuz")]
-//~^ WARNING unexpected `cfg` condition value
-fn target_os_linux_misspell() {}
-
 #[cfg(target_os = "linux")]
 fn target_os_linux() {}
 
diff --git a/tests/ui/check-cfg/values-target-json.stderr b/tests/ui/check-cfg/values-target-json.stderr
deleted file mode 100644
index e71149f337f..00000000000
--- a/tests/ui/check-cfg/values-target-json.stderr
+++ /dev/null
@@ -1,13 +0,0 @@
-warning: unexpected `cfg` condition value: `linuz`
-  --> $DIR/values-target-json.rs:13:7
-   |
-LL | #[cfg(target_os = "linuz")]
-   |       ^^^^^^^^^^^^-------
-   |                   |
-   |                   help: there is a expected value with a similar name: `"linux"`
-   |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `ericos`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
-   = note: `#[warn(unexpected_cfgs)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/check-cfg/well-known-values.rs b/tests/ui/check-cfg/well-known-values.rs
index 8b56c8729d8..39a470c202f 100644
--- a/tests/ui/check-cfg/well-known-values.rs
+++ b/tests/ui/check-cfg/well-known-values.rs
@@ -1,41 +1,104 @@
-// This test check that we lint on non well known values and that we don't lint on well known
-// values
+// This test check that we recognize all the well known config names
+// and that we correctly lint on unexpected values.
+//
+// This test also serve as an "anti-regression" for the well known
+// values since the suggestion shows them.
 //
 // check-pass
 // compile-flags: --check-cfg=cfg() -Z unstable-options
 
-#[cfg(target_os = "linuz")]
+#![feature(cfg_overflow_checks)]
+#![feature(cfg_relocation_model)]
+#![feature(cfg_sanitize)]
+#![feature(cfg_target_abi)]
+#![feature(cfg_target_has_atomic)]
+#![feature(cfg_target_has_atomic_equal_alignment)]
+#![feature(cfg_target_thread_local)]
+
+// This part makes sure that none of the well known names are
+// unexpected.
+//
+// BUT to make sure that no expected values changes without
+// being noticed we pass them a obviously wrong value so the
+// diagnostic prints the list of expected values.
+#[cfg(any(
+    // tidy-alphabetical-start
+    debug_assertions = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    doc = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    doctest = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    miri = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    overflow_checks = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    panic = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    proc_macro = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    relocation_model = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    sanitize = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_abi = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_arch = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_endian = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_env = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_family = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_feature = "_UNEXPECTED_VALUE", // currently *any* values are "expected"
+    target_has_atomic = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_has_atomic_load_store = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_os = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_pointer_width = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_thread_local = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    target_vendor = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    test = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    unix = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    windows = "_UNEXPECTED_VALUE",
+    //~^ WARN unexpected `cfg` condition value
+    // tidy-alphabetical-end
+))]
+fn unexpected_values() {}
+
+#[cfg(target_os = "linuz")] // testing that we suggest `linux`
 //~^ WARNING unexpected `cfg` condition value
 fn target_os_linux_misspell() {}
 
+// The #[cfg]s below serve as a safeguard to make sure we
+// don't lint when using an expected well-known name and
+// value, only a small subset of all possible expected
+// configs are tested, since we already test the names
+// above and don't need to test all values, just different
+// combinations (without value, with value, both...).
+
 #[cfg(target_os = "linux")]
 fn target_os_linux() {}
 
-#[cfg(target_has_atomic = "0")]
-//~^ WARNING unexpected `cfg` condition value
-fn target_has_atomic_invalid() {}
-
 #[cfg(target_has_atomic = "8")]
-fn target_has_atomic() {}
+fn target_has_atomic_8() {}
 
-#[cfg(unix = "aa")]
-//~^ WARNING unexpected `cfg` condition value
-fn unix_with_value() {}
+#[cfg(target_has_atomic)]
+fn target_has_atomic() {}
 
 #[cfg(unix)]
 fn unix() {}
 
-#[cfg(miri = "miri")]
-//~^ WARNING unexpected `cfg` condition value
-fn miri_with_value() {}
-
-#[cfg(miri)]
-fn miri() {}
-
-#[cfg(doc = "linux")]
-//~^ WARNING unexpected `cfg` condition value
-fn doc_with_value() {}
-
 #[cfg(doc)]
 fn doc() {}
 
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index 6877d8f5bb7..a6b9c75a142 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -1,53 +1,225 @@
-warning: unexpected `cfg` condition value: `linuz`
-  --> $DIR/well-known-values.rs:7:7
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:26:5
    |
-LL | #[cfg(target_os = "linuz")]
-   |       ^^^^^^^^^^^^-------
-   |                   |
-   |                   help: there is a expected value with a similar name: `"linux"`
+LL |     debug_assertions = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^----------------------
+   |                     |
+   |                     help: remove the value
    |
-   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
+   = note: no expected value for `debug_assertions`
    = note: `#[warn(unexpected_cfgs)]` on by default
 
-warning: unexpected `cfg` condition value: `0`
-  --> $DIR/well-known-values.rs:14:7
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:28:5
+   |
+LL |     doc = "_UNEXPECTED_VALUE",
+   |     ^^^----------------------
+   |        |
+   |        help: remove the value
+   |
+   = note: no expected value for `doc`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:30:5
+   |
+LL |     doctest = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^----------------------
+   |            |
+   |            help: remove the value
+   |
+   = note: no expected value for `doctest`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:32:5
+   |
+LL |     miri = "_UNEXPECTED_VALUE",
+   |     ^^^^----------------------
+   |         |
+   |         help: remove the value
+   |
+   = note: no expected value for `miri`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:34:5
+   |
+LL |     overflow_checks = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^----------------------
+   |                    |
+   |                    help: remove the value
+   |
+   = note: no expected value for `overflow_checks`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:36:5
    |
-LL | #[cfg(target_has_atomic = "0")]
-   |       ^^^^^^^^^^^^^^^^^^^^---
-   |                           |
-   |                           help: there is a expected value with a similar name: `"8"`
+LL |     panic = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `panic` are: `abort`, `unwind`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:38:5
+   |
+LL |     proc_macro = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^----------------------
+   |               |
+   |               help: remove the value
+   |
+   = note: no expected value for `proc_macro`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:40:5
+   |
+LL |     relocation_model = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `relocation_model` are: `dynamic-no-pic`, `pic`, `pie`, `ropi`, `ropi-rwpi`, `rwpi`, `static`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:42:5
+   |
+LL |     sanitize = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `sanitize` are: `address`, `cfi`, `hwaddress`, `kcfi`, `kernel-address`, `leak`, `memory`, `memtag`, `safestack`, `shadow-call-stack`, `thread`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:44:5
+   |
+LL |     target_abi = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_abi` are: ``, `abi64`, `abiv2`, `abiv2hf`, `eabi`, `eabihf`, `elf`, `fortanix`, `ilp32`, `llvm`, `macabi`, `sim`, `softfloat`, `spe`, `uwp`, `vec-extabi`, `x32`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:46:5
+   |
+LL |     target_arch = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_arch` are: `aarch64`, `arm`, `avr`, `bpf`, `csky`, `hexagon`, `loongarch64`, `m68k`, `mips`, `mips32r6`, `mips64`, `mips64r6`, `msp430`, `nvptx64`, `powerpc`, `powerpc64`, `riscv32`, `riscv64`, `s390x`, `sparc`, `sparc64`, `wasm32`, `wasm64`, `x86`, `x86_64`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:48:5
+   |
+LL |     target_endian = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_endian` are: `big`, `little`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:50:5
+   |
+LL |     target_env = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_env` are: ``, `eabihf`, `gnu`, `gnueabihf`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `ohos`, `psx`, `relibc`, `sgx`, `uclibc`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:52:5
+   |
+LL |     target_family = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_family` are: `unix`, `wasm`, `windows`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:55:5
+   |
+LL |     target_has_atomic = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = note: expected values for `target_has_atomic` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
 
-warning: unexpected `cfg` condition value: `aa`
-  --> $DIR/well-known-values.rs:21:7
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:57:5
    |
-LL | #[cfg(unix = "aa")]
-   |       ^^^^-------
-   |           |
-   |           help: remove the value
+LL |     target_has_atomic_equal_alignment = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_has_atomic_equal_alignment` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:59:5
+   |
+LL |     target_has_atomic_load_store = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_has_atomic_load_store` are: (none), `128`, `16`, `32`, `64`, `8`, `ptr`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:61:5
+   |
+LL |     target_os = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:63:5
+   |
+LL |     target_pointer_width = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_pointer_width` are: `16`, `32`, `64`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:65:5
+   |
+LL |     target_thread_local = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^----------------------
+   |                        |
+   |                        help: remove the value
+   |
+   = note: no expected value for `target_thread_local`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:67:5
+   |
+LL |     target_vendor = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: expected values for `target_vendor` are: `apple`, `espressif`, `fortanix`, `ibm`, `kmc`, `nintendo`, `nvidia`, `pc`, `sony`, `sun`, `unikraft`, `unknown`, `uwp`, `win7`, `wrs`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:69:5
+   |
+LL |     test = "_UNEXPECTED_VALUE",
+   |     ^^^^----------------------
+   |         |
+   |         help: remove the value
+   |
+   = note: no expected value for `test`
+
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:71:5
+   |
+LL |     unix = "_UNEXPECTED_VALUE",
+   |     ^^^^----------------------
+   |         |
+   |         help: remove the value
    |
    = note: no expected value for `unix`
 
-warning: unexpected `cfg` condition value: `miri`
-  --> $DIR/well-known-values.rs:28:7
+warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
+  --> $DIR/well-known-values.rs:73:5
    |
-LL | #[cfg(miri = "miri")]
-   |       ^^^^---------
-   |           |
-   |           help: remove the value
+LL |     windows = "_UNEXPECTED_VALUE",
+   |     ^^^^^^^----------------------
+   |            |
+   |            help: remove the value
    |
-   = note: no expected value for `miri`
+   = note: no expected value for `windows`
 
-warning: unexpected `cfg` condition value: `linux`
-  --> $DIR/well-known-values.rs:35:7
+warning: unexpected `cfg` condition value: `linuz`
+  --> $DIR/well-known-values.rs:79:7
    |
-LL | #[cfg(doc = "linux")]
-   |       ^^^----------
-   |          |
-   |          help: remove the value
+LL | #[cfg(target_os = "linuz")] // testing that we suggest `linux`
+   |       ^^^^^^^^^^^^-------
+   |                   |
+   |                   help: there is a expected value with a similar name: `"linux"`
    |
-   = note: no expected value for `doc`
+   = note: expected values for `target_os` are: `aix`, `android`, `cuda`, `dragonfly`, `emscripten`, `espidf`, `freebsd`, `fuchsia`, `haiku`, `hermit`, `horizon`, `hurd`, `illumos`, `ios`, `l4re`, `linux`, `macos`, `netbsd`, `none`, `nto`, `openbsd`, `psp`, `redox`, `solaris`, `solid_asp3`, `teeos`, `tvos`, `uefi`, `unknown`, `vita`, `vxworks`, `wasi`, `watchos`, `windows`, `xous`
 
-warning: 5 warnings emitted
+warning: 25 warnings emitted
 
diff --git a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
index e6ddc606897..e010f0502f8 100644
--- a/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
+++ b/tests/ui/closure-expected-type/expect-fn-supply-fn.stderr
@@ -25,8 +25,8 @@ error[E0308]: mismatched types
 LL |     with_closure_expecting_fn_with_free_region(|x: fn(&u32), y| {});
    |                                                 ^ one type is more general than the other
    |
-   = note: expected fn pointer `fn(&u32)`
-              found fn pointer `for<'a> fn(&'a u32)`
+   = note: expected fn pointer `fn(&_)`
+              found fn pointer `for<'a> fn(&'a _)`
 
 error[E0308]: mismatched types
   --> $DIR/expect-fn-supply-fn.rs:39:50
@@ -34,8 +34,8 @@ error[E0308]: mismatched types
 LL |     with_closure_expecting_fn_with_bound_region(|x: fn(&'x u32), y| {});
    |                                                  ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a> fn(&'a u32)`
-              found fn pointer `fn(&u32)`
+   = note: expected fn pointer `for<'a> fn(&'a _)`
+              found fn pointer `fn(&_)`
 
 error[E0308]: mismatched types
   --> $DIR/expect-fn-supply-fn.rs:48:50
@@ -43,8 +43,8 @@ error[E0308]: mismatched types
 LL |     with_closure_expecting_fn_with_bound_region(|x: Foo<'_>, y| {
    |                                                  ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a> fn(&'a u32)`
-              found fn pointer `fn(&u32)`
+   = note: expected fn pointer `for<'a> fn(&'a _)`
+              found fn pointer `fn(&_)`
 
 error: aborting due to 5 previous errors
 
diff --git a/tests/ui/closures/multiple-fn-bounds.stderr b/tests/ui/closures/multiple-fn-bounds.stderr
index d510fc585f6..325652ef14c 100644
--- a/tests/ui/closures/multiple-fn-bounds.stderr
+++ b/tests/ui/closures/multiple-fn-bounds.stderr
@@ -6,8 +6,8 @@ LL |     foo(move |x| v);
    |     |
    |     expected due to this
    |
-   = note: expected closure signature `fn(char) -> _`
-              found closure signature `for<'a> fn(&'a char) -> _`
+   = note: expected closure signature `fn(_) -> _`
+              found closure signature `for<'a> fn(&'a _) -> _`
 note: closure inferred to have a different signature due to this bound
   --> $DIR/multiple-fn-bounds.rs:1:11
    |
diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs
index bf8202ac152..d51696f9ebd 100644
--- a/tests/ui/const-generics/assoc_const_eq_diagnostic.rs
+++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.rs
@@ -9,9 +9,9 @@ pub trait Parse {
 }
 
 pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
-//~^ ERROR expected associated constant bound
-//~| ERROR expected associated constant bound
-//~| ERROR expected type
+//~^ ERROR expected type, found variant
+//~| ERROR expected constant, found type
+//~| ERROR expected constant, found type
 
 fn no_help() -> Mode::Cool {}
 //~^ ERROR expected type, found variant
diff --git a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
index 6d5cd45479e..3d724bb1642 100644
--- a/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
+++ b/tests/ui/const-generics/assoc_const_eq_diagnostic.stderr
@@ -16,30 +16,42 @@ LL | fn no_help() -> Mode::Cool {}
    |                 not a type
    |                 help: try using the variant's enum: `Mode`
 
-error: expected associated constant bound, found type
-  --> $DIR/assoc_const_eq_diagnostic.rs:11:28
+error: expected constant, found type
+  --> $DIR/assoc_const_eq_diagnostic.rs:11:35
    |
 LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
-   |                            ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }`
+   |                            ----   ^^^^^^^^^^ unexpected type
+   |                            |
+   |                            expected a constant because of this associated constant
    |
-note: associated constant defined here
+note: the associated constant is defined here
   --> $DIR/assoc_const_eq_diagnostic.rs:8:5
    |
 LL |     const MODE: Mode;
    |     ^^^^^^^^^^^^^^^^
+help: consider adding braces here
+   |
+LL | pub trait CoolStuff: Parse<MODE = { Mode::Cool }> {}
+   |                                   +            +
 
-error: expected associated constant bound, found type
-  --> $DIR/assoc_const_eq_diagnostic.rs:11:28
+error: expected constant, found type
+  --> $DIR/assoc_const_eq_diagnostic.rs:11:35
    |
 LL | pub trait CoolStuff: Parse<MODE = Mode::Cool> {}
-   |                            ^^^^^^^^^^^^^^^^^ help: if equating a const, try wrapping with braces: `MODE = { const }`
+   |                            ----   ^^^^^^^^^^ unexpected type
+   |                            |
+   |                            expected a constant because of this associated constant
    |
-note: associated constant defined here
+note: the associated constant is defined here
   --> $DIR/assoc_const_eq_diagnostic.rs:8:5
    |
 LL |     const MODE: Mode;
    |     ^^^^^^^^^^^^^^^^
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+help: consider adding braces here
+   |
+LL | pub trait CoolStuff: Parse<MODE = { Mode::Cool }> {}
+   |                                   +            +
 
 error: aborting due to 4 previous errors
 
diff --git a/tests/ui/consts/precise-drop-with-promoted.rs b/tests/ui/consts/precise-drop-with-promoted.rs
index 0c0514dd9d5..7cbe3c4e415 100644
--- a/tests/ui/consts/precise-drop-with-promoted.rs
+++ b/tests/ui/consts/precise-drop-with-promoted.rs
@@ -1,11 +1,6 @@
 // Regression test for issue #89938.
+// check-pass
 // compile-flags: --crate-type=lib
-// known-bug: #103507
-// failure-status: 101
-// normalize-stderr-test "note: .*\n\n" -> ""
-// normalize-stderr-test "thread 'rustc' panicked.*\n.*\n" -> ""
-// normalize-stderr-test "(error: internal compiler error: [^:]+):\d+:\d+: " -> "$1:LL:CC: "
-// rustc-env:RUST_BACKTRACE=0
 
 #![feature(const_precise_live_drops)]
 
diff --git a/tests/ui/consts/precise-drop-with-promoted.stderr b/tests/ui/consts/precise-drop-with-promoted.stderr
deleted file mode 100644
index a56672048eb..00000000000
--- a/tests/ui/consts/precise-drop-with-promoted.stderr
+++ /dev/null
@@ -1,6 +0,0 @@
-error: the compiler unexpectedly panicked. this is a bug.
-
-query stack during panic:
-#0 [mir_drops_elaborated_and_const_checked] elaborating drops for `f`
-#1 [analysis] running analysis passes on this crate
-end of query stack
diff --git a/tests/ui/coroutine/async_gen_fn.e2024.stderr b/tests/ui/coroutine/async_gen_fn.e2024.stderr
new file mode 100644
index 00000000000..d24cdbbc30d
--- /dev/null
+++ b/tests/ui/coroutine/async_gen_fn.e2024.stderr
@@ -0,0 +1,12 @@
+error[E0658]: gen blocks are experimental
+  --> $DIR/async_gen_fn.rs:4:1
+   |
+LL | async gen fn foo() {}
+   | ^^^^^^^^^
+   |
+   = note: see issue #117078 <https://github.com/rust-lang/rust/issues/117078> for more information
+   = help: add `#![feature(gen_blocks)]` to the crate attributes to enable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/coroutine/async_gen_fn.none.stderr b/tests/ui/coroutine/async_gen_fn.none.stderr
new file mode 100644
index 00000000000..7950251a75d
--- /dev/null
+++ b/tests/ui/coroutine/async_gen_fn.none.stderr
@@ -0,0 +1,18 @@
+error[E0670]: `async fn` is not permitted in Rust 2015
+  --> $DIR/async_gen_fn.rs:4:1
+   |
+LL | async gen fn foo() {}
+   | ^^^^^ to use `async fn`, switch to Rust 2018 or later
+   |
+   = help: pass `--edition 2021` to `rustc`
+   = note: for more on editions, read https://doc.rust-lang.org/edition-guide
+
+error: expected one of `extern`, `fn`, or `unsafe`, found `gen`
+  --> $DIR/async_gen_fn.rs:4:7
+   |
+LL | async gen fn foo() {}
+   |       ^^^ expected one of `extern`, `fn`, or `unsafe`
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0670`.
diff --git a/tests/ui/coroutine/async_gen_fn.rs b/tests/ui/coroutine/async_gen_fn.rs
index f8860e07f6c..20564106f99 100644
--- a/tests/ui/coroutine/async_gen_fn.rs
+++ b/tests/ui/coroutine/async_gen_fn.rs
@@ -1,11 +1,9 @@
-// edition: 2024
-// compile-flags: -Zunstable-options
-#![feature(gen_blocks)]
-
-// async generators are not yet supported, so this test makes sure they make some kind of reasonable
-// error.
+// revisions: e2024 none
+//[e2024] compile-flags: --edition 2024 -Zunstable-options
 
 async gen fn foo() {}
-//~^ `async gen` functions are not supported
+//[none]~^ ERROR: `async fn` is not permitted in Rust 2015
+//[none]~| ERROR: expected one of `extern`, `fn`, or `unsafe`, found `gen`
+//[e2024]~^^^ ERROR: gen blocks are experimental
 
 fn main() {}
diff --git a/tests/ui/coroutine/async_gen_fn.stderr b/tests/ui/coroutine/async_gen_fn.stderr
deleted file mode 100644
index 6857ebe6c79..00000000000
--- a/tests/ui/coroutine/async_gen_fn.stderr
+++ /dev/null
@@ -1,8 +0,0 @@
-error: `async gen` functions are not supported
-  --> $DIR/async_gen_fn.rs:8:1
-   |
-LL | async gen fn foo() {}
-   | ^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/coroutine/async_gen_fn_iter.rs b/tests/ui/coroutine/async_gen_fn_iter.rs
new file mode 100644
index 00000000000..4fa29e1095a
--- /dev/null
+++ b/tests/ui/coroutine/async_gen_fn_iter.rs
@@ -0,0 +1,100 @@
+// edition: 2024
+// compile-flags: -Zunstable-options
+// run-pass
+
+#![feature(gen_blocks, async_iterator)]
+
+// make sure that a ridiculously simple async gen fn works as an iterator.
+
+async fn pause() {
+    // this doesn't actually do anything, lol
+}
+
+async fn one() -> i32 {
+    1
+}
+
+async fn two() -> i32 {
+    2
+}
+
+async gen fn foo() -> i32 {
+    yield one().await;
+    pause().await;
+    yield two().await;
+    pause().await;
+    yield 3;
+    pause().await;
+}
+
+async fn async_main() {
+    let mut iter = std::pin::pin!(foo());
+    assert_eq!(iter.next().await, Some(1));
+    assert_eq!(iter.as_mut().next().await, Some(2));
+    assert_eq!(iter.as_mut().next().await, Some(3));
+    assert_eq!(iter.as_mut().next().await, None);
+
+    // Test that the iterator is fused and does not panic
+    assert_eq!(iter.as_mut().next().await, None);
+    assert_eq!(iter.as_mut().next().await, None);
+}
+
+// ------------------------------------------------------------------------- //
+// Implementation Details Below...
+
+use std::pin::Pin;
+use std::task::*;
+use std::async_iter::AsyncIterator;
+use std::future::Future;
+
+trait AsyncIterExt {
+    fn next(&mut self) -> Next<'_, Self>;
+}
+
+impl<T> AsyncIterExt for T {
+    fn next(&mut self) -> Next<'_, Self> {
+        Next { s: self }
+    }
+}
+
+struct Next<'s, S: ?Sized> {
+    s: &'s mut S,
+}
+
+impl<'s, S: AsyncIterator> Future for Next<'s, S> where S: Unpin {
+    type Output = Option<S::Item>;
+
+    fn poll(mut self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Option<S::Item>> {
+        Pin::new(&mut *self.s).poll_next(cx)
+    }
+}
+
+pub fn noop_waker() -> Waker {
+    let raw = RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE);
+
+    // SAFETY: the contracts for RawWaker and RawWakerVTable are upheld
+    unsafe { Waker::from_raw(raw) }
+}
+
+const NOOP_WAKER_VTABLE: RawWakerVTable = RawWakerVTable::new(noop_clone, noop, noop, noop);
+
+unsafe fn noop_clone(_p: *const ()) -> RawWaker {
+    RawWaker::new(std::ptr::null(), &NOOP_WAKER_VTABLE)
+}
+
+unsafe fn noop(_p: *const ()) {}
+
+fn main() {
+    let mut fut = async_main();
+
+    // Poll loop, just to test the future...
+    let waker = noop_waker();
+    let ctx = &mut Context::from_waker(&waker);
+
+    loop {
+        match unsafe { Pin::new_unchecked(&mut fut).poll(ctx) } {
+            Poll::Pending => {}
+            Poll::Ready(()) => break,
+        }
+    }
+}
diff --git a/tests/ui/error-codes/E0221.stderr b/tests/ui/error-codes/E0221.stderr
index e600acf7834..07e7485b67e 100644
--- a/tests/ui/error-codes/E0221.stderr
+++ b/tests/ui/error-codes/E0221.stderr
@@ -28,7 +28,7 @@ LL |     fn test() {
 LL |         let _: Self::Err;
    |                ^^^^^^^^^ ambiguous associated type `Err`
    |
-   = note: associated type `Self` could derive from `FromStr`
+   = note: associated type `Err` could derive from `FromStr`
 help: use fully-qualified syntax to disambiguate
    |
 LL |         let _: <Self as My>::Err;
diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.rs b/tests/ui/feature-gates/feature-gate-never_patterns.rs
index 69e9f62abf0..ca5ce3b9489 100644
--- a/tests/ui/feature-gates/feature-gate-never_patterns.rs
+++ b/tests/ui/feature-gates/feature-gate-never_patterns.rs
@@ -12,7 +12,7 @@ fn main() {
     unsafe {
         let ptr: *const Void = NonNull::dangling().as_ptr();
         match *ptr {
-            ! => {} //~ ERROR `!` patterns are experimental
+            ! //~ ERROR `!` patterns are experimental
         }
     }
 
diff --git a/tests/ui/feature-gates/feature-gate-never_patterns.stderr b/tests/ui/feature-gates/feature-gate-never_patterns.stderr
index b7290eeb36d..2354a3b0476 100644
--- a/tests/ui/feature-gates/feature-gate-never_patterns.stderr
+++ b/tests/ui/feature-gates/feature-gate-never_patterns.stderr
@@ -18,7 +18,7 @@ LL |     let (Ok(_x) | Err(&!)) = res.as_ref();
 error[E0658]: `!` patterns are experimental
   --> $DIR/feature-gate-never_patterns.rs:15:13
    |
-LL |             ! => {}
+LL |             !
    |             ^
    |
    = note: see issue #118155 <https://github.com/rust-lang/rust/issues/118155> for more information
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
index 1bdb2574ead..a15b01618f5 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.cfg.stderr
@@ -15,13 +15,18 @@ LL | fn foo<T: Trait<m(): Send>>() {}
    |                  |
    |                  help: remove these parentheses
 
-error[E0220]: associated type `m` not found for `Trait`
+error: expected type, found function
   --> $DIR/feature-gate-return_type_notation.rs:14:17
    |
 LL | fn foo<T: Trait<m(): Send>>() {}
-   |                 ^ associated type `m` not found
+   |                 ^ unexpected function
+   |
+note: the associated function is defined here
+  --> $DIR/feature-gate-return_type_notation.rs:10:5
+   |
+LL |     async fn m();
+   |     ^^^^^^^^^^^^^
 
 error: aborting due to 3 previous errors
 
-Some errors have detailed explanations: E0220, E0658.
-For more information about an error, try `rustc --explain E0220`.
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/feature-gates/feature-gate-return_type_notation.rs b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
index 86e2c48e188..60ac9f8d4f1 100644
--- a/tests/ui/feature-gates/feature-gate-return_type_notation.rs
+++ b/tests/ui/feature-gates/feature-gate-return_type_notation.rs
@@ -14,7 +14,7 @@ trait Trait {
 fn foo<T: Trait<m(): Send>>() {}
 //[cfg]~^ ERROR return type notation is experimental
 //[cfg]~| ERROR parenthesized generic arguments cannot be used in associated type constraints
-//[cfg]~| ERROR associated type `m` not found for `Trait`
+//[cfg]~| ERROR expected type, found function
 //[no]~^^^^ WARN return type notation is experimental
 //[no]~| WARN unstable syntax can change at any point in the future, causing a hard error!
 
diff --git a/tests/ui/fn/fn-pointer-mismatch.rs b/tests/ui/fn/fn-pointer-mismatch.rs
index 0597478cb42..1c50d8b0f8b 100644
--- a/tests/ui/fn/fn-pointer-mismatch.rs
+++ b/tests/ui/fn/fn-pointer-mismatch.rs
@@ -35,20 +35,20 @@ fn main() {
     // suggest removing reference
     let c: fn(u32) -> u32 = &foo;
     //~^ ERROR mismatched types
-    //~| expected fn pointer `fn(u32) -> u32`
-    //~| found reference `&fn(u32) -> u32 {foo}`
+    //~| expected fn pointer `fn(_) -> _`
+    //~| found reference `&fn(_) -> _ {foo}`
 
     // suggest using reference
     let d: &fn(u32) -> u32 = foo;
     //~^ ERROR mismatched types
-    //~| expected reference `&fn(u32) -> u32`
-    //~| found fn item `fn(u32) -> u32 {foo}`
+    //~| expected reference `&fn(_) -> _`
+    //~| found fn item `fn(_) -> _ {foo}`
 
     // suggest casting with reference
     let e: &fn(u32) -> u32 = &foo;
     //~^ ERROR mismatched types
-    //~| expected reference `&fn(u32) -> u32`
-    //~| found reference `&fn(u32) -> u32 {foo}`
+    //~| expected reference `&fn(_) -> _`
+    //~| found reference `&fn(_) -> _ {foo}`
 
     // OK
     let mut z: fn(u32) -> u32 = foo as fn(u32) -> u32;
diff --git a/tests/ui/fn/fn-pointer-mismatch.stderr b/tests/ui/fn/fn-pointer-mismatch.stderr
index 87ece845b83..9cda11639d0 100644
--- a/tests/ui/fn/fn-pointer-mismatch.stderr
+++ b/tests/ui/fn/fn-pointer-mismatch.stderr
@@ -6,8 +6,8 @@ LL |     let g = if n % 2 == 0 { &foo } else { &bar };
    |                             |
    |                             expected because of this
    |
-   = note: expected reference `&fn(u32) -> u32 {foo}`
-              found reference `&fn(u32) -> u32 {bar}`
+   = note: expected reference `&fn(_) -> _ {foo}`
+              found reference `&fn(_) -> _ {bar}`
    = note: different fn items have unique types, even if their signatures are the same
    = help: consider casting both fn items to fn pointers using `as fn(u32) -> u32`
 
@@ -47,8 +47,8 @@ LL |     let c: fn(u32) -> u32 = &foo;
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `fn(u32) -> u32`
-               found reference `&fn(u32) -> u32 {foo}`
+   = note: expected fn pointer `fn(_) -> _`
+               found reference `&fn(_) -> _ {foo}`
 help: consider removing the reference
    |
 LL |     let c: fn(u32) -> u32 = foo;
@@ -62,8 +62,8 @@ LL |     let d: &fn(u32) -> u32 = foo;
    |            |
    |            expected due to this
    |
-   = note: expected reference `&fn(u32) -> u32`
-                found fn item `fn(u32) -> u32 {foo}`
+   = note: expected reference `&fn(_) -> _`
+                found fn item `fn(_) -> _ {foo}`
 help: consider using a reference
    |
 LL |     let d: &fn(u32) -> u32 = &foo;
@@ -77,8 +77,8 @@ LL |     let e: &fn(u32) -> u32 = &foo;
    |            |
    |            expected due to this
    |
-   = note: expected reference `&fn(u32) -> u32`
-              found reference `&fn(u32) -> u32 {foo}`
+   = note: expected reference `&fn(_) -> _`
+              found reference `&fn(_) -> _ {foo}`
    = note: fn items are distinct from fn pointers
 help: consider casting to a fn pointer
    |
diff --git a/tests/ui/generic-associated-types/issue-88360.stderr b/tests/ui/generic-associated-types/issue-88360.stderr
index 64cd55e684c..49d36acadd6 100644
--- a/tests/ui/generic-associated-types/issue-88360.stderr
+++ b/tests/ui/generic-associated-types/issue-88360.stderr
@@ -9,8 +9,8 @@ LL |     fn copy(&self) -> Self::Gat<'_> where T: Copy {
 LL |         *self.test()
    |         ^^^^^^^^^^^^ expected `&T`, found type parameter `T`
    |
-   = note:   expected reference `&T`
-           found type parameter `T`
+   = note:   expected reference `&_`
+           found type parameter `_`
 help: consider removing deref here
    |
 LL -         *self.test()
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
index 55353999b67..9ffc2190d20 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.rs
@@ -17,7 +17,7 @@ fn main() {
         }
         match x as i32 {
             0..5+1 => errors_only.push(x),
-            //~^ error: expected one of `=>`, `if`, or `|`, found `+`
+            //~^ error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+`
             1 | -3..0 => first_or.push(x),
             y @ (0..5 | 6) => or_two.push(y),
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
index 19ebcaf0f36..05235c9b922 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions1.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=>`, `if`, or `|`, found `+`
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `+`
   --> $DIR/range_pat_interactions1.rs:19:17
    |
 LL |             0..5+1 => errors_only.push(x),
-   |                 ^ expected one of `=>`, `if`, or `|`
+   |                 ^ expected one of `,`, `=>`, `if`, `|`, or `}`
 
 error[E0408]: variable `n` is not bound in all patterns
   --> $DIR/range_pat_interactions1.rs:10:25
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
index 4615ebd688a..b212bfbe093 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.rs
@@ -9,7 +9,7 @@ fn main() {
         match x as i32 {
             0..=(5+1) => errors_only.push(x),
             //~^ error: inclusive range with no end
-            //~| error: expected one of `=>`, `if`, or `|`, found `(`
+            //~| error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(`
             1 | -3..0 => first_or.push(x),
             y @ (0..5 | 6) => or_two.push(y),
             y @ 0..const { 5 + 1 } => assert_eq!(y, 5),
diff --git a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
index 13a5542a474..0129f927e34 100644
--- a/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
+++ b/tests/ui/half-open-range-patterns/range_pat_interactions2.stderr
@@ -6,11 +6,11 @@ LL |             0..=(5+1) => errors_only.push(x),
    |
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: expected one of `=>`, `if`, or `|`, found `(`
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `(`
   --> $DIR/range_pat_interactions2.rs:10:17
    |
 LL |             0..=(5+1) => errors_only.push(x),
-   |                 ^ expected one of `=>`, `if`, or `|`
+   |                 ^ expected one of `,`, `=>`, `if`, `|`, or `}`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
index 7cb7edfafeb..d7f0860a026 100644
--- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_b_ret_a_vs_bound_a_ret_a.stderr
@@ -8,8 +8,8 @@ LL | / check! { bound_a_b_ret_a_vs_bound_a_ret_a: (for<'a,'b> fn(&'a u32, &'b u3
 LL | | for<'a>    fn(&'a u32, &'a u32) -> &'a u32) }
    | |_____________________________________________- in this macro invocation
    |
-   = note: expected enum `Option<for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32>`
-              found enum `Option<for<'a> fn(&'a u32, &'a u32) -> &'a u32>`
+   = note: expected enum `Option<for<'a, 'b> fn(&'a _, &'b _) -> &'a _>`
+              found enum `Option<for<'a> fn(&'a _, &'a _) -> &'a _>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr
index c6adbd91e78..9b5ca3b2056 100644
--- a/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr
+++ b/tests/ui/higher-ranked/subtype/hr-subtype.bound_a_vs_free_x.stderr
@@ -8,8 +8,8 @@ LL | / check! { bound_a_vs_free_x: (for<'a> fn(&'a u32),
 LL | | fn(&'x u32)) }
    | |______________- in this macro invocation
    |
-   = note: expected enum `Option<for<'a> fn(&'a u32)>`
-              found enum `Option<fn(&u32)>`
+   = note: expected enum `Option<for<'a> fn(&'a _)>`
+              found enum `Option<fn(&_)>`
    = note: this error originates in the macro `check` (in Nightly builds, run with -Z macro-backtrace for more info)
 
 error: aborting due to 1 previous error
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr
index f269babcf71..2d6b8063f69 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-exists-forall-fn.stderr
@@ -6,8 +6,8 @@ LL |     let _: for<'b> fn(&'b u32) = foo();
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `for<'b> fn(&'b u32)`
-              found fn pointer `fn(&u32)`
+   = note: expected fn pointer `for<'b> fn(&'b _)`
+              found fn pointer `fn(&_)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/in-trait/specialization-broken.stderr b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
index 25c0adeddbd..b8a8e2401b2 100644
--- a/tests/ui/impl-trait/in-trait/specialization-broken.stderr
+++ b/tests/ui/impl-trait/in-trait/specialization-broken.stderr
@@ -15,8 +15,8 @@ note: type in trait
    |
 LL |     fn bar(&self) -> impl Sized;
    |                      ^^^^^^^^^^
-   = note: expected signature `fn(&U) -> impl Sized`
-              found signature `fn(&U) -> U`
+   = note: expected signature `fn(&_) -> impl Sized`
+              found signature `fn(&_) -> U`
 
 error: method with return-position `impl Trait` in trait cannot be specialized
   --> $DIR/specialization-broken.rs:15:5
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 fe765271bd2..07ac1a37e75 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
@@ -18,8 +18,8 @@ LL |         fn eq(&self, _other: &(Foo, i32)) -> bool {
    |                              expected `a::Bar`, found opaque type
    |                              help: change the parameter type to match the trait: `&(a::Bar, i32)`
    |
-   = note: expected signature `fn(&a::Bar, &(a::Bar, i32)) -> _`
-              found signature `fn(&a::Bar, &(a::Foo, i32)) -> _`
+   = note: expected signature `fn(&a::Bar, &(a::Bar, _)) -> _`
+              found signature `fn(&a::Bar, &(a::Foo, _)) -> _`
 
 error: unconstrained opaque type
   --> $DIR/recursive-type-alias-impl-trait-declaration-too-subtle.rs:18:16
@@ -41,8 +41,8 @@ LL |         fn eq(&self, _other: &(Bar, i32)) -> bool {
    |                              expected opaque type, found `b::Bar`
    |                              help: change the parameter type to match the trait: `&(b::Foo, i32)`
    |
-   = note: expected signature `fn(&b::Bar, &(b::Foo, i32)) -> _`
-              found signature `fn(&b::Bar, &(b::Bar, i32)) -> _`
+   = 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
    |
diff --git a/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs
new file mode 100644
index 00000000000..b373d39f4d9
--- /dev/null
+++ b/tests/ui/implied-bounds/auxiliary/bevy_ecs.rs
@@ -0,0 +1,18 @@
+// Related to Bevy regression #118553
+
+pub trait WorldQuery {}
+impl WorldQuery for &u8 {}
+
+pub struct Query<Q: WorldQuery>(Q);
+
+pub trait SystemParam {
+    type State;
+}
+impl<Q: WorldQuery + 'static> SystemParam for Query<Q> {
+    type State = ();
+    // `Q: 'static` is required because we need the TypeId of Q ...
+}
+
+pub struct ParamSet<T: SystemParam>(T)
+where
+    T::State: Sized;
diff --git a/tests/ui/implied-bounds/bevy_world_query.rs b/tests/ui/implied-bounds/bevy_world_query.rs
new file mode 100644
index 00000000000..f8e64632676
--- /dev/null
+++ b/tests/ui/implied-bounds/bevy_world_query.rs
@@ -0,0 +1,11 @@
+// aux-crate:bevy_ecs=bevy_ecs.rs
+// check-pass
+// Related to Bevy regression #118553
+
+extern crate bevy_ecs;
+
+use bevy_ecs::*;
+
+fn handler<'a>(_: ParamSet<Query<&'a u8>>) {}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/from-trait-impl.rs b/tests/ui/implied-bounds/from-trait-impl.rs
new file mode 100644
index 00000000000..d13fddd9b8d
--- /dev/null
+++ b/tests/ui/implied-bounds/from-trait-impl.rs
@@ -0,0 +1,24 @@
+// check-pass
+// known-bug: #109628
+
+trait Trait {
+    type Assoc;
+}
+
+impl<X: 'static> Trait for (X,) {
+    type Assoc = ();
+}
+
+struct Foo<T: Trait>(T)
+where
+    T::Assoc: Clone; // any predicate using `T::Assoc` works here
+
+fn func1(foo: Foo<(&str,)>) {
+    let _: &'static str = foo.0.0;
+}
+
+trait TestTrait {}
+
+impl<X> TestTrait for [Foo<(X,)>; 1] {}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/gluon_salsa.rs b/tests/ui/implied-bounds/gluon_salsa.rs
new file mode 100644
index 00000000000..98951af8ac2
--- /dev/null
+++ b/tests/ui/implied-bounds/gluon_salsa.rs
@@ -0,0 +1,31 @@
+// check-pass
+// Related to Bevy regression #118553
+
+pub trait QueryBase {
+    type Db;
+}
+
+pub trait AsyncQueryFunction<'f>: // 'f is important
+    QueryBase<Db = <Self as AsyncQueryFunction<'f>>::SendDb> // bound is important
+{
+    type SendDb;
+}
+
+pub struct QueryTable<'me, Q, DB> {
+    _q: Option<Q>,
+    _db: Option<DB>,
+    _marker: Option<&'me ()>,
+}
+
+impl<'me, Q> QueryTable<'me, Q, <Q as QueryBase>::Db>
+// projection is important
+//   ^^^ removing 'me (and in QueryTable) gives a different error
+where
+    Q: for<'f> AsyncQueryFunction<'f>,
+{
+    pub fn get_async<'a>(&'a mut self) {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/issue-100690.stderr b/tests/ui/implied-bounds/issue-100690.stderr
index 49f2fcd0a67..df069d875ce 100644
--- a/tests/ui/implied-bounds/issue-100690.stderr
+++ b/tests/ui/implied-bounds/issue-100690.stderr
@@ -6,8 +6,8 @@ LL |         real_dispatch(f)
    |         |
    |         required by a bound introduced by this call
    |
-   = note: expected a closure with arguments `(&mut UIView<'a, T>,)`
-              found a closure with arguments `(&mut UIView<'_, T>,)`
+   = note: expected a closure with arguments `(&mut UIView<'a, _>,)`
+              found a closure with arguments `(&mut UIView<'_, _>,)`
 note: required by a bound in `real_dispatch`
   --> $DIR/issue-100690.rs:9:8
    |
diff --git a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr
index abffee57a0f..e020230d86a 100644
--- a/tests/ui/implied-bounds/normalization-nested.lifetime.stderr
+++ b/tests/ui/implied-bounds/normalization-nested.lifetime.stderr
@@ -1,11 +1,11 @@
 error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement
-  --> $DIR/normalization-nested.rs:35:20
+  --> $DIR/normalization-nested.rs:35:28
    |
-LL | pub fn test<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
-   |                    ^^^^^^^^^^^^^^^^
-   |                    |
-   |                    this data with lifetime `'x`...
-   |                    ...is used and required to live as long as `'static` here
+LL | pub fn test_wfcheck<'x>(_: Map<Vec<&'x ()>>) {}
+   |                            ^^^^^^^^^^^^^^^^
+   |                            |
+   |                            this data with lifetime `'x`...
+   |                            ...is used and required to live as long as `'static` here
    |
 note: `'static` lifetime requirement introduced by this bound
   --> $DIR/normalization-nested.rs:33:14
@@ -13,6 +13,21 @@ note: `'static` lifetime requirement introduced by this bound
 LL |     I::Item: 'static;
    |              ^^^^^^^
 
-error: aborting due to 1 previous error
+error[E0759]: `fn` parameter has lifetime `'x` but it needs to satisfy a `'static` lifetime requirement
+  --> $DIR/normalization-nested.rs:37:29
+   |
+LL | pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
+   |                             ^^^^^^^^^^^^^^^^
+   |                             |
+   |                             this data with lifetime `'x`...
+   |                             ...is used and required to live as long as `'static` here
+   |
+note: `'static` lifetime requirement introduced by this bound
+  --> $DIR/normalization-nested.rs:33:14
+   |
+LL |     I::Item: 'static;
+   |              ^^^^^^^
+
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0759`.
diff --git a/tests/ui/implied-bounds/normalization-nested.rs b/tests/ui/implied-bounds/normalization-nested.rs
index 5f1cbb3f697..87903783a67 100644
--- a/tests/ui/implied-bounds/normalization-nested.rs
+++ b/tests/ui/implied-bounds/normalization-nested.rs
@@ -32,7 +32,9 @@ where
     I: Iter,
     I::Item: 'static;
 
-pub fn test<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
+pub fn test_wfcheck<'x>(_: Map<Vec<&'x ()>>) {}
+
+pub fn test_borrowck<'x>(_: Map<Vec<&'x ()>>, s: &'x str) -> &'static str {
     s
 }
 
diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr
new file mode 100644
index 00000000000..96c76ca9ac3
--- /dev/null
+++ b/tests/ui/implied-bounds/normalization-preserve-equality.borrowck.stderr
@@ -0,0 +1,28 @@
+error: lifetime may not live long enough
+  --> $DIR/normalization-preserve-equality.rs:24:1
+   |
+LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
+   | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |                |   |
+   | |                |   lifetime `'b` defined here
+   | |                lifetime `'a` defined here
+   | requires that `'a` must outlive `'b`
+   |
+   = help: consider adding the following bound: `'a: 'b`
+
+error: lifetime may not live long enough
+  --> $DIR/normalization-preserve-equality.rs:24:1
+   |
+LL | fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
+   | ^^^^^^^^^^^^^^^^^--^^--^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   | |                |   |
+   | |                |   lifetime `'b` defined here
+   | |                lifetime `'a` defined here
+   | requires that `'b` must outlive `'a`
+   |
+   = help: consider adding the following bound: `'b: 'a`
+
+help: `'a` and `'b` must be the same: replace one with the other
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/implied-bounds/normalization-preserve-equality.rs b/tests/ui/implied-bounds/normalization-preserve-equality.rs
new file mode 100644
index 00000000000..557c171e515
--- /dev/null
+++ b/tests/ui/implied-bounds/normalization-preserve-equality.rs
@@ -0,0 +1,28 @@
+// Both revisions should pass. `borrowck` revision is a bug!
+//
+// revisions: wfcheck borrowck
+// [wfcheck] check-pass
+// [borrowck] check-fail
+// [borrowck] known-bug: #106569
+
+struct Equal<'a, 'b>(&'a &'b (), &'b &'a ()); // implies 'a == 'b
+
+trait Trait {
+    type Ty;
+}
+
+impl<'x> Trait for Equal<'x, 'x> {
+    type Ty = ();
+}
+
+trait WfCheckTrait {}
+
+#[cfg(wfcheck)]
+impl<'a, 'b> WfCheckTrait for (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>) {}
+
+#[cfg(borrowck)]
+fn test_borrowck<'a, 'b>(_: (<Equal<'a, 'b> as Trait>::Ty, Equal<'a, 'b>)) {
+    let _ = None::<Equal<'a, 'b>>;
+}
+
+fn main() {}
diff --git a/tests/ui/implied-bounds/sod_service_chain.rs b/tests/ui/implied-bounds/sod_service_chain.rs
new file mode 100644
index 00000000000..f45ced71f75
--- /dev/null
+++ b/tests/ui/implied-bounds/sod_service_chain.rs
@@ -0,0 +1,37 @@
+// check-pass
+// Related to crater regressions on #118553
+
+pub trait Debug {}
+
+pub trait Service {
+    type Input;
+    type Output;
+    type Error;
+}
+
+pub struct ServiceChain<P, S> {
+    prev: P,
+    service: S,
+}
+impl<P: Service, S: Service<Input = P::Output>> Service for ServiceChain<P, S>
+where
+    P::Error: 'static,
+    S::Error: 'static,
+{
+    type Input = P::Input;
+    type Output = S::Output;
+    type Error = ();
+}
+
+pub struct ServiceChainBuilder<P: Service, S: Service<Input = P::Output>> {
+    chain: ServiceChain<P, S>,
+}
+impl<P: Service, S: Service<Input = P::Output>> ServiceChainBuilder<P, S> {
+    pub fn next<NS: Service<Input = S::Output>>(
+        self,
+    ) -> ServiceChainBuilder<ServiceChain<P, S>, NS> {
+        panic!();
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/issues/issue-17905-2.stderr b/tests/ui/issues/issue-17905-2.stderr
index 88b5fbec6cf..c66cb222489 100644
--- a/tests/ui/issues/issue-17905-2.stderr
+++ b/tests/ui/issues/issue-17905-2.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn say(self: &Pair<&str, isize>) {
    |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected struct `Pair<&str, _>`
-              found struct `Pair<&str, _>`
+   = note: expected struct `Pair<&_, _>`
+              found struct `Pair<&_, _>`
 note: the anonymous lifetime defined here...
   --> $DIR/issue-17905-2.rs:8:24
    |
@@ -23,8 +23,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn say(self: &Pair<&str, isize>) {
    |                  ^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected struct `Pair<&str, _>`
-              found struct `Pair<&str, _>`
+   = note: expected struct `Pair<&_, _>`
+              found struct `Pair<&_, _>`
 note: the anonymous lifetime as defined here...
   --> $DIR/issue-17905-2.rs:5:5
    |
diff --git a/tests/ui/issues/issue-20225.stderr b/tests/ui/issues/issue-20225.stderr
index b34aa8e1ff5..2d24a5bbd50 100644
--- a/tests/ui/issues/issue-20225.stderr
+++ b/tests/ui/issues/issue-20225.stderr
@@ -9,8 +9,8 @@ LL |   extern "rust-call" fn call(&self, (_,): (T,)) {}
    |                                           expected `&'a T`, found type parameter `T`
    |                                           help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected signature `extern "rust-call" fn(&Foo, (&'a T,))`
-              found signature `extern "rust-call" fn(&Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(&Foo, (&'a _,))`
+              found signature `extern "rust-call" fn(&Foo, (_,))`
 
 error[E0053]: method `call_mut` has an incompatible type for trait
   --> $DIR/issue-20225.rs:11:51
@@ -23,8 +23,8 @@ LL |   extern "rust-call" fn call_mut(&mut self, (_,): (T,)) {}
    |                                                   expected `&'a T`, found type parameter `T`
    |                                                   help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a T,))`
-              found signature `extern "rust-call" fn(&mut Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(&mut Foo, (&'a _,))`
+              found signature `extern "rust-call" fn(&mut Foo, (_,))`
 
 error[E0053]: method `call_once` has an incompatible type for trait
   --> $DIR/issue-20225.rs:18:47
@@ -38,8 +38,8 @@ LL |   extern "rust-call" fn call_once(self, (_,): (T,)) {}
    |                                               expected `&'a T`, found type parameter `T`
    |                                               help: change the parameter type to match the trait: `(&'a T,)`
    |
-   = note: expected signature `extern "rust-call" fn(Foo, (&'a T,))`
-              found signature `extern "rust-call" fn(Foo, (T,))`
+   = note: expected signature `extern "rust-call" fn(Foo, (&'a _,))`
+              found signature `extern "rust-call" fn(Foo, (_,))`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/issues/issue-24322.stderr b/tests/ui/issues/issue-24322.stderr
index b260d027388..d078069addc 100644
--- a/tests/ui/issues/issue-24322.stderr
+++ b/tests/ui/issues/issue-24322.stderr
@@ -6,8 +6,8 @@ LL |     let x: &fn(&B) -> u32 = &B::func;
    |            |
    |            expected due to this
    |
-   = note: expected reference `&for<'a> fn(&'a B) -> u32`
-              found reference `&for<'a> fn(&'a B) -> u32 {B::func}`
+   = note: expected reference `&for<'a> fn(&'a B) -> _`
+              found reference `&for<'a> fn(&'a B) -> _ {B::func}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/issues/issue-37884.stderr b/tests/ui/issues/issue-37884.stderr
index 633abeb6f22..b7c0095d682 100644
--- a/tests/ui/issues/issue-37884.stderr
+++ b/tests/ui/issues/issue-37884.stderr
@@ -4,8 +4,8 @@ error[E0308]: method not compatible with trait
 LL |     fn next(&'a mut self) -> Option<Self::Item>
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected signature `fn(&mut RepeatMut<'a, T>) -> Option<_>`
-              found signature `fn(&'a mut RepeatMut<'a, T>) -> Option<_>`
+   = note: expected signature `fn(&mut RepeatMut<'_, _>) -> Option<_>`
+              found signature `fn(&'a mut RepeatMut<'_, _>) -> Option<_>`
 note: the anonymous lifetime as defined here...
   --> $DIR/issue-37884.rs:6:5
    |
diff --git a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr
index 065787cab08..1d41335036e 100644
--- a/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr
+++ b/tests/ui/let-else/let-else-binding-explicit-mut-annotated.stderr
@@ -6,8 +6,8 @@ LL |     let Some(n): &mut Option<i32> = &&Some(5i32) else { return };
    |                  |
    |                  expected due to this
    |
-   = note: expected mutable reference `&mut Option<i32>`
-                      found reference `&&Option<i32>`
+   = note: expected mutable reference `&mut Option<_>`
+                      found reference `&&Option<_>`
 
 error[E0308]: mismatched types
   --> $DIR/let-else-binding-explicit-mut-annotated.rs:13:37
@@ -17,8 +17,8 @@ LL |     let Some(n): &mut Option<i32> = &&mut Some(5i32) else { return };
    |                  |
    |                  expected due to this
    |
-   = note: expected mutable reference `&mut Option<i32>`
-                      found reference `&&mut Option<i32>`
+   = note: expected mutable reference `&mut Option<_>`
+                      found reference `&&mut Option<_>`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/lifetimes/issue-79187-2.stderr b/tests/ui/lifetimes/issue-79187-2.stderr
index 86a4ac4132e..e8115bb6b06 100644
--- a/tests/ui/lifetimes/issue-79187-2.stderr
+++ b/tests/ui/lifetimes/issue-79187-2.stderr
@@ -54,8 +54,8 @@ error[E0308]: mismatched types
 LL |     take_foo(|a: &i32| a);
    |     ^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
-   = note: expected reference `&i32`
-              found reference `&i32`
+   = note: expected reference `&_`
+              found reference `&_`
 note: the lifetime requirement is introduced here
   --> $DIR/issue-79187-2.rs:5:21
    |
@@ -68,8 +68,8 @@ error[E0308]: mismatched types
 LL |     take_foo(|a: &i32| -> &i32 { a });
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
-   = note: expected reference `&i32`
-              found reference `&i32`
+   = note: expected reference `&_`
+              found reference `&_`
 note: the lifetime requirement is introduced here
   --> $DIR/issue-79187-2.rs:5:21
    |
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
index c3d7960de56..10e3fc92868 100644
--- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
+++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.leak.stderr
@@ -12,8 +12,8 @@ LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
-   = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
-              found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
+              found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr
index 8e4a514c7c6..bf77875fa7a 100644
--- a/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr
+++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq1.noleak.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |         _ => y,
    |              ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
-              found fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
+              found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr
index a1958cc436a..1c8925e0bfb 100644
--- a/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr
+++ b/tests/ui/lub-glb/old-lub-glb-hr-noteq2.leak.stderr
@@ -11,8 +11,8 @@ LL | |
 LL | |     };
    | |_____- `match` arms have incompatible types
    |
-   = note: expected fn pointer `for<'a> fn(&'a u8, &'a u8) -> &'a u8`
-              found fn pointer `for<'a, 'b> fn(&'a u8, &'b u8) -> &'a u8`
+   = note: expected fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
+              found fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/macros/issue-118048.rs b/tests/ui/macros/issue-118048.rs
new file mode 100644
index 00000000000..15a834fa2df
--- /dev/null
+++ b/tests/ui/macros/issue-118048.rs
@@ -0,0 +1,10 @@
+macro_rules! foo {
+    ($ty:ty) => {
+        fn foo(_: $ty, _: $ty) {}
+    }
+}
+
+foo!(_);
+//~^ ERROR the placeholder `_` is not allowed within types on item signatures for functions
+
+fn main() {}
diff --git a/tests/ui/macros/issue-118048.stderr b/tests/ui/macros/issue-118048.stderr
new file mode 100644
index 00000000000..6acf78f63b2
--- /dev/null
+++ b/tests/ui/macros/issue-118048.stderr
@@ -0,0 +1,21 @@
+error[E0121]: the placeholder `_` is not allowed within types on item signatures for functions
+  --> $DIR/issue-118048.rs:7:6
+   |
+LL | foo!(_);
+   |      ^
+   |      |
+   |      not allowed in type signatures
+   |      not allowed in type signatures
+   |
+help: use type parameters instead
+   |
+LL ~         fn foo<T>(_: $ty, _: $ty) {}
+LL |     }
+LL | }
+LL | 
+LL ~ foo!(T);
+   |
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0121`.
diff --git a/tests/ui/mir/field-projection-mutating-context.stderr b/tests/ui/mir/field-projection-mutating-context.stderr
index 62c9e55a44b..c7289c0f07c 100644
--- a/tests/ui/mir/field-projection-mutating-context.stderr
+++ b/tests/ui/mir/field-projection-mutating-context.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     let Foo(ref mut y): Foo<fn(&'static str)> = x;
    |             ^^^^^^^^^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a> fn(&'a str)`
-              found fn pointer `fn(&str)`
+   = note: expected fn pointer `for<'a> fn(&'a _)`
+              found fn pointer `fn(&_)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
index 760e3327b77..e9808b86991 100644
--- a/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
+++ b/tests/ui/mismatched_types/closure-arg-type-mismatch.stderr
@@ -6,8 +6,8 @@ LL |     a.iter().map(|_: (u32, u32)| 45);
    |              |
    |              expected due to this
    |
-   = note: expected closure signature `fn(&(u32, u32)) -> _`
-              found closure signature `fn((u32, u32)) -> _`
+   = note: expected closure signature `fn(&(_, _)) -> _`
+              found closure signature `fn((_, _)) -> _`
 note: required by a bound in `map`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 help: consider adjusting the signature so it borrows its argument
diff --git a/tests/ui/mismatched_types/issue-36053-2.stderr b/tests/ui/mismatched_types/issue-36053-2.stderr
index bac27788a2d..292525daa3d 100644
--- a/tests/ui/mismatched_types/issue-36053-2.stderr
+++ b/tests/ui/mismatched_types/issue-36053-2.stderr
@@ -6,8 +6,8 @@ LL |     once::<&str>("str").fuse().filter(|a: &str| true).count();
    |                                |
    |                                expected due to this
    |
-   = note: expected closure signature `for<'a> fn(&'a &str) -> _`
-              found closure signature `for<'a> fn(&'a str) -> _`
+   = note: expected closure signature `for<'a> fn(&'a &_) -> _`
+              found closure signature `for<'a> fn(&'a _) -> _`
 note: required by a bound in `filter`
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
 help: consider adjusting the signature so it borrows its argument
diff --git a/tests/ui/mismatched_types/normalize-fn-sig.stderr b/tests/ui/mismatched_types/normalize-fn-sig.stderr
index 2166de85f1f..0fb3975c3c2 100644
--- a/tests/ui/mismatched_types/normalize-fn-sig.stderr
+++ b/tests/ui/mismatched_types/normalize-fn-sig.stderr
@@ -6,8 +6,8 @@ LL |     needs_i32_ref_fn(foo::<()>);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected fn pointer `fn(&'static i32, i32)`
-                 found fn item `fn(i32, &'static i32) {foo::<()>}`
+   = note: expected fn pointer `fn(&'static _, _)`
+                 found fn item `fn(_, &'static _) {foo::<()>}`
 note: function defined here
   --> $DIR/normalize-fn-sig.rs:11:4
    |
diff --git a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr
index 821661f1a56..6a9d76f7998 100644
--- a/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr
+++ b/tests/ui/moves/assignment-of-clone-call-on-ref-due-to-missing-bound.stderr
@@ -6,8 +6,8 @@ LL |             let mut x: HashSet<Day> = v.clone();
    |                        |
    |                        expected due to this
    |
-   = note: expected struct `HashSet<Day>`
-           found reference `&HashSet<Day>`
+   = note: expected struct `HashSet<_>`
+           found reference `&HashSet<_>`
 note: `HashSet<Day>` does not implement `Clone`, so `&HashSet<Day>` was cloned instead
   --> $DIR/assignment-of-clone-call-on-ref-due-to-missing-bound.rs:18:39
    |
diff --git a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
index 7d76c916d6d..58fd7776f2f 100644
--- a/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
+++ b/tests/ui/nll/relate_tys/hr-fn-aaa-as-aba.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     let a: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
    |                                                          ^^^^^^^^^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
-              found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
+              found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
 
 error[E0308]: mismatched types
   --> $DIR/hr-fn-aaa-as-aba.rs:20:12
@@ -13,8 +13,8 @@ error[E0308]: mismatched types
 LL |     let _: for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32 = make_it();
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a, 'b> fn(&'a u32, &'b u32) -> &'a u32`
-              found fn pointer `for<'a> fn(&'a u32, &'a u32) -> &'a u32`
+   = note: expected fn pointer `for<'a, 'b> fn(&'a _, &'b _) -> &'a _`
+              found fn pointer `for<'a> fn(&'a _, &'a _) -> &'a _`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/nll/relate_tys/universe-violation.stderr b/tests/ui/nll/relate_tys/universe-violation.stderr
index b585eee0769..a538a59a495 100644
--- a/tests/ui/nll/relate_tys/universe-violation.stderr
+++ b/tests/ui/nll/relate_tys/universe-violation.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     let b: fn(&u32) -> &u32 = a;
    |                               ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'a> fn(&'a u32) -> &'a u32`
-              found fn pointer `fn(&u32) -> &u32`
+   = note: expected fn pointer `for<'a> fn(&'a _) -> &'a _`
+              found fn pointer `fn(&_) -> &_`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/nll/trait-associated-constant.stderr b/tests/ui/nll/trait-associated-constant.stderr
index f6277508eeb..371f7860d4d 100644
--- a/tests/ui/nll/trait-associated-constant.stderr
+++ b/tests/ui/nll/trait-associated-constant.stderr
@@ -4,8 +4,8 @@ error[E0308]: const not compatible with trait
 LL |     const AC: Option<&'c str> = None;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ lifetime mismatch
    |
-   = note: expected enum `Option<&'b str>`
-              found enum `Option<&'c str>`
+   = note: expected enum `Option<&'b _>`
+              found enum `Option<&'c _>`
 note: the lifetime `'c` as defined here...
   --> $DIR/trait-associated-constant.rs:20:18
    |
diff --git a/tests/ui/or-patterns/inconsistent-modes.stderr b/tests/ui/or-patterns/inconsistent-modes.stderr
index f6367ef8234..19618d336f8 100644
--- a/tests/ui/or-patterns/inconsistent-modes.stderr
+++ b/tests/ui/or-patterns/inconsistent-modes.stderr
@@ -57,8 +57,8 @@ LL |     let (Ok(ref a) | Err(ref mut a)): Result<&u8, &mut u8> = Ok(&0);
    |             |            types differ in mutability
    |             first introduced with type `&&u8` here
    |
-   = note:      expected reference `&&u8`
-           found mutable reference `&mut &mut u8`
+   = note:      expected reference `&&_`
+           found mutable reference `&mut &mut _`
    = note: a binding must have the same type in all alternatives
 
 error[E0308]: mismatched types
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
index d1950087c4c..2c402e4c65e 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.rs
@@ -84,15 +84,15 @@ fn main() {}
 
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
 //~^ ERROR inclusive range with no end
-//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
 //~^ ERROR inclusive range with no end
-//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=-#[attr] 10 => () } }
 //~^ ERROR unexpected token: `#`
 #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
 //~^ ERROR inclusive range with no end
-//~| ERROR expected one of `=>`, `if`, or `|`, found `#`
+//~| ERROR expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
 
 #[cfg(FALSE)] fn e() { let _ = x.#![attr]foo(); }
 //~^ ERROR unexpected token: `#`
diff --git a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
index e46c591080d..a0e95c5c1ed 100644
--- a/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
+++ b/tests/ui/parser/attribute/attr-stmt-expr-attr-bad.stderr
@@ -365,11 +365,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
    |
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: expected one of `=>`, `if`, or `|`, found `#`
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:85:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] 10 => () } }
-   |                                      ^ expected one of `=>`, `if`, or `|`
+   |                                      ^ expected one of `,`, `=>`, `if`, `|`, or `}`
 
 error[E0586]: inclusive range with no end
   --> $DIR/attr-stmt-expr-attr-bad.rs:88:35
@@ -379,11 +379,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
    |
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: expected one of `=>`, `if`, or `|`, found `#`
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:88:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] -10 => () } }
-   |                                      ^ expected one of `=>`, `if`, or `|`
+   |                                      ^ expected one of `,`, `=>`, `if`, `|`, or `}`
 
 error: unexpected token: `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:91:39
@@ -399,11 +399,11 @@ LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
    |
    = note: inclusive ranges must be bounded at the end (`..=b` or `a..=b`)
 
-error: expected one of `=>`, `if`, or `|`, found `#`
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:93:38
    |
 LL | #[cfg(FALSE)] fn e() { match 0 { 0..=#[attr] FOO => () } }
-   |                                      ^ expected one of `=>`, `if`, or `|`
+   |                                      ^ expected one of `,`, `=>`, `if`, `|`, or `}`
 
 error: unexpected token: `#`
   --> $DIR/attr-stmt-expr-attr-bad.rs:97:34
diff --git a/tests/ui/parser/issues/issue-24375.rs b/tests/ui/parser/issues/issue-24375.rs
index 1d128d33e4f..8d1bc579e7b 100644
--- a/tests/ui/parser/issues/issue-24375.rs
+++ b/tests/ui/parser/issues/issue-24375.rs
@@ -3,7 +3,7 @@ static tmp : [&'static str; 2]  = ["hello", "he"];
 fn main() {
     let z = "hello";
     match z {
-        tmp[0] => {} //~ ERROR expected one of `=>`, `@`, `if`, or `|`, found `[`
+        tmp[0] => {} //~ ERROR expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[`
         _ => {}
     }
 }
diff --git a/tests/ui/parser/issues/issue-24375.stderr b/tests/ui/parser/issues/issue-24375.stderr
index bb1e19e9e6d..2b980a5520f 100644
--- a/tests/ui/parser/issues/issue-24375.stderr
+++ b/tests/ui/parser/issues/issue-24375.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `[`
+error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `[`
   --> $DIR/issue-24375.rs:6:12
    |
 LL |         tmp[0] => {}
-   |            ^ expected one of `=>`, `@`, `if`, or `|`
+   |            ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.rs b/tests/ui/parser/macro/macro-expand-to-match-arm.rs
index 39d1d065ed9..db38fa0d7bc 100644
--- a/tests/ui/parser/macro/macro-expand-to-match-arm.rs
+++ b/tests/ui/parser/macro/macro-expand-to-match-arm.rs
@@ -1,6 +1,9 @@
 macro_rules! arm {
     ($pattern:pat => $block:block) => {
         $pattern => $block
+        //~^ ERROR macro expansion ignores token `=>` and any following
+        //~| NOTE the usage of `arm!` is likely invalid in pattern context
+        //~| NOTE macros cannot expand to match arms
     };
 }
 
@@ -9,9 +12,8 @@ fn main() {
     match x {
         Some(1) => {},
         arm!(None => {}),
-        //~^ NOTE macros cannot expand to match arms
-        //~| ERROR unexpected `,` in pattern
-        // doesn't recover
+        //~^ NOTE caused by the macro expansion here
+        //~| ERROR `match` arm with no body
         Some(2) => {},
         _ => {},
     };
diff --git a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
index 1b34d2d12b2..e3e7ff89c81 100644
--- a/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
+++ b/tests/ui/parser/macro/macro-expand-to-match-arm.stderr
@@ -1,10 +1,20 @@
-error: unexpected `,` in pattern
-  --> $DIR/macro-expand-to-match-arm.rs:11:25
+error: macro expansion ignores token `=>` and any following
+  --> $DIR/macro-expand-to-match-arm.rs:3:18
    |
+LL |         $pattern => $block
+   |                  ^^
+...
 LL |         arm!(None => {}),
-   |                         ^
+   |         ---------------- caused by the macro expansion here
    |
+   = note: the usage of `arm!` is likely invalid in pattern context
    = note: macros cannot expand to match arms
 
-error: aborting due to 1 previous error
+error: `match` arm with no body
+  --> $DIR/macro-expand-to-match-arm.rs:14:9
+   |
+LL |         arm!(None => {}),
+   |         ^^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/parser/match-arm-without-body.rs b/tests/ui/parser/match-arm-without-body.rs
new file mode 100644
index 00000000000..c3487c2c658
--- /dev/null
+++ b/tests/ui/parser/match-arm-without-body.rs
@@ -0,0 +1,79 @@
+macro_rules! pat {
+    () => { Some(_) }
+}
+
+fn main() {
+    match Some(false) {
+        Some(_)
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        Some(_)
+        _ => {}
+        //~^ ERROR expected one of
+    }
+    match Some(false) {
+        Some(_),
+        //~^ ERROR unexpected `,` in pattern
+        //~| HELP try adding parentheses to match on a tuple
+        //~| HELP or a vertical bar to match on multiple alternatives
+    }
+    match Some(false) {
+        Some(_),
+        //~^ ERROR unexpected `,` in pattern
+        //~| HELP try adding parentheses to match on a tuple
+        //~| HELP or a vertical bar to match on multiple alternatives
+        _ => {}
+    }
+    match Some(false) {
+        Some(_) if true
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        Some(_) if true
+        _ => {}
+        //~^ ERROR expected one of
+    }
+    match Some(false) {
+        Some(_) if true,
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        Some(_) if true,
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+        _ => {}
+    }
+    match Some(false) {
+        pat!()
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        pat!(),
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        pat!() if true,
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+    }
+    match Some(false) {
+        pat!()
+        //~^ ERROR expected `,` following `match` arm
+        //~| HELP missing a comma here
+        //~| ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+        _ => {}
+    }
+    match Some(false) {
+        pat!(),
+        //~^ ERROR `match` arm with no body
+        //~| HELP add a body after the pattern
+        _ => {}
+    }
+}
diff --git a/tests/ui/parser/match-arm-without-body.stderr b/tests/ui/parser/match-arm-without-body.stderr
new file mode 100644
index 00000000000..3a06ed050b5
--- /dev/null
+++ b/tests/ui/parser/match-arm-without-body.stderr
@@ -0,0 +1,116 @@
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found reserved identifier `_`
+  --> $DIR/match-arm-without-body.rs:13:9
+   |
+LL |         Some(_)
+   |                - expected one of `,`, `=>`, `if`, `|`, or `}`
+LL |         _ => {}
+   |         ^ unexpected token
+
+error: unexpected `,` in pattern
+  --> $DIR/match-arm-without-body.rs:17:16
+   |
+LL |         Some(_),
+   |                ^
+   |
+help: try adding parentheses to match on a tuple...
+   |
+LL |         (Some(_),)
+   |         +        +
+help: ...or a vertical bar to match on multiple alternatives
+   |
+LL |         Some(_) |
+   |
+
+error: unexpected `,` in pattern
+  --> $DIR/match-arm-without-body.rs:23:16
+   |
+LL |         Some(_),
+   |                ^
+   |
+help: try adding parentheses to match on a tuple...
+   |
+LL ~         (Some(_),
+LL |
+LL |
+LL |
+LL ~         _) => {}
+   |
+help: ...or a vertical bar to match on multiple alternatives
+   |
+LL ~         Some(_) |
+LL +
+LL +
+LL +
+LL ~         _ => {}
+   |
+
+error: expected one of `,`, `.`, `=>`, `?`, `}`, or an operator, found reserved identifier `_`
+  --> $DIR/match-arm-without-body.rs:36:9
+   |
+LL |         Some(_) if true
+   |                        - expected one of `,`, `.`, `=>`, `?`, `}`, or an operator
+LL |         _ => {}
+   |         ^ unexpected token
+
+error: expected `,` following `match` arm
+  --> $DIR/match-arm-without-body.rs:66:15
+   |
+LL |         pat!()
+   |               ^ help: missing a comma here to end this `match` arm: `,`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:7:9
+   |
+LL |         Some(_)
+   |         ^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:30:9
+   |
+LL |         Some(_) if true
+   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:40:9
+   |
+LL |         Some(_) if true,
+   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:45:9
+   |
+LL |         Some(_) if true,
+   |         ^^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:51:9
+   |
+LL |         pat!()
+   |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:56:9
+   |
+LL |         pat!(),
+   |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:61:9
+   |
+LL |         pat!() if true,
+   |         ^^^^^^^^^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:66:9
+   |
+LL |         pat!()
+   |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: `match` arm with no body
+  --> $DIR/match-arm-without-body.rs:74:9
+   |
+LL |         pat!(),
+   |         ^^^^^^- help: add a body after the pattern: `=> todo!(),`
+
+error: aborting due to 14 previous errors
+
diff --git a/tests/ui/parser/pat-lt-bracket-1.rs b/tests/ui/parser/pat-lt-bracket-1.rs
index 2e2001434f2..33da15adb9e 100644
--- a/tests/ui/parser/pat-lt-bracket-1.rs
+++ b/tests/ui/parser/pat-lt-bracket-1.rs
@@ -1,7 +1,7 @@
 fn main() {
   match 42 {
     x < 7 => (),
-   //~^ error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+   //~^ error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<`
     _ => ()
   }
 }
diff --git a/tests/ui/parser/pat-lt-bracket-1.stderr b/tests/ui/parser/pat-lt-bracket-1.stderr
index 14e679bbee0..f39487052ad 100644
--- a/tests/ui/parser/pat-lt-bracket-1.stderr
+++ b/tests/ui/parser/pat-lt-bracket-1.stderr
@@ -1,8 +1,8 @@
-error: expected one of `=>`, `@`, `if`, or `|`, found `<`
+error: expected one of `,`, `=>`, `@`, `if`, `|`, or `}`, found `<`
   --> $DIR/pat-lt-bracket-1.rs:3:7
    |
 LL |     x < 7 => (),
-   |       ^ expected one of `=>`, `@`, `if`, or `|`
+   |       ^ expected one of `,`, `=>`, `@`, `if`, `|`, or `}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/pattern/never_patterns.rs b/tests/ui/pattern/never_patterns.rs
index e2e17e0e9a7..915f3e75e7b 100644
--- a/tests/ui/pattern/never_patterns.rs
+++ b/tests/ui/pattern/never_patterns.rs
@@ -20,58 +20,58 @@ fn never_pattern_location(void: Void) {
     // FIXME(never_patterns): Don't accept on a non-empty type.
     match Some(0) {
         None => {}
-        Some(!) => {}
+        Some(!),
     }
     // FIXME(never_patterns): Don't accept on an arbitrary type, even if there are no more branches.
     match () {
         () => {}
-        ! => {}
+        !,
     }
     // FIXME(never_patterns): Don't accept even on an empty branch.
     match None::<Void> {
         None => {}
-        ! => {}
+        !,
     }
     // FIXME(never_patterns): Let alone if the emptiness is behind a reference.
     match None::<&Void> {
         None => {}
-        ! => {}
+        !,
     }
     // Participate in match ergonomics.
     match &void {
-        ! => {}
+        !
     }
     match &&void {
-        ! => {}
+        !
     }
     match &&void {
-        &! => {}
+        &!
     }
     match &None::<Void> {
         None => {}
-        Some(!) => {}
+        Some(!)
     }
     match None::<&Void> {
         None => {}
-        Some(!) => {}
+        Some(!),
     }
     // Accept on a composite empty type.
     match None::<&(u32, Void)> {
         None => {}
-        Some(&!) => {}
+        Some(&!),
     }
     // Accept on an simple empty type.
     match None::<Void> {
         None => {}
-        Some(!) => {}
+        Some(!),
     }
     match None::<&Void> {
         None => {}
-        Some(&!) => {}
+        Some(&!),
     }
     match None::<&(u32, Void)> {
         None => {}
-        Some(&(_, !)) => {}
+        Some(&(_, !)),
     }
 }
 
@@ -84,12 +84,12 @@ fn never_and_bindings() {
         //~^ ERROR: is not bound in all patterns
     }
     let (Ok(_x) | Err(&!)) = x;
-        //~^ ERROR: is not bound in all patterns
+    //~^ ERROR: is not bound in all patterns
 
     // FIXME(never_patterns): A never pattern mustn't have bindings.
     match x {
         Ok(_) => {}
-        Err(&(_b, !)) => {}
+        Err(&(_b, !)),
     }
     match x {
         Ok(_a) | Err(&(_b, !)) => {}
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
new file mode 100644
index 00000000000..304435cb21e
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.exhaustive_patterns.stderr
@@ -0,0 +1,63 @@
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:17:9
+   |
+LL |         _ => {}
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-match-check-notes.rs:7:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:20:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:27:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:30:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match-check-notes.rs:35:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/empty-match-check-notes.rs:45:11
+   |
+LL |     match 0u8 {
+   |           ^^^ pattern `_` not covered
+   |
+   = note: the matched value is of type `u8`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         _ if false => {},
+LL +         _ => todo!()
+   |
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
new file mode 100644
index 00000000000..40494b726f0
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.normal.stderr
@@ -0,0 +1,62 @@
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:17:9
+   |
+LL |         _ => {}
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-match-check-notes.rs:7:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:20:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:27:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-match-check-notes.rs:30:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-match-check-notes.rs:35:9
+   |
+LL |     let None = x;
+   |         ^^^^ pattern `Some(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
+help: you might want to use `if let` to ignore the variant that isn't matched
+   |
+LL |     if let None = x { todo!() };
+   |     ++              +++++++++++
+
+error[E0004]: non-exhaustive patterns: `_` not covered
+  --> $DIR/empty-match-check-notes.rs:45:11
+   |
+LL |     match 0u8 {
+   |           ^^^ pattern `_` not covered
+   |
+   = note: the matched value is of type `u8`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         _ if false => {},
+LL +         _ => todo!()
+   |
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match-check-notes.rs b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
new file mode 100644
index 00000000000..ee9ff3dcf90
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-match-check-notes.rs
@@ -0,0 +1,52 @@
+// aux-build:empty.rs
+// revisions: normal exhaustive_patterns
+//
+// This tests a match with no arms on various types, and checks NOTEs.
+#![feature(never_type)]
+#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
+#![deny(unreachable_patterns)]
+//~^ NOTE the lint level is defined here
+
+extern crate empty;
+
+enum EmptyEnum {}
+
+fn empty_enum(x: EmptyEnum) {
+    match x {} // ok
+    match x {
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {} //~ ERROR unreachable pattern
+    }
+}
+
+fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
+    match x {} // ok
+    match x {
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match x {
+        _ if false => {} //~ ERROR unreachable pattern
+    }
+}
+
+fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
+    let None = x;
+    //~^ ERROR refutable pattern in local binding
+    //~| NOTE `let` bindings require an "irrefutable pattern"
+    //~| NOTE for more information, visit
+    //~| NOTE the matched value is of type
+    //~| NOTE pattern `Some(_)` not covered
+    //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
+}
+
+fn main() {
+    match 0u8 {
+        //~^ ERROR `_` not covered
+        //~| NOTE the matched value is of type
+        //~| NOTE match arms with guards don't count towards exhaustivity
+        //~| NOTE pattern `_` not covered
+        _ if false => {}
+    }
+}
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 8f9bd5bde89..9c3bebd7797 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -1,62 +1,5 @@
-error: unreachable pattern
-  --> $DIR/empty-match.rs:68:9
-   |
-LL |         _ => {},
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/empty-match.rs:8:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:71:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:78:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:81:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match.rs:86:9
-   |
-LL |     let None = x;
-   |         ^^^^ pattern `Some(_)` not covered
-   |
-   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
-   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-   = note: pattern `Some(_)` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
-   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     if let None = x { todo!() };
-   |     ++              +++++++++++
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:98:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:101:9
-   |
-LL |         _ if false => {},
-   |         ^
-
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:119:20
+  --> $DIR/empty-match.rs:46:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -65,122 +8,121 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:121:20
+  --> $DIR/empty-match.rs:47:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:22:12
    |
-LL | struct NonEmptyStruct1;
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct1;
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:123:20
+  --> $DIR/empty-match.rs:48:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:18:8
+  --> $DIR/empty-match.rs:23:12
    |
-LL | struct NonEmptyStruct2(bool);
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct2(bool);
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:125:20
+  --> $DIR/empty-match.rs:49:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:21:7
+  --> $DIR/empty-match.rs:24:11
    |
-LL | union NonEmptyUnion1 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion1 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:127:20
+  --> $DIR/empty-match.rs:50:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:26:7
+  --> $DIR/empty-match.rs:27:11
    |
-LL | union NonEmptyUnion2 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion2 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:129:20
+  --> $DIR/empty-match.rs:51:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:32:6
+  --> $DIR/empty-match.rs:31:10
    |
-LL | enum NonEmptyEnum1 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
+LL |     enum NonEmptyEnum1 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:132:20
+  --> $DIR/empty-match.rs:52:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:39:6
-   |
-LL | enum NonEmptyEnum2 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
-...
-LL |     Bar,
-   |     --- not covered
+  --> $DIR/empty-match.rs:34:10
+   |
+LL |     enum NonEmptyEnum2 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
+LL |         Bar,
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:135:20
+  --> $DIR/empty-match.rs:53:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:49:6
-   |
-LL | enum NonEmptyEnum5 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     V1, V2, V3, V4, V5,
-   |     --  --  --  --  -- not covered
-   |     |   |   |   |
-   |     |   |   |   not covered
-   |     |   |   not covered
-   |     |   not covered
-   |     not covered
+  --> $DIR/empty-match.rs:38:10
+   |
+LL |     enum NonEmptyEnum5 {
+   |          ^^^^^^^^^^^^^
+LL |         V1,
+   |         -- not covered
+LL |         V2,
+   |         -- not covered
+LL |         V3,
+   |         -- not covered
+LL |         V4,
+   |         -- not covered
+LL |         V5,
+   |         -- not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:139:24
+  --> $DIR/empty-match.rs:55:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -189,161 +131,159 @@ LL |     match_guarded_arm!(0u8);
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             _ => todo!()
+LL ~                 _ if false => {},
+LL +                 _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:144:24
+  --> $DIR/empty-match.rs:56:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:22:12
    |
-LL | struct NonEmptyStruct1;
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct1;
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyStruct1 => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:149:24
+  --> $DIR/empty-match.rs:57:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:18:8
+  --> $DIR/empty-match.rs:23:12
    |
-LL | struct NonEmptyStruct2(bool);
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct2(bool);
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyStruct2(_) => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:154:24
+  --> $DIR/empty-match.rs:58:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:21:7
+  --> $DIR/empty-match.rs:24:11
    |
-LL | union NonEmptyUnion1 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion1 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyUnion1 { .. } => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:159:24
+  --> $DIR/empty-match.rs:59:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:26:7
+  --> $DIR/empty-match.rs:27:11
    |
-LL | union NonEmptyUnion2 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion2 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyUnion2 { .. } => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:164:24
+  --> $DIR/empty-match.rs:60:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:32:6
+  --> $DIR/empty-match.rs:31:10
    |
-LL | enum NonEmptyEnum1 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
+LL |     enum NonEmptyEnum1 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyEnum1::Foo(_) => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:169:24
+  --> $DIR/empty-match.rs:61:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:39:6
-   |
-LL | enum NonEmptyEnum2 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
-...
-LL |     Bar,
-   |     --- not covered
+  --> $DIR/empty-match.rs:34:10
+   |
+LL |     enum NonEmptyEnum2 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
+LL |         Bar,
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~             _ if false => {},
-LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:174:24
+  --> $DIR/empty-match.rs:62:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:49:6
-   |
-LL | enum NonEmptyEnum5 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     V1, V2, V3, V4, V5,
-   |     --  --  --  --  -- not covered
-   |     |   |   |   |
-   |     |   |   |   not covered
-   |     |   |   not covered
-   |     |   not covered
-   |     not covered
+  --> $DIR/empty-match.rs:38:10
+   |
+LL |     enum NonEmptyEnum5 {
+   |          ^^^^^^^^^^^^^
+LL |         V1,
+   |         -- not covered
+LL |         V2,
+   |         -- not covered
+LL |         V3,
+   |         -- not covered
+LL |         V4,
+   |         -- not covered
+LL |         V5,
+   |         -- not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~             _ if false => {},
-LL +             _ => todo!()
+LL ~                 _ if false => {},
+LL +                 _ => todo!()
    |
 
-error: aborting due to 23 previous errors
+error: aborting due to 16 previous errors
 
-Some errors have detailed explanations: E0004, E0005.
-For more information about an error, try `rustc --explain E0004`.
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 7f0389f40e2..9c3bebd7797 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -1,61 +1,5 @@
-error: unreachable pattern
-  --> $DIR/empty-match.rs:68:9
-   |
-LL |         _ => {},
-   |         ^
-   |
-note: the lint level is defined here
-  --> $DIR/empty-match.rs:8:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:71:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:78:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:81:9
-   |
-LL |         _ if false => {},
-   |         ^
-
-error[E0005]: refutable pattern in local binding
-  --> $DIR/empty-match.rs:86:9
-   |
-LL |     let None = x;
-   |         ^^^^ pattern `Some(_)` not covered
-   |
-   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
-   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
-   = note: the matched value is of type `Option<SecretlyUninhabitedForeignStruct>`
-help: you might want to use `if let` to ignore the variant that isn't matched
-   |
-LL |     if let None = x { todo!() };
-   |     ++              +++++++++++
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:98:9
-   |
-LL |         _ => {},
-   |         ^
-
-error: unreachable pattern
-  --> $DIR/empty-match.rs:101:9
-   |
-LL |         _ if false => {},
-   |         ^
-
 error[E0004]: non-exhaustive patterns: type `u8` is non-empty
-  --> $DIR/empty-match.rs:119:20
+  --> $DIR/empty-match.rs:46:20
    |
 LL |     match_no_arms!(0u8);
    |                    ^^^
@@ -64,122 +8,121 @@ LL |     match_no_arms!(0u8);
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct1` is non-empty
-  --> $DIR/empty-match.rs:121:20
+  --> $DIR/empty-match.rs:47:20
    |
 LL |     match_no_arms!(NonEmptyStruct1);
    |                    ^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:22:12
    |
-LL | struct NonEmptyStruct1;
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct1;
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyStruct2` is non-empty
-  --> $DIR/empty-match.rs:123:20
+  --> $DIR/empty-match.rs:48:20
    |
 LL |     match_no_arms!(NonEmptyStruct2(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:18:8
+  --> $DIR/empty-match.rs:23:12
    |
-LL | struct NonEmptyStruct2(bool);
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct2(bool);
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion1` is non-empty
-  --> $DIR/empty-match.rs:125:20
+  --> $DIR/empty-match.rs:49:20
    |
 LL |     match_no_arms!((NonEmptyUnion1 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:21:7
+  --> $DIR/empty-match.rs:24:11
    |
-LL | union NonEmptyUnion1 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion1 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: type `NonEmptyUnion2` is non-empty
-  --> $DIR/empty-match.rs:127:20
+  --> $DIR/empty-match.rs:50:20
    |
 LL |     match_no_arms!((NonEmptyUnion2 { foo: () }));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:26:7
+  --> $DIR/empty-match.rs:27:11
    |
-LL | union NonEmptyUnion2 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion2 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:129:20
+  --> $DIR/empty-match.rs:51:20
    |
 LL |     match_no_arms!(NonEmptyEnum1::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:32:6
+  --> $DIR/empty-match.rs:31:10
    |
-LL | enum NonEmptyEnum1 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
+LL |     enum NonEmptyEnum1 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:132:20
+  --> $DIR/empty-match.rs:52:20
    |
 LL |     match_no_arms!(NonEmptyEnum2::Foo(true));
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:39:6
-   |
-LL | enum NonEmptyEnum2 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
-...
-LL |     Bar,
-   |     --- not covered
+  --> $DIR/empty-match.rs:34:10
+   |
+LL |     enum NonEmptyEnum2 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
+LL |         Bar,
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:135:20
+  --> $DIR/empty-match.rs:53:20
    |
 LL |     match_no_arms!(NonEmptyEnum5::V1);
    |                    ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:49:6
-   |
-LL | enum NonEmptyEnum5 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     V1, V2, V3, V4, V5,
-   |     --  --  --  --  -- not covered
-   |     |   |   |   |
-   |     |   |   |   not covered
-   |     |   |   not covered
-   |     |   not covered
-   |     not covered
+  --> $DIR/empty-match.rs:38:10
+   |
+LL |     enum NonEmptyEnum5 {
+   |          ^^^^^^^^^^^^^
+LL |         V1,
+   |         -- not covered
+LL |         V2,
+   |         -- not covered
+LL |         V3,
+   |         -- not covered
+LL |         V4,
+   |         -- not covered
+LL |         V5,
+   |         -- not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or multiple match arms
 
 error[E0004]: non-exhaustive patterns: `_` not covered
-  --> $DIR/empty-match.rs:139:24
+  --> $DIR/empty-match.rs:55:24
    |
 LL |     match_guarded_arm!(0u8);
    |                        ^^^ pattern `_` not covered
@@ -188,161 +131,159 @@ LL |     match_guarded_arm!(0u8);
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             _ => todo!()
+LL ~                 _ if false => {},
+LL +                 _ => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct1` not covered
-  --> $DIR/empty-match.rs:144:24
+  --> $DIR/empty-match.rs:56:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct1);
    |                        ^^^^^^^^^^^^^^^ pattern `NonEmptyStruct1` not covered
    |
 note: `NonEmptyStruct1` defined here
-  --> $DIR/empty-match.rs:15:8
+  --> $DIR/empty-match.rs:22:12
    |
-LL | struct NonEmptyStruct1;
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct1;
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyStruct1 => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyStruct1 => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyStruct2(_)` not covered
-  --> $DIR/empty-match.rs:149:24
+  --> $DIR/empty-match.rs:57:24
    |
 LL |     match_guarded_arm!(NonEmptyStruct2(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyStruct2(_)` not covered
    |
 note: `NonEmptyStruct2` defined here
-  --> $DIR/empty-match.rs:18:8
+  --> $DIR/empty-match.rs:23:12
    |
-LL | struct NonEmptyStruct2(bool);
-   |        ^^^^^^^^^^^^^^^
+LL |     struct NonEmptyStruct2(bool);
+   |            ^^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyStruct2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyStruct2(_) => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyStruct2(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion1 { .. }` not covered
-  --> $DIR/empty-match.rs:154:24
+  --> $DIR/empty-match.rs:58:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion1 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion1 { .. }` not covered
    |
 note: `NonEmptyUnion1` defined here
-  --> $DIR/empty-match.rs:21:7
+  --> $DIR/empty-match.rs:24:11
    |
-LL | union NonEmptyUnion1 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion1 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyUnion1 { .. } => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyUnion1 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyUnion2 { .. }` not covered
-  --> $DIR/empty-match.rs:159:24
+  --> $DIR/empty-match.rs:59:24
    |
 LL |     match_guarded_arm!((NonEmptyUnion2 { foo: () }));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyUnion2 { .. }` not covered
    |
 note: `NonEmptyUnion2` defined here
-  --> $DIR/empty-match.rs:26:7
+  --> $DIR/empty-match.rs:27:11
    |
-LL | union NonEmptyUnion2 {
-   |       ^^^^^^^^^^^^^^
+LL |     union NonEmptyUnion2 {
+   |           ^^^^^^^^^^^^^^
    = note: the matched value is of type `NonEmptyUnion2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyUnion2 { .. } => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyUnion2 { .. } => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum1::Foo(_)` not covered
-  --> $DIR/empty-match.rs:164:24
+  --> $DIR/empty-match.rs:60:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum1::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ pattern `NonEmptyEnum1::Foo(_)` not covered
    |
 note: `NonEmptyEnum1` defined here
-  --> $DIR/empty-match.rs:32:6
+  --> $DIR/empty-match.rs:31:10
    |
-LL | enum NonEmptyEnum1 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
+LL |     enum NonEmptyEnum1 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum1`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {},
-LL +             NonEmptyEnum1::Foo(_) => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyEnum1::Foo(_) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-  --> $DIR/empty-match.rs:169:24
+  --> $DIR/empty-match.rs:61:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum2::Foo(true));
    |                        ^^^^^^^^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
    |
 note: `NonEmptyEnum2` defined here
-  --> $DIR/empty-match.rs:39:6
-   |
-LL | enum NonEmptyEnum2 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     Foo(bool),
-   |     --- not covered
-...
-LL |     Bar,
-   |     --- not covered
+  --> $DIR/empty-match.rs:34:10
+   |
+LL |     enum NonEmptyEnum2 {
+   |          ^^^^^^^^^^^^^
+LL |         Foo(bool),
+   |         --- not covered
+LL |         Bar,
+   |         --- not covered
    = note: the matched value is of type `NonEmptyEnum2`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~             _ if false => {},
-LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
+LL ~                 _ if false => {},
+LL +                 NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-  --> $DIR/empty-match.rs:174:24
+  --> $DIR/empty-match.rs:62:24
    |
 LL |     match_guarded_arm!(NonEmptyEnum5::V1);
    |                        ^^^^^^^^^^^^^^^^^ patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
    |
 note: `NonEmptyEnum5` defined here
-  --> $DIR/empty-match.rs:49:6
-   |
-LL | enum NonEmptyEnum5 {
-   |      ^^^^^^^^^^^^^
-...
-LL |     V1, V2, V3, V4, V5,
-   |     --  --  --  --  -- not covered
-   |     |   |   |   |
-   |     |   |   |   not covered
-   |     |   |   not covered
-   |     |   not covered
-   |     not covered
+  --> $DIR/empty-match.rs:38:10
+   |
+LL |     enum NonEmptyEnum5 {
+   |          ^^^^^^^^^^^^^
+LL |         V1,
+   |         -- not covered
+LL |         V2,
+   |         -- not covered
+LL |         V3,
+   |         -- not covered
+LL |         V4,
+   |         -- not covered
+LL |         V5,
+   |         -- not covered
    = note: the matched value is of type `NonEmptyEnum5`
    = note: match arms with guards don't count towards exhaustivity
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~             _ if false => {},
-LL +             _ => todo!()
+LL ~                 _ if false => {},
+LL +                 _ => todo!()
    |
 
-error: aborting due to 23 previous errors
+error: aborting due to 16 previous errors
 
-Some errors have detailed explanations: E0004, E0005.
-For more information about an error, try `rustc --explain E0004`.
+For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-match.rs b/tests/ui/pattern/usefulness/empty-match.rs
index fe5d0bce14f..321f24adc46 100644
--- a/tests/ui/pattern/usefulness/empty-match.rs
+++ b/tests/ui/pattern/usefulness/empty-match.rs
@@ -1,179 +1,65 @@
-// aux-build:empty.rs
 // revisions: normal exhaustive_patterns
 //
 // This tests a match with no arms on various types.
 #![feature(never_type)]
-#![feature(never_type_fallback)]
 #![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
 #![deny(unreachable_patterns)]
-//~^ NOTE the lint level is defined here
 
-extern crate empty;
-
-enum EmptyEnum {}
-
-struct NonEmptyStruct1;
-//~^ NOTE `NonEmptyStruct1` defined here
-//~| NOTE `NonEmptyStruct1` defined here
-struct NonEmptyStruct2(bool);
-//~^ NOTE `NonEmptyStruct2` defined here
-//~| NOTE `NonEmptyStruct2` defined here
-union NonEmptyUnion1 {
-    //~^ NOTE `NonEmptyUnion1` defined here
-    //~| NOTE `NonEmptyUnion1` defined here
-    foo: (),
-}
-union NonEmptyUnion2 {
-    //~^ NOTE `NonEmptyUnion2` defined here
-    //~| NOTE `NonEmptyUnion2` defined here
-    foo: (),
-    bar: (),
-}
-enum NonEmptyEnum1 {
-    //~^ NOTE `NonEmptyEnum1` defined here
-    //~| NOTE `NonEmptyEnum1` defined here
-    Foo(bool),
-    //~^ NOTE not covered
-    //~| NOTE not covered
-}
-enum NonEmptyEnum2 {
-    //~^ NOTE `NonEmptyEnum2` defined here
-    //~| NOTE `NonEmptyEnum2` defined here
-    Foo(bool),
-    //~^ NOTE not covered
-    //~| NOTE not covered
-    Bar,
-    //~^ NOTE not covered
-    //~| NOTE not covered
-}
-enum NonEmptyEnum5 {
-    //~^ NOTE `NonEmptyEnum5` defined here
-    //~| NOTE `NonEmptyEnum5` defined here
-    V1, V2, V3, V4, V5,
-    //~^ NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-    //~| NOTE not covered
-}
-
-fn empty_enum(x: EmptyEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
+fn nonempty() {
+    macro_rules! match_no_arms {
+        ($e:expr) => {
+            match $e {}
+        };
     }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
+    macro_rules! match_guarded_arm {
+        ($e:expr) => {
+            match $e {
+                _ if false => {}
+            }
+        };
     }
-}
 
-fn empty_foreign_enum(x: empty::EmptyForeignEnum) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
+    struct NonEmptyStruct1;
+    struct NonEmptyStruct2(bool);
+    union NonEmptyUnion1 {
+        foo: (),
     }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
+    union NonEmptyUnion2 {
+        foo: (),
+        bar: !,
     }
-}
-
-fn empty_foreign_enum_private(x: Option<empty::SecretlyUninhabitedForeignStruct>) {
-    let None = x;
-    //~^ ERROR refutable pattern in local binding
-    //~| NOTE `let` bindings require an "irrefutable pattern"
-    //~| NOTE for more information, visit
-    //~| NOTE the matched value is of type
-    //~| NOTE pattern `Some(_)` not covered
-    //[exhaustive_patterns]~| NOTE currently uninhabited, but this variant contains private fields
-}
-
-fn never(x: !) {
-    match x {} // ok
-    match x {
-        _ => {}, //~ ERROR unreachable pattern
+    enum NonEmptyEnum1 {
+        Foo(bool),
     }
-    match x {
-        _ if false => {}, //~ ERROR unreachable pattern
+    enum NonEmptyEnum2 {
+        Foo(bool),
+        Bar,
+    }
+    enum NonEmptyEnum5 {
+        V1,
+        V2,
+        V3,
+        V4,
+        V5,
     }
-}
-
-macro_rules! match_no_arms {
-    ($e:expr) => {
-        match $e {}
-    };
-}
-macro_rules! match_guarded_arm {
-    ($e:expr) => {
-        match $e {
-            _ if false => {}
-        }
-    };
-}
 
-fn main() {
     match_no_arms!(0u8); //~ ERROR type `u8` is non-empty
-                         //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct1); //~ ERROR type `NonEmptyStruct1` is non-empty
-                                     //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyStruct2(true)); //~ ERROR type `NonEmptyStruct2` is non-empty
-                                           //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion1 { foo: () })); //~ ERROR type `NonEmptyUnion1` is non-empty
-                                                  //~| NOTE the matched value is of type
     match_no_arms!((NonEmptyUnion2 { foo: () })); //~ ERROR type `NonEmptyUnion2` is non-empty
-                                                  //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
-                                              //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
-                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-                                              //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
-                                              //~| NOTE the matched value is of type
     match_no_arms!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-                                       //~| NOTE patterns `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`
-                                       //~| NOTE the matched value is of type
 
     match_guarded_arm!(0u8); //~ ERROR `_` not covered
-                             //~| NOTE the matched value is of type
-                             //~| NOTE match arms with guards don't count towards exhaustivity
-                             //~| NOTE pattern `_` not covered
-                             //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct1); //~ ERROR `NonEmptyStruct1` not covered
-                                         //~| NOTE pattern `NonEmptyStruct1` not covered
-                                         //~| NOTE the matched value is of type
-                                         //~| NOTE match arms with guards don't count towards exhaustivity
-                                         //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyStruct2(true)); //~ ERROR `NonEmptyStruct2(_)` not covered
-                                               //~| NOTE the matched value is of type
-                                               //~| NOTE pattern `NonEmptyStruct2(_)` not covered
-                                               //~| NOTE match arms with guards don't count towards exhaustivity
-                                               //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion1 { foo: () })); //~ ERROR `NonEmptyUnion1 { .. }` not covered
-                                                      //~| NOTE the matched value is of type
-                                                      //~| NOTE pattern `NonEmptyUnion1 { .. }` not covered
-                                                      //~| NOTE match arms with guards don't count towards exhaustivity
-                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!((NonEmptyUnion2 { foo: () })); //~ ERROR `NonEmptyUnion2 { .. }` not covered
-                                                      //~| NOTE the matched value is of type
-                                                      //~| NOTE pattern `NonEmptyUnion2 { .. }` not covered
-                                                      //~| NOTE match arms with guards don't count towards exhaustivity
-                                                      //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum1::Foo(true)); //~ ERROR `NonEmptyEnum1::Foo(_)` not covered
-                                                  //~| NOTE the matched value is of type
-                                                  //~| NOTE pattern `NonEmptyEnum1::Foo(_)` not covered
-                                                  //~| NOTE match arms with guards don't count towards exhaustivity
-                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum2::Foo(true)); //~ ERROR `NonEmptyEnum2::Foo(_)` and `NonEmptyEnum2::Bar` not covered
-                                                  //~| NOTE the matched value is of type
-                                                  //~| NOTE patterns `NonEmptyEnum2::Foo(_)` and
-                                                  //~| NOTE match arms with guards don't count towards exhaustivity
-                                                  //~| NOTE in this expansion of match_guarded_arm!
     match_guarded_arm!(NonEmptyEnum5::V1); //~ ERROR `NonEmptyEnum5::V1`, `NonEmptyEnum5::V2`, `NonEmptyEnum5::V3` and 2 more not covered
-                                           //~| NOTE the matched value is of type
-                                           //~| NOTE patterns `NonEmptyEnum5::V1`,
-                                           //~| NOTE match arms with guards don't count towards exhaustivity
-                                           //~| NOTE in this expansion of match_guarded_arm!
 }
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
new file mode 100644
index 00000000000..367aba3bdd6
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-types.exhaustive_patterns.stderr
@@ -0,0 +1,393 @@
+error: unreachable pattern
+  --> $DIR/empty-types.rs:47:9
+   |
+LL |         _ => {}
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-types.rs:13:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:50:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
+  --> $DIR/empty-types.rs:54:11
+   |
+LL |     match ref_never {}
+   |           ^^^^^^^^^
+   |
+   = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match ref_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:69:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:76:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:79:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:83:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` not covered
+  --> $DIR/empty-types.rs:87:11
+   |
+LL |     match res_u32_never {}
+   |           ^^^^^^^^^^^^^ pattern `Ok(_)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~     match res_u32_never {
+LL +         Ok(_) => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:95:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:100:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
+  --> $DIR/empty-types.rs:97:11
+   |
+LL |     match res_u32_never {
+   |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Err(_) => {},
+LL ~         Ok(1_u32..=u32::MAX) => todo!()
+   |
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:104:9
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref();
+   |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Result<&u32, &!>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref() else { todo!() };
+   |                                         ++++++++++++++++
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:115:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:119:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:122:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:123:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:126:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:127:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:136:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:139:13
+   |
+LL |             _ if false => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:148:13
+   |
+LL |             Some(_) => {}
+   |             ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:152:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:204:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:209:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:214:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:219:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:225:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:284:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:287:9
+   |
+LL |         (_, _) => {}
+   |         ^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:290:9
+   |
+LL |         Ok(_) => {}
+   |         ^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:291:9
+   |
+LL |         Err(_) => {}
+   |         ^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
+  --> $DIR/empty-types.rs:323:11
+   |
+LL |     match slice_never {}
+   |           ^^^^^^^^^^^
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]` not covered
+  --> $DIR/empty-types.rs:334:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ pattern `&[]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [_, _, _, ..] => {},
+LL +         &[] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]` not covered
+  --> $DIR/empty-types.rs:347:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ pattern `&[]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &[..] if false => {},
+LL +         &[] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
+  --> $DIR/empty-types.rs:353:11
+   |
+LL |     match *slice_never {}
+   |           ^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:363:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:366:9
+   |
+LL |         [_, _, _] => {}
+   |         ^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:369:9
+   |
+LL |         [_, ..] => {}
+   |         ^^^^^^^
+
+error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
+  --> $DIR/empty-types.rs:383:11
+   |
+LL |     match array_0_never {}
+   |           ^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!; 0]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match array_0_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:390:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+  --> $DIR/empty-types.rs:392:11
+   |
+LL |     match array_0_never {
+   |           ^^^^^^^^^^^^^ pattern `[]` not covered
+   |
+   = note: the matched value is of type `[!; 0]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [..] if false => {},
+LL +         [] => todo!()
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:411:9
+   |
+LL |         Some(_) => {}
+   |         ^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:416:9
+   |
+LL |         Some(_a) => {}
+   |         ^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:421:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:426:9
+   |
+LL |         _a => {}
+   |         ^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:598:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:601:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:604:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:607:9
+   |
+LL |         _x if false => {}
+   |         ^^
+
+error: aborting due to 49 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.normal.stderr b/tests/ui/pattern/usefulness/empty-types.normal.stderr
new file mode 100644
index 00000000000..133a95a821b
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-types.normal.stderr
@@ -0,0 +1,617 @@
+error: unreachable pattern
+  --> $DIR/empty-types.rs:47:9
+   |
+LL |         _ => {}
+   |         ^
+   |
+note: the lint level is defined here
+  --> $DIR/empty-types.rs:13:9
+   |
+LL | #![deny(unreachable_patterns)]
+   |         ^^^^^^^^^^^^^^^^^^^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:50:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: type `&!` is non-empty
+  --> $DIR/empty-types.rs:54:11
+   |
+LL |     match ref_never {}
+   |           ^^^^^^^^^
+   |
+   = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match ref_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
+  --> $DIR/empty-types.rs:66:11
+   |
+LL |     match tuple_half_never {}
+   |           ^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `(u32, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match tuple_half_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
+  --> $DIR/empty-types.rs:73:11
+   |
+LL |     match tuple_never {}
+   |           ^^^^^^^^^^^
+   |
+   = note: the matched value is of type `(!, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match tuple_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:83:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
+  --> $DIR/empty-types.rs:87:11
+   |
+LL |     match res_u32_never {}
+   |           ^^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match res_u32_never {
+LL +         Ok(_) | Err(_) => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:89:11
+   |
+LL |     match res_u32_never {
+   |           ^^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Ok(_) => {},
+LL +         Err(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Ok(1_u32..=u32::MAX)` not covered
+  --> $DIR/empty-types.rs:97:11
+   |
+LL |     match res_u32_never {
+   |           ^^^^^^^^^^^^^ pattern `Ok(1_u32..=u32::MAX)` not covered
+   |
+note: `Result<u32, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<u32, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Err(_) => {},
+LL ~         Ok(1_u32..=u32::MAX) => todo!()
+   |
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:102:9
+   |
+LL |     let Ok(_x) = res_u32_never;
+   |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Result<u32, !>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = res_u32_never else { todo!() };
+   |                                ++++++++++++++++
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:104:9
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref();
+   |         ^^^^^^ pattern `Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `Result<&u32, &!>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = res_u32_never.as_ref() else { todo!() };
+   |                                         ++++++++++++++++
+
+error[E0005]: refutable pattern in local binding
+  --> $DIR/empty-types.rs:108:9
+   |
+LL |     let Ok(_x) = &res_u32_never;
+   |         ^^^^^^ pattern `&Err(_)` not covered
+   |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
+   = note: the matched value is of type `&Result<u32, !>`
+help: you might want to use `let else` to handle the variant that isn't matched
+   |
+LL |     let Ok(_x) = &res_u32_never else { todo!() };
+   |                                 ++++++++++++++++
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
+  --> $DIR/empty-types.rs:112:11
+   |
+LL |     match result_never {}
+   |           ^^^^^^^^^^^^ patterns `Ok(_)` and `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match result_never {
+LL +         Ok(_) | Err(_) => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:117:11
+   |
+LL |     match result_never {
+   |           ^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL |         Ok(_) => {}, Err(_) => todo!()
+   |                    +++++++++++++++++++
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:136:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:139:13
+   |
+LL |             _ if false => {}
+   |             ^
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:142:15
+   |
+LL |         match opt_void {
+   |               ^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<Void>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<Void>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             None => {},
+LL +             Some(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:161:15
+   |
+LL |         match *ref_opt_void {
+   |               ^^^^^^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<Void>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<Void>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~             None => {},
+LL +             Some(_) => todo!()
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:204:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:209:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:214:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:219:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:225:13
+   |
+LL |             _ => {}
+   |             ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:284:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
+  --> $DIR/empty-types.rs:312:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `(u32, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `(!, !)` is non-empty
+  --> $DIR/empty-types.rs:314:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `(!, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: `Ok(_)` and `Err(_)` not covered
+  --> $DIR/empty-types.rs:316:11
+   |
+LL |     match *x {}
+   |           ^^ patterns `Ok(_)` and `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~     match *x {
+LL +         Ok(_) | Err(_) => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
+  --> $DIR/empty-types.rs:318:11
+   |
+LL |     match *x {}
+   |           ^^
+   |
+   = note: the matched value is of type `[!; 3]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *x {
+LL +         _ => todo!(),
+LL ~     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `&[!]` is non-empty
+  --> $DIR/empty-types.rs:323:11
+   |
+LL |     match slice_never {}
+   |           ^^^^^^^^^^^
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: `&[_, ..]` not covered
+  --> $DIR/empty-types.rs:325:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ pattern `&[_, ..]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [] => {},
+LL +         &[_, ..] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]`, `&[_]` and `&[_, _]` not covered
+  --> $DIR/empty-types.rs:334:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ patterns `&[]`, `&[_]` and `&[_, _]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         [_, _, _, ..] => {},
+LL +         &[] | &[_] | &[_, _] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&[]` and `&[_, ..]` not covered
+  --> $DIR/empty-types.rs:347:11
+   |
+LL |     match slice_never {
+   |           ^^^^^^^^^^^ patterns `&[]` and `&[_, ..]` not covered
+   |
+   = note: the matched value is of type `&[!]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
+   |
+LL ~         &[..] if false => {},
+LL +         &[] | &[_, ..] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!]` is non-empty
+  --> $DIR/empty-types.rs:353:11
+   |
+LL |     match *slice_never {}
+   |           ^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *slice_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!; 3]` is non-empty
+  --> $DIR/empty-types.rs:360:11
+   |
+LL |     match array_3_never {}
+   |           ^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!; 3]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match array_3_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error[E0004]: non-exhaustive patterns: type `[!; 0]` is non-empty
+  --> $DIR/empty-types.rs:383:11
+   |
+LL |     match array_0_never {}
+   |           ^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `[!; 0]`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match array_0_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:390:9
+   |
+LL |         _ => {}
+   |         ^
+
+error[E0004]: non-exhaustive patterns: `[]` not covered
+  --> $DIR/empty-types.rs:392:11
+   |
+LL |     match array_0_never {
+   |           ^^^^^^^^^^^^^ pattern `[]` not covered
+   |
+   = note: the matched value is of type `[!; 0]`
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         [..] if false => {},
+LL +         [] => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `&Some(_)` not covered
+  --> $DIR/empty-types.rs:446:11
+   |
+LL |     match ref_opt_never {
+   |           ^^^^^^^^^^^^^ pattern `&Some(_)` not covered
+   |
+note: `Option<!>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `&Option<!>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &None => {},
+LL +         &Some(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:487:11
+   |
+LL |     match *ref_opt_never {
+   |           ^^^^^^^^^^^^^^ pattern `Some(_)` not covered
+   |
+note: `Option<!>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<!>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         None => {},
+LL +         Some(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:535:11
+   |
+LL |     match *ref_res_never {
+   |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Ok(_) => {},
+LL +         Err(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Err(_)` not covered
+  --> $DIR/empty-types.rs:546:11
+   |
+LL |     match *ref_res_never {
+   |           ^^^^^^^^^^^^^^ pattern `Err(_)` not covered
+   |
+note: `Result<!, !>` defined here
+  --> $SRC_DIR/core/src/result.rs:LL:COL
+  ::: $SRC_DIR/core/src/result.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Result<!, !>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         Ok(_a) => {},
+LL +         Err(_) => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: type `(u32, !)` is non-empty
+  --> $DIR/empty-types.rs:565:11
+   |
+LL |     match *ref_tuple_half_never {}
+   |           ^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: the matched value is of type `(u32, !)`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown
+   |
+LL ~     match *ref_tuple_half_never {
+LL +         _ => todo!(),
+LL +     }
+   |
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:598:9
+   |
+LL |         _ => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:601:9
+   |
+LL |         _x => {}
+   |         ^^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:604:9
+   |
+LL |         _ if false => {}
+   |         ^
+
+error: unreachable pattern
+  --> $DIR/empty-types.rs:607:9
+   |
+LL |         _x if false => {}
+   |         ^^
+
+error[E0004]: non-exhaustive patterns: `&_` not covered
+  --> $DIR/empty-types.rs:631:11
+   |
+LL |     match ref_never {
+   |           ^^^^^^^^^ pattern `&_` not covered
+   |
+   = note: the matched value is of type `&!`
+   = note: references are always considered inhabited
+   = note: match arms with guards don't count towards exhaustivity
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         &_a if false => {},
+LL +         &_ => todo!()
+   |
+
+error[E0004]: non-exhaustive patterns: `Some(_)` not covered
+  --> $DIR/empty-types.rs:659:11
+   |
+LL |     match *x {
+   |           ^^ pattern `Some(_)` not covered
+   |
+note: `Option<Result<!, !>>` defined here
+  --> $SRC_DIR/core/src/option.rs:LL:COL
+  ::: $SRC_DIR/core/src/option.rs:LL:COL
+   |
+   = note: not covered
+   = note: the matched value is of type `Option<Result<!, !>>`
+help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
+   |
+LL ~         None => {},
+LL +         Some(_) => todo!()
+   |
+
+error: aborting due to 48 previous errors
+
+Some errors have detailed explanations: E0004, E0005.
+For more information about an error, try `rustc --explain E0004`.
diff --git a/tests/ui/pattern/usefulness/empty-types.rs b/tests/ui/pattern/usefulness/empty-types.rs
new file mode 100644
index 00000000000..1e1d23e446d
--- /dev/null
+++ b/tests/ui/pattern/usefulness/empty-types.rs
@@ -0,0 +1,665 @@
+// revisions: normal exhaustive_patterns
+//
+// This tests correct handling of empty types in exhaustiveness checking.
+//
+// Most of the subtlety of this file happens in scrutinee places which are not required to hold
+// valid data, namely dereferences and union field accesses. In these cases, empty arms can
+// generally not be omitted, except with `exhaustive_patterns` which ignores this..
+#![feature(never_type)]
+// This feature is useful to avoid `!` falling back to `()` all the time.
+#![feature(never_type_fallback)]
+#![cfg_attr(exhaustive_patterns, feature(exhaustive_patterns))]
+#![allow(dead_code, unreachable_code)]
+#![deny(unreachable_patterns)]
+
+#[derive(Copy, Clone)]
+enum Void {}
+
+/// A bunch of never situations that can't be normally constructed.
+#[derive(Copy, Clone)]
+struct NeverBundle {
+    never: !,
+    void: Void,
+    tuple_never: (!, !),
+    tuple_half_never: (u32, !),
+    array_3_never: [!; 3],
+    result_never: Result<!, !>,
+}
+
+/// A simplified `MaybeUninit` to test union field accesses.
+#[derive(Copy, Clone)]
+union Uninit<T: Copy> {
+    value: T,
+    uninit: (),
+}
+
+impl<T: Copy> Uninit<T> {
+    fn new() -> Self {
+        Self { uninit: () }
+    }
+}
+
+// Simple cases of omitting empty arms, all with known_valid scrutinees.
+fn basic(x: NeverBundle) {
+    let never: ! = x.never;
+    match never {}
+    match never {
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match never {
+        _x => {} //~ ERROR unreachable pattern
+    }
+
+    let ref_never: &! = &x.never;
+    match ref_never {}
+    //~^ ERROR non-empty
+    match ref_never {
+        // useful, reachable
+        _ => {}
+    }
+    match ref_never {
+        // useful, reachable
+        &_ => {}
+    }
+
+    let tuple_half_never: (u32, !) = x.tuple_half_never;
+    match tuple_half_never {}
+    //[normal]~^ ERROR non-empty
+    match tuple_half_never {
+        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+
+    let tuple_never: (!, !) = x.tuple_never;
+    match tuple_never {}
+    //[normal]~^ ERROR non-empty
+    match tuple_never {
+        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match tuple_never {
+        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match tuple_never.0 {}
+    match tuple_never.0 {
+        _ => {} //~ ERROR unreachable pattern
+    }
+
+    let res_u32_never: Result<u32, !> = Ok(0);
+    match res_u32_never {}
+    //~^ ERROR non-exhaustive
+    match res_u32_never {
+        //[normal]~^ ERROR non-exhaustive
+        Ok(_) => {}
+    }
+    match res_u32_never {
+        Ok(_) => {}
+        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match res_u32_never {
+        //~^ ERROR non-exhaustive
+        Ok(0) => {}
+        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    let Ok(_x) = res_u32_never;
+    //[normal]~^ ERROR refutable
+    let Ok(_x) = res_u32_never.as_ref();
+    //~^ ERROR refutable
+    // Non-obvious difference: here there's an implicit dereference in the patterns, which makes the
+    // inner place !known_valid. `exhaustive_patterns` ignores this.
+    let Ok(_x) = &res_u32_never;
+    //[normal]~^ ERROR refutable
+
+    let result_never: Result<!, !> = x.result_never;
+    match result_never {}
+    //[normal]~^ ERROR non-exhaustive
+    match result_never {
+        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match result_never {
+        //[normal]~^ ERROR non-exhaustive
+        Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match result_never {
+        Ok(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        _ => {}     //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match result_never {
+        Ok(_) => {}  //[exhaustive_patterns]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+}
+
+// Check for a few cases that `Void` and `!` are treated the same.
+fn void_same_as_never(x: NeverBundle) {
+    unsafe {
+        match x.void {}
+        match x.void {
+            _ => {} //~ ERROR unreachable pattern
+        }
+        match x.void {
+            _ if false => {} //~ ERROR unreachable pattern
+        }
+        let opt_void: Option<Void> = None;
+        match opt_void {
+            //[normal]~^ ERROR non-exhaustive
+            None => {}
+        }
+        match opt_void {
+            None => {}
+            Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        }
+        match opt_void {
+            None => {}
+            _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+        }
+
+        let ref_void: &Void = &x.void;
+        match *ref_void {}
+        match *ref_void {
+            _ => {}
+        }
+        let ref_opt_void: &Option<Void> = &None;
+        match *ref_opt_void {
+            //[normal]~^ ERROR non-exhaustive
+            None => {}
+        }
+        match *ref_opt_void {
+            None => {}
+            Some(_) => {}
+        }
+        match *ref_opt_void {
+            None => {}
+            _ => {}
+        }
+        match *ref_opt_void {
+            None => {}
+            _a => {}
+        }
+        let union_void = Uninit::<Void>::new();
+        match union_void.value {}
+        match union_void.value {
+            _ => {}
+        }
+        let ptr_void: *const Void = std::ptr::null();
+        match *ptr_void {}
+        match *ptr_void {
+            _ => {}
+        }
+    }
+}
+
+// Test if we correctly determine validity from the scrutinee expression.
+fn invalid_scrutinees(x: NeverBundle) {
+    let ptr_never: *const ! = std::ptr::null();
+    let never: ! = x.never;
+    let ref_never: &! = &never;
+
+    struct NestedNeverBundle(NeverBundle);
+    let nested_x = NestedNeverBundle(x);
+
+    // These should be considered known_valid and warn unreachable.
+    unsafe {
+        // A plain `!` value must be valid.
+        match never {}
+        match never {
+            _ => {} //~ ERROR unreachable pattern
+        }
+        // A block forces a copy.
+        match { *ptr_never } {}
+        match { *ptr_never } {
+            _ => {} //~ ERROR unreachable pattern
+        }
+        // This field access is not a dereference.
+        match x.never {}
+        match x.never {
+            _ => {} //~ ERROR unreachable pattern
+        }
+        // This nested field access is not a dereference.
+        match nested_x.0.never {}
+        match nested_x.0.never {
+            _ => {} //~ ERROR unreachable pattern
+        }
+        // Indexing is like a field access. This one does not access behind a reference.
+        let array_3_never: [!; 3] = x.array_3_never;
+        match array_3_never[0] {}
+        match array_3_never[0] {
+            _ => {} //~ ERROR unreachable pattern
+        }
+    }
+
+    // These should be considered !known_valid and not warn unreachable.
+    unsafe {
+        // A pointer may point to a place with an invalid value.
+        match *ptr_never {}
+        match *ptr_never {
+            _ => {}
+        }
+        // A reference may point to a place with an invalid value.
+        match *ref_never {}
+        match *ref_never {
+            _ => {}
+        }
+        // This field access is a dereference.
+        let ref_x: &NeverBundle = &x;
+        match ref_x.never {}
+        match ref_x.never {
+            _ => {}
+        }
+        // This nested field access is a dereference.
+        let nested_ref_x: &NestedNeverBundle = &nested_x;
+        match nested_ref_x.0.never {}
+        match nested_ref_x.0.never {
+            _ => {}
+        }
+        // A cast does not load.
+        match (*ptr_never as Void) {}
+        match (*ptr_never as Void) {
+            _ => {}
+        }
+        // A union field may contain invalid data.
+        let union_never = Uninit::<!>::new();
+        match union_never.value {}
+        match union_never.value {
+            _ => {}
+        }
+        // Indexing is like a field access. This one accesses behind a reference.
+        let slice_never: &[!] = &[];
+        match slice_never[0] {}
+        match slice_never[0] {
+            _ => {}
+        }
+    }
+}
+
+// Test we correctly track validity as we dig into patterns. Validity changes when we go under a
+// dereference or a union field access, and it otherwise preserved.
+fn nested_validity_tracking(bundle: NeverBundle) {
+    let never: ! = bundle.never;
+    let ref_never: &! = &never;
+    let tuple_never: (!, !) = bundle.tuple_never;
+    let result_never: Result<!, !> = bundle.result_never;
+    let union_never = Uninit::<!>::new();
+
+    // These should be considered known_valid and warn unreachable.
+    match never {
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match tuple_never {
+        (_, _) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match result_never {
+        Ok(_) => {}  //[exhaustive_patterns]~ ERROR unreachable pattern
+        Err(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+
+    // These should be considered !known_valid and not warn unreachable.
+    match ref_never {
+        &_ => {}
+    }
+    match union_never {
+        Uninit { value: _ } => {}
+    }
+}
+
+// Test we don't allow empty matches on empty types if the scrutinee is `!known_valid`.
+fn invalid_empty_match(bundle: NeverBundle) {
+    // We allow these two for backwards-compability.
+    let x: &! = &bundle.never;
+    match *x {}
+    let x: &Void = &bundle.void;
+    match *x {}
+
+    let x: &(u32, !) = &bundle.tuple_half_never;
+    match *x {} //[normal]~ ERROR non-exhaustive
+    let x: &(!, !) = &bundle.tuple_never;
+    match *x {} //[normal]~ ERROR non-exhaustive
+    let x: &Result<!, !> = &bundle.result_never;
+    match *x {} //[normal]~ ERROR non-exhaustive
+    let x: &[!; 3] = &bundle.array_3_never;
+    match *x {} //[normal]~ ERROR non-exhaustive
+}
+
+fn arrays_and_slices(x: NeverBundle) {
+    let slice_never: &[!] = &[];
+    match slice_never {}
+    //~^ ERROR non-empty
+    match slice_never {
+        //[normal]~^ ERROR not covered
+        [] => {}
+    }
+    match slice_never {
+        [] => {}
+        [_] => {}
+        [_, _, ..] => {}
+    }
+    match slice_never {
+        //[normal]~^ ERROR `&[]`, `&[_]` and `&[_, _]` not covered
+        //[exhaustive_patterns]~^^ ERROR `&[]` not covered
+        [_, _, _, ..] => {}
+    }
+    match slice_never {
+        [] => {}
+        _ => {}
+    }
+    match slice_never {
+        [] => {}
+        _x => {}
+    }
+    match slice_never {
+        //[normal]~^ ERROR `&[]` and `&[_, ..]` not covered
+        //[exhaustive_patterns]~^^ ERROR `&[]` not covered
+        &[..] if false => {}
+    }
+
+    match *slice_never {}
+    //~^ ERROR non-empty
+    match *slice_never {
+        _ => {}
+    }
+
+    let array_3_never: [!; 3] = x.array_3_never;
+    match array_3_never {}
+    //[normal]~^ ERROR non-empty
+    match array_3_never {
+        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match array_3_never {
+        [_, _, _] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match array_3_never {
+        [_, ..] => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+
+    let ref_array_3_never: &[!; 3] = &array_3_never;
+    match ref_array_3_never {
+        // useful, reachable
+        &[_, _, _] => {}
+    }
+    match ref_array_3_never {
+        // useful, !reachable
+        &[_x, _, _] => {}
+    }
+
+    let array_0_never: [!; 0] = [];
+    match array_0_never {}
+    //~^ ERROR non-empty
+    match array_0_never {
+        [] => {}
+    }
+    match array_0_never {
+        [] => {}
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match array_0_never {
+        //~^ ERROR `[]` not covered
+        [..] if false => {}
+    }
+}
+
+// The difference between `_` and `_a` patterns is that `_a` loads the value. In case of an empty
+// type, this asserts validity of the value, and thus the binding is unreachable. We don't yet
+// distinguish these cases since we don't lint "unreachable" on `useful && !reachable` arms.
+// Once/if never patterns are a thing, we can warn that the `_a` cases should be never patterns.
+fn bindings(x: NeverBundle) {
+    let opt_never: Option<!> = None;
+    let ref_never: &! = &x.never;
+    let ref_opt_never: &Option<!> = &None;
+
+    // On a known_valid place.
+    match opt_never {
+        None => {}
+        // !useful, !reachable
+        Some(_) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match opt_never {
+        None => {}
+        // !useful, !reachable
+        Some(_a) => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match opt_never {
+        None => {}
+        // !useful, !reachable
+        _ => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+    match opt_never {
+        None => {}
+        // !useful, !reachable
+        _a => {} //[exhaustive_patterns]~ ERROR unreachable pattern
+    }
+
+    // The scrutinee is known_valid, but under the `&` isn't anymore.
+    match ref_never {
+        // useful, reachable
+        _ => {}
+    }
+    match ref_never {
+        // useful, reachable
+        &_ => {}
+    }
+    match ref_never {
+        // useful, reachable
+        _a => {}
+    }
+    match ref_never {
+        // useful, !reachable
+        &_a => {}
+    }
+    match ref_opt_never {
+        //[normal]~^ ERROR non-exhaustive
+        &None => {}
+    }
+    match ref_opt_never {
+        &None => {}
+        // useful, reachable
+        _ => {}
+    }
+    match ref_opt_never {
+        &None => {}
+        // useful, reachable
+        _a => {}
+    }
+    match ref_opt_never {
+        &None => {}
+        // useful, reachable
+        &_ => {}
+    }
+    match ref_opt_never {
+        &None => {}
+        // useful, !reachable
+        &_a => {}
+    }
+
+    // On a !known_valid place.
+    match *ref_never {}
+    match *ref_never {
+        // useful, reachable
+        _ => {}
+    }
+    match *ref_never {
+        // useful, !reachable
+        _a => {}
+    }
+    // This is equivalent to `match ref_never { _a => {} }`. In other words, it asserts validity of
+    // `ref_never` but says nothing of the data at `*ref_never`.
+    match *ref_never {
+        // useful, reachable
+        ref _a => {}
+    }
+    match *ref_opt_never {
+        //[normal]~^ ERROR non-exhaustive
+        None => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, reachable
+        Some(_) => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, !reachable
+        Some(_a) => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, reachable
+        _ => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, !reachable
+        _a => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, !reachable
+        _a @ Some(_) => {}
+    }
+    // This is equivalent to `match ref_opt_never { None => {}, _a => {} }`. In other words, it
+    // asserts validity of `ref_opt_never` but says nothing of the data at `*ref_opt_never`.
+    match *ref_opt_never {
+        None => {}
+        // useful, reachable
+        ref _a => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, reachable
+        ref _a @ Some(_) => {}
+    }
+    match *ref_opt_never {
+        None => {}
+        // useful, !reachable
+        ref _a @ Some(_b) => {}
+    }
+
+    let ref_res_never: &Result<!, !> = &x.result_never;
+    match *ref_res_never {
+        //[normal]~^ ERROR non-exhaustive
+        // useful, reachable
+        Ok(_) => {}
+    }
+    match *ref_res_never {
+        // useful, reachable
+        Ok(_) => {}
+        // useful, reachable
+        _ => {}
+    }
+    match *ref_res_never {
+        //[normal]~^ ERROR non-exhaustive
+        // useful, !reachable
+        Ok(_a) => {}
+    }
+    match *ref_res_never {
+        // useful, !reachable
+        Ok(_a) => {}
+        // useful, reachable
+        _ => {}
+    }
+    match *ref_res_never {
+        // useful, !reachable
+        Ok(_a) => {}
+        // useful, reachable
+        Err(_) => {}
+    }
+
+    let ref_tuple_half_never: &(u32, !) = &x.tuple_half_never;
+    match *ref_tuple_half_never {}
+    //[normal]~^ ERROR non-empty
+    match *ref_tuple_half_never {
+        // useful, reachable
+        (_, _) => {}
+    }
+    match *ref_tuple_half_never {
+        // useful, reachable
+        (_x, _) => {}
+    }
+    match *ref_tuple_half_never {
+        // useful, !reachable
+        (_, _x) => {}
+    }
+    match *ref_tuple_half_never {
+        // useful, !reachable
+        (0, _x) => {}
+        // useful, reachable
+        (1.., _) => {}
+    }
+}
+
+// When we execute the condition for a guard we loads from all bindings. This asserts validity at
+// all places with bindings. Surprisingly this can make subsequent arms unreachable. We choose to
+// not detect this in exhaustiveness because this is rather subtle. With never patterns, we would
+// recommend using a never pattern instead.
+fn guards_and_validity(x: NeverBundle) {
+    let never: ! = x.never;
+    let ref_never: &! = &never;
+
+    // Basic guard behavior when known_valid.
+    match never {}
+    match never {
+        _ => {} //~ ERROR unreachable pattern
+    }
+    match never {
+        _x => {} //~ ERROR unreachable pattern
+    }
+    match never {
+        _ if false => {} //~ ERROR unreachable pattern
+    }
+    match never {
+        _x if false => {} //~ ERROR unreachable pattern
+    }
+
+    // If the pattern under the guard doesn't load, all is normal.
+    match *ref_never {
+        // useful, reachable
+        _ if false => {}
+        // useful, reachable
+        _ => {}
+    }
+    // Now the madness commences. The guard caused a load of the value thus asserting validity. So
+    // there's no invalid value for `_` to catch. So the second pattern is unreachable despite the
+    // guard not being taken.
+    match *ref_never {
+        // useful, !reachable
+        _a if false => {}
+        // !useful, !reachable
+        _ => {}
+    }
+    // The above still applies to the implicit `_` pattern used for exhaustiveness.
+    match *ref_never {
+        // useful, !reachable
+        _a if false => {}
+    }
+    match ref_never {
+        //[normal]~^ ERROR non-exhaustive
+        // useful, !reachable
+        &_a if false => {}
+    }
+
+    // Same but with subpatterns.
+    let ref_result_never: &Result<!, !> = &x.result_never;
+    match *ref_result_never {
+        // useful, !reachable
+        Ok(_x) if false => {}
+        // !useful, !reachable
+        Ok(_) => {}
+        // useful, !reachable
+        Err(_) => {}
+    }
+    let ref_tuple_never: &(!, !) = &x.tuple_never;
+    match *ref_tuple_never {
+        // useful, !reachable
+        (_, _x) if false => {}
+        // !useful, !reachable
+        (_, _) => {}
+    }
+}
+
+fn diagnostics_subtlety(x: NeverBundle) {
+    // Regression test for diagnostics: don't report `Some(Ok(_))` and `Some(Err(_))`.
+    let x: &Option<Result<!, !>> = &None;
+    match *x {
+        //[normal]~^ ERROR `Some(_)` not covered
+        None => {}
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.rs b/tests/ui/pattern/usefulness/slice_of_empty.rs
index fe068871195..3cbd0eba57f 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.rs
+++ b/tests/ui/pattern/usefulness/slice_of_empty.rs
@@ -11,12 +11,12 @@ fn foo(nevers: &[!]) {
 
     match nevers {
         &[] => (),
-        &[_] => (),        //~ ERROR unreachable pattern
-        &[_, _, ..] => (), //~ ERROR unreachable pattern
+        &[_] => (),
+        &[_, _, ..] => (),
     };
 
     match nevers {
         //~^ ERROR non-exhaustive patterns: `&[]` not covered
-        &[_] => (), //~ ERROR unreachable pattern
+        &[_] => (),
     };
 }
diff --git a/tests/ui/pattern/usefulness/slice_of_empty.stderr b/tests/ui/pattern/usefulness/slice_of_empty.stderr
index 07bb6b3a67d..d56360d4cec 100644
--- a/tests/ui/pattern/usefulness/slice_of_empty.stderr
+++ b/tests/ui/pattern/usefulness/slice_of_empty.stderr
@@ -1,27 +1,3 @@
-error: unreachable pattern
-  --> $DIR/slice_of_empty.rs:14:9
-   |
-LL |         &[_] => (),
-   |         ^^^^
-   |
-note: the lint level is defined here
-  --> $DIR/slice_of_empty.rs:3:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/slice_of_empty.rs:15:9
-   |
-LL |         &[_, _, ..] => (),
-   |         ^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/slice_of_empty.rs:20:9
-   |
-LL |         &[_] => (),
-   |         ^^^^
-
 error[E0004]: non-exhaustive patterns: `&[]` not covered
   --> $DIR/slice_of_empty.rs:18:11
    |
@@ -31,9 +7,10 @@ LL |     match nevers {
    = note: the matched value is of type `&[!]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL |         &[_] => (), &[] => todo!(),
-   |                   ++++++++++++++++
+LL ~         &[_] => (),
+LL ~         &[] => todo!(),
+   |
 
-error: aborting due to 4 previous errors
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0004`.
diff --git a/tests/ui/privacy/auxiliary/issue-117997.rs b/tests/ui/privacy/auxiliary/issue-117997.rs
new file mode 100644
index 00000000000..6f71cc2ba35
--- /dev/null
+++ b/tests/ui/privacy/auxiliary/issue-117997.rs
@@ -0,0 +1,35 @@
+// no-prefer-dynamic
+// compile-flags: --crate-type=rlib
+
+pub use impl_mod::TraitImplementer as Implementer;
+
+pub use trait_mod::get_assoc;
+
+mod impl_mod {
+    use crate::trait_mod::TraitWithAssocType;
+
+    pub struct TraitImplementer {}
+    pub struct AssociatedType {}
+
+    impl AssociatedType {
+        pub fn method_on_assoc(&self) -> i32 {
+            todo!()
+        }
+    }
+
+    impl TraitWithAssocType for TraitImplementer {
+        type AssocType = AssociatedType;
+    }
+}
+
+mod trait_mod {
+    use crate::Implementer;
+
+    pub fn get_assoc() -> <Implementer as TraitWithAssocType>::AssocType {
+        todo!()
+    }
+
+    pub trait TraitWithAssocType {
+        type AssocType;
+    }
+}
diff --git a/tests/ui/privacy/issue-117997.rs b/tests/ui/privacy/issue-117997.rs
new file mode 100644
index 00000000000..d8284ef2997
--- /dev/null
+++ b/tests/ui/privacy/issue-117997.rs
@@ -0,0 +1,8 @@
+// aux-build:issue-117997.rs
+// build-pass
+
+extern crate issue_117997;
+
+pub fn main() {
+    issue_117997::get_assoc().method_on_assoc();
+}
diff --git a/tests/ui/privacy/private-in-public.rs b/tests/ui/privacy/private-in-public.rs
index 3fff2d51710..7b8e0fbe6b6 100644
--- a/tests/ui/privacy/private-in-public.rs
+++ b/tests/ui/privacy/private-in-public.rs
@@ -106,6 +106,7 @@ mod aliases_pub {
     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
     //~^ WARNING type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
     //~| WARNING associated type `aliases_pub::PrivTr::Assoc` is more private than the item `aliases_pub::f3`
+    //~^^^ WARNING trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3`
 
     impl PrivUseAlias {
         pub fn f(arg: Priv) {}
@@ -135,6 +136,7 @@ mod aliases_priv {
     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
     //~^ WARNING type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
     //~| WARNING associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3`
+    //~^^^ WARNING trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3`
 }
 
 mod aliases_params {
diff --git a/tests/ui/privacy/private-in-public.stderr b/tests/ui/privacy/private-in-public.stderr
index 49cc2e19bf0..ff3061337ff 100644
--- a/tests/ui/privacy/private-in-public.stderr
+++ b/tests/ui/privacy/private-in-public.stderr
@@ -288,6 +288,18 @@ note: but associated type `aliases_pub::PrivTr::Assoc` is only usable at visibil
 LL |         type Assoc = m::Pub3;
    |         ^^^^^^^^^^
 
+warning: trait `aliases_pub::PrivTr` is more private than the item `aliases_pub::f3`
+  --> $DIR/private-in-public.rs:106:5
+   |
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_pub::f3` is reachable at visibility `pub(crate)`
+   |
+note: but trait `aliases_pub::PrivTr` is only usable at visibility `pub(self)`
+  --> $DIR/private-in-public.rs:100:5
+   |
+LL |     trait PrivTr {
+   |     ^^^^^^^^^^^^
+
 warning: type `aliases_pub::Priv` is more private than the item `aliases_pub::f3`
   --> $DIR/private-in-public.rs:106:5
    |
@@ -301,76 +313,88 @@ LL |     struct Priv;
    |     ^^^^^^^^^^^
 
 warning: type `Priv1` is more private than the item `aliases_priv::f1`
-  --> $DIR/private-in-public.rs:133:5
+  --> $DIR/private-in-public.rs:134:5
    |
 LL |     pub fn f1(arg: PrivUseAlias) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f1` is reachable at visibility `pub(crate)`
    |
 note: but type `Priv1` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:118:5
+  --> $DIR/private-in-public.rs:119:5
    |
 LL |     struct Priv1;
    |     ^^^^^^^^^^^^
 
 warning: type `Priv2` is more private than the item `aliases_priv::f2`
-  --> $DIR/private-in-public.rs:134:5
+  --> $DIR/private-in-public.rs:135:5
    |
 LL |     pub fn f2(arg: PrivAlias) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f2` is reachable at visibility `pub(crate)`
    |
 note: but type `Priv2` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:119:5
+  --> $DIR/private-in-public.rs:120:5
    |
 LL |     struct Priv2;
    |     ^^^^^^^^^^^^
 
 warning: associated type `aliases_priv::PrivTr::Assoc` is more private than the item `aliases_priv::f3`
-  --> $DIR/private-in-public.rs:135:5
+  --> $DIR/private-in-public.rs:136:5
    |
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
    |
 note: but associated type `aliases_priv::PrivTr::Assoc` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:129:9
+  --> $DIR/private-in-public.rs:130:9
    |
 LL |         type Assoc = Priv3;
    |         ^^^^^^^^^^
 
+warning: trait `aliases_priv::PrivTr` is more private than the item `aliases_priv::f3`
+  --> $DIR/private-in-public.rs:136:5
+   |
+LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
+   |
+note: but trait `aliases_priv::PrivTr` is only usable at visibility `pub(self)`
+  --> $DIR/private-in-public.rs:129:5
+   |
+LL |     trait PrivTr {
+   |     ^^^^^^^^^^^^
+
 warning: type `aliases_priv::Priv` is more private than the item `aliases_priv::f3`
-  --> $DIR/private-in-public.rs:135:5
+  --> $DIR/private-in-public.rs:136:5
    |
 LL |     pub fn f3(arg: <Priv as PrivTr>::Assoc) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_priv::f3` is reachable at visibility `pub(crate)`
    |
 note: but type `aliases_priv::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:116:5
+  --> $DIR/private-in-public.rs:117:5
    |
 LL |     struct Priv;
    |     ^^^^^^^^^^^
 
 warning: type `aliases_params::Priv` is more private than the item `aliases_params::f2`
-  --> $DIR/private-in-public.rs:145:5
+  --> $DIR/private-in-public.rs:147:5
    |
 LL |     pub fn f2(arg: PrivAliasGeneric) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f2` is reachable at visibility `pub(crate)`
    |
 note: but type `aliases_params::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:141:5
+  --> $DIR/private-in-public.rs:143:5
    |
 LL |     struct Priv;
    |     ^^^^^^^^^^^
 
 warning: type `aliases_params::Priv` is more private than the item `aliases_params::f3`
-  --> $DIR/private-in-public.rs:147:5
+  --> $DIR/private-in-public.rs:149:5
    |
 LL |     pub fn f3(arg: Result<u8>) {}
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^ function `aliases_params::f3` is reachable at visibility `pub(crate)`
    |
 note: but type `aliases_params::Priv` is only usable at visibility `pub(self)`
-  --> $DIR/private-in-public.rs:141:5
+  --> $DIR/private-in-public.rs:143:5
    |
 LL |     struct Priv;
    |     ^^^^^^^^^^^
 
-warning: 31 warnings emitted
+warning: 33 warnings emitted
 
diff --git a/tests/ui/range/issue-73553-misinterp-range-literal.stderr b/tests/ui/range/issue-73553-misinterp-range-literal.stderr
index 52efa241d0b..15e55708c37 100644
--- a/tests/ui/range/issue-73553-misinterp-range-literal.stderr
+++ b/tests/ui/range/issue-73553-misinterp-range-literal.stderr
@@ -6,8 +6,8 @@ LL |     demo(tell(1)..tell(10));
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&std::ops::Range<usize>`
-                 found struct `std::ops::Range<usize>`
+   = note: expected reference `&std::ops::Range<_>`
+                 found struct `std::ops::Range<_>`
 note: function defined here
   --> $DIR/issue-73553-misinterp-range-literal.rs:3:4
    |
diff --git a/tests/ui/regions/issue-101280.stderr b/tests/ui/regions/issue-101280.stderr
index 70953808b81..48deb99494b 100644
--- a/tests/ui/regions/issue-101280.stderr
+++ b/tests/ui/regions/issue-101280.stderr
@@ -6,8 +6,8 @@ LL | fn f<'r>(f: fn(Cell<(&'r i32, &i32)>)) -> Ty {
 LL |     f
    |     ^ one type is more general than the other
    |
-   = note: expected fn pointer `for<'r> fn(Cell<(&'r i32, &'r i32)>)`
-              found fn pointer `for<'a> fn(Cell<(&'r i32, &'a i32)>)`
+   = note: expected fn pointer `for<'r> fn(Cell<(&'r _, &'r _)>)`
+              found fn pointer `for<'a> fn(Cell<(&'r _, &'a _)>)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
index 03d5a0be723..d8269514bef 100644
--- a/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-lifetime-bounds-on-fns-where-clause.stderr
@@ -6,8 +6,8 @@ LL |     let _: fn(&mut &isize, &mut &isize) = a;
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
-                 found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
+                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
index 250571f1556..e383f352b9e 100644
--- a/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
+++ b/tests/ui/regions/region-multiple-lifetime-bounds-on-fns-where-clause.stderr
@@ -6,8 +6,8 @@ LL |     let _: fn(&mut &isize, &mut &isize, &mut &isize) = a;
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b isize, &'c mut &'d isize, &'e mut &'f isize)`
-                 found fn item `for<'a, 'b, 'c> fn(&'a mut &isize, &'b mut &isize, &'c mut &isize) {a::<'_, '_, '_>}`
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd, 'e, 'f> fn(&'a mut &'b _, &'c mut &'d _, &'e mut &'f _)`
+                 found fn item `for<'a, 'b, 'c> fn(&'a mut &_, &'b mut &_, &'c mut &_) {a::<'_, '_, '_>}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
index 31dd7efe067..989e91c702b 100644
--- a/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
+++ b/tests/ui/regions/regions-lifetime-bounds-on-fns.stderr
@@ -6,8 +6,8 @@ LL |     let _: fn(&mut &isize, &mut &isize) = a;
    |            |
    |            expected due to this
    |
-   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b isize, &'c mut &'d isize)`
-                 found fn item `for<'a, 'b> fn(&'a mut &isize, &'b mut &isize) {a::<'_, '_>}`
+   = note: expected fn pointer `for<'a, 'b, 'c, 'd> fn(&'a mut &'b _, &'c mut &'d _)`
+                 found fn item `for<'a, 'b> fn(&'a mut &_, &'b mut &_) {a::<'_, '_>}`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr
index c805c9eb125..6e44c280f75 100644
--- a/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr
+++ b/tests/ui/resolve/resolve-inconsistent-binding-mode.stderr
@@ -62,8 +62,8 @@ LL |         Opts::A(ref mut i) | Opts::B(ref i) => {}
    |                 |
    |                 first introduced with type `&mut isize` here
    |
-   = note: expected mutable reference `&mut isize`
-                      found reference `&isize`
+   = note: expected mutable reference `&mut _`
+                      found reference `&_`
    = note: in the same arm, a binding must have the same type in all alternatives
 
 error: aborting due to 6 previous errors
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.rs b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
new file mode 100644
index 00000000000..e298112244a
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.rs
@@ -0,0 +1,33 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+fn main() {}
+
+macro_rules! never {
+    () => { ! }
+}
+
+fn no_arms_or_guards(x: Void) {
+    match None::<Void> {
+        Some(!) => {}
+        //~^ ERROR a never pattern is always unreachable
+        None => {}
+    }
+    match None::<Void> {
+        Some(!) if true,
+        //~^ ERROR guard on a never pattern
+        None => {}
+    }
+    match None::<Void> {
+        Some(!) if true => {}
+        //~^ ERROR a never pattern is always unreachable
+        None => {}
+    }
+    match None::<Void> {
+        Some(never!()) => {},
+        //~^ ERROR a never pattern is always unreachable
+        None => {}
+    }
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
new file mode 100644
index 00000000000..bfbc7a1b534
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/check.stderr
@@ -0,0 +1,35 @@
+error: a never pattern is always unreachable
+  --> $DIR/check.rs:14:20
+   |
+LL |         Some(!) => {}
+   |                    ^^
+   |                    |
+   |                    this will never be executed
+   |                    help: remove this expression
+
+error: a guard on a never pattern will never be run
+  --> $DIR/check.rs:19:20
+   |
+LL |         Some(!) if true,
+   |                    ^^^^ help: remove this guard
+
+error: a never pattern is always unreachable
+  --> $DIR/check.rs:24:28
+   |
+LL |         Some(!) if true => {}
+   |                            ^^
+   |                            |
+   |                            this will never be executed
+   |                            help: remove this expression
+
+error: a never pattern is always unreachable
+  --> $DIR/check.rs:29:27
+   |
+LL |         Some(never!()) => {},
+   |                           ^^
+   |                           |
+   |                           this will never be executed
+   |                           help: remove this expression
+
+error: aborting due to 4 previous errors
+
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs
new file mode 100644
index 00000000000..1b23e60e0ca
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.rs
@@ -0,0 +1,71 @@
+#![feature(never_patterns)]
+#![allow(incomplete_features)]
+
+enum Void {}
+
+fn main() {}
+
+macro_rules! never {
+    () => { ! }
+}
+
+fn parse(x: Void) {
+    match None::<Void> {
+        None => {}
+        Some(!),
+    }
+    match None::<Void> {
+        Some(!),
+        None => {}
+    }
+    match None::<Void> {
+        None => {}
+        Some(!)
+    }
+    match None::<Void> {
+        Some(!)
+        //~^ ERROR expected `,` following `match` arm
+        None => {}
+    }
+    match None::<Void> {
+        Some(!) if true
+        //~^ ERROR expected `,` following `match` arm
+        //~| ERROR guard on a never pattern
+        None => {}
+    }
+    match None::<Void> {
+        Some(!) if true,
+        //~^ ERROR guard on a never pattern
+        None => {}
+    }
+    match None::<Void> {
+        Some(!) <=
+        //~^ ERROR expected one of
+    }
+    match x {
+        never!(),
+    }
+    match x {
+        never!() if true,
+        //~^ ERROR guard on a never pattern
+    }
+    match x {
+        never!()
+    }
+    match &x {
+        &never!(),
+    }
+    match None::<Void> {
+        Some(never!()),
+        None => {}
+    }
+    match x { ! }
+    match &x { &! }
+
+    let res: Result<bool, Void> = Ok(false);
+    let Ok(_) = res;
+    let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
+    //~^ ERROR top-level or-patterns are not allowed in `let` bindings
+    let (Ok(_) | Err(!)) = &res;
+    let (Ok(_) | Err(&!)) = res.as_ref();
+}
diff --git a/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr
new file mode 100644
index 00000000000..e81a13a3967
--- /dev/null
+++ b/tests/ui/rfcs/rfc-0000-never_patterns/parse.stderr
@@ -0,0 +1,44 @@
+error: expected `,` following `match` arm
+  --> $DIR/parse.rs:26:16
+   |
+LL |         Some(!)
+   |                ^ help: missing a comma here to end this `match` arm: `,`
+
+error: expected `,` following `match` arm
+  --> $DIR/parse.rs:31:24
+   |
+LL |         Some(!) if true
+   |                        ^ help: missing a comma here to end this `match` arm: `,`
+
+error: expected one of `,`, `=>`, `if`, `|`, or `}`, found `<=`
+  --> $DIR/parse.rs:42:17
+   |
+LL |         Some(!) <=
+   |                 ^^ expected one of `,`, `=>`, `if`, `|`, or `}`
+
+error: top-level or-patterns are not allowed in `let` bindings
+  --> $DIR/parse.rs:67:9
+   |
+LL |     let Ok(_) | Err(!) = &res; // Disallowed; see #82048.
+   |         ^^^^^^^^^^^^^^ help: wrap the pattern in parentheses: `(Ok(_) | Err(!))`
+
+error: a guard on a never pattern will never be run
+  --> $DIR/parse.rs:31:20
+   |
+LL |         Some(!) if true
+   |                    ^^^^ help: remove this guard
+
+error: a guard on a never pattern will never be run
+  --> $DIR/parse.rs:37:20
+   |
+LL |         Some(!) if true,
+   |                    ^^^^ help: remove this guard
+
+error: a guard on a never pattern will never be run
+  --> $DIR/parse.rs:49:21
+   |
+LL |         never!() if true,
+   |                     ^^^^ help: remove this guard
+
+error: aborting due to 7 previous errors
+
diff --git a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr
index 181f57899a9..970a9c151c1 100644
--- a/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr
+++ b/tests/ui/rfcs/rfc-2005-default-binding-mode/lit.stderr
@@ -6,8 +6,8 @@ LL |     match &s {
 LL |             "abc" => true,
    |             ^^^^^ expected `&&str`, found `&str`
    |
-   = note: expected reference `&&str`
-              found reference `&'static str`
+   = note: expected reference `&&_`
+              found reference `&'static _`
 
 error[E0308]: mismatched types
   --> $DIR/lit.rs:16:9
diff --git a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
index 61aae850a94..86f2d9b6ec8 100644
--- a/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
+++ b/tests/ui/rfcs/rfc-2528-type-changing-struct-update/issue-92010-trait-bound-not-satisfied.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |     fn y(&self, y: f64) -> Self { P{y, .. self.clone() } }
    |                                           ^^^^^^^^^^^^ expected `P<T>`, found `&P<T>`
    |
-   = note: expected struct `P<T>`
-           found reference `&P<T>`
+   = note: expected struct `P<_>`
+           found reference `&P<_>`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
index 2c6fd83484f..2a2e8cec3f0 100644
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
+++ b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.rs
@@ -1,3 +1,5 @@
+// check-pass
+
 #![crate_type = "lib"]
 #![feature(no_core, lang_items, unboxed_closures, auto_traits, intrinsics, rustc_attrs)]
 #![feature(fundamental)]
@@ -6,8 +8,6 @@
 #![no_std]
 #![no_core]
 
-// known-bug: #110395
-
 #[lang = "sized"]
 trait Sized {}
 #[lang = "copy"]
diff --git a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr b/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr
deleted file mode 100644
index 3c1e6dda85c..00000000000
--- a/tests/ui/rfcs/rfc-2632-const-trait-impl/effects/minicore.stderr
+++ /dev/null
@@ -1,20 +0,0 @@
-error[E0493]: destructor of `Self` cannot be evaluated at compile-time
-  --> $DIR/minicore.rs:501:9
-   |
-LL |         *self = source.clone()
-   |         ^^^^^
-   |         |
-   |         the destructor for this type cannot be evaluated in constant functions
-   |         value is dropped here
-
-error[E0493]: destructor of `T` cannot be evaluated at compile-time
-  --> $DIR/minicore.rs:511:35
-   |
-LL | const fn drop<T: ~const Destruct>(_: T) {}
-   |                                   ^      - value is dropped here
-   |                                   |
-   |                                   the destructor for this type cannot be evaluated in constant functions
-
-error: aborting due to 2 previous errors
-
-For more information about this error, try `rustc --explain E0493`.
diff --git a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
index a7e36b2233e..e20ca50b88f 100644
--- a/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
+++ b/tests/ui/rfcs/rfc-3348-c-string-literals/no-nuls.rs
Binary files differdiff --git a/tests/ui/simd/masked-load-store-build-fail.rs b/tests/ui/simd/masked-load-store-build-fail.rs
new file mode 100644
index 00000000000..9b79b3bd6ea
--- /dev/null
+++ b/tests/ui/simd/masked-load-store-build-fail.rs
@@ -0,0 +1,74 @@
+// build-fail
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+    fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+    unsafe {
+        let mut arr = [4u8, 5, 6, 7];
+        let default = Simd::<u8, 4>([9; 4]);
+
+        simd_masked_load(
+            Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]),
+            arr.as_ptr(),
+            default
+        );
+        //~^^^^^ ERROR expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4
+
+        simd_masked_load(
+            Simd::<i8, 4>([-1, 0, -1, -1]),
+            arr.as_ptr() as *const i8,
+            default
+        );
+        //~^^^^^ ERROR expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8`
+
+        simd_masked_load(
+            Simd::<i8, 4>([-1, 0, -1, -1]),
+            arr.as_ptr(),
+            Simd::<u32, 4>([9; 4])
+        );
+        //~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32`
+
+        simd_masked_load(
+            Simd::<u8, 4>([1, 0, 1, 1]),
+            arr.as_ptr(),
+            default
+        );
+        //~^^^^^ ERROR expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
+
+        simd_masked_store(
+            Simd([-1i8; 4]),
+            arr.as_ptr(),
+            Simd([5u32; 4])
+        );
+        //~^^^^^ ERROR expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
+
+        simd_masked_store(
+            Simd([-1i8; 4]),
+            arr.as_ptr(),
+            Simd([5u8; 4])
+        );
+        //~^^^^^ ERROR expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8`
+
+        simd_masked_store(
+            Simd([-1i8; 4]),
+            arr.as_mut_ptr(),
+            Simd([5u8; 2])
+        );
+        //~^^^^^ ERROR expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2
+
+        simd_masked_store(
+            Simd([1u32; 4]),
+            arr.as_mut_ptr(),
+            Simd([5u8; 4])
+        );
+        //~^^^^^ ERROR expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
+    }
+}
diff --git a/tests/ui/simd/masked-load-store-build-fail.stderr b/tests/ui/simd/masked-load-store-build-fail.stderr
new file mode 100644
index 00000000000..59af83fe0e8
--- /dev/null
+++ b/tests/ui/simd/masked-load-store-build-fail.stderr
@@ -0,0 +1,83 @@
+error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected third argument with length 8 (same as input type `Simd<i8, 8>`), found `Simd<u8, 4>` with length 4
+  --> $DIR/masked-load-store-build-fail.rs:18:9
+   |
+LL | /         simd_masked_load(
+LL | |             Simd::<i8, 8>([-1, 0, -1, -1, 0, 0, 0, 0]),
+LL | |             arr.as_ptr(),
+LL | |             default
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of second argument `*const i8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*_ u8`
+  --> $DIR/masked-load-store-build-fail.rs:25:9
+   |
+LL | /         simd_masked_load(
+LL | |             Simd::<i8, 4>([-1, 0, -1, -1]),
+LL | |             arr.as_ptr() as *const i8,
+LL | |             default
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*_ u32`
+  --> $DIR/masked-load-store-build-fail.rs:32:9
+   |
+LL | /         simd_masked_load(
+LL | |             Simd::<i8, 4>([-1, 0, -1, -1]),
+LL | |             arr.as_ptr(),
+LL | |             Simd::<u32, 4>([9; 4])
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_load` intrinsic: expected element type `u8` of third argument `Simd<u8, 4>` to be a signed integer type
+  --> $DIR/masked-load-store-build-fail.rs:39:9
+   |
+LL | /         simd_masked_load(
+LL | |             Simd::<u8, 4>([1, 0, 1, 1]),
+LL | |             arr.as_ptr(),
+LL | |             default
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u32` of second argument `*const u8` to be a pointer to the element type `u32` of the first argument `Simd<u32, 4>`, found `u32` != `*mut u32`
+  --> $DIR/masked-load-store-build-fail.rs:46:9
+   |
+LL | /         simd_masked_store(
+LL | |             Simd([-1i8; 4]),
+LL | |             arr.as_ptr(),
+LL | |             Simd([5u32; 4])
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of second argument `*const u8` to be a pointer to the element type `u8` of the first argument `Simd<u8, 4>`, found `u8` != `*mut u8`
+  --> $DIR/masked-load-store-build-fail.rs:53:9
+   |
+LL | /         simd_masked_store(
+LL | |             Simd([-1i8; 4]),
+LL | |             arr.as_ptr(),
+LL | |             Simd([5u8; 4])
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected third argument with length 4 (same as input type `Simd<i8, 4>`), found `Simd<u8, 2>` with length 2
+  --> $DIR/masked-load-store-build-fail.rs:60:9
+   |
+LL | /         simd_masked_store(
+LL | |             Simd([-1i8; 4]),
+LL | |             arr.as_mut_ptr(),
+LL | |             Simd([5u8; 2])
+LL | |         );
+   | |_________^
+
+error[E0511]: invalid monomorphization of `simd_masked_store` intrinsic: expected element type `u8` of third argument `Simd<u32, 4>` to be a signed integer type
+  --> $DIR/masked-load-store-build-fail.rs:67:9
+   |
+LL | /         simd_masked_store(
+LL | |             Simd([1u32; 4]),
+LL | |             arr.as_mut_ptr(),
+LL | |             Simd([5u8; 4])
+LL | |         );
+   | |_________^
+
+error: aborting due to 8 previous errors
+
+For more information about this error, try `rustc --explain E0511`.
diff --git a/tests/ui/simd/masked-load-store-check-fail.rs b/tests/ui/simd/masked-load-store-check-fail.rs
new file mode 100644
index 00000000000..d4b35e211c8
--- /dev/null
+++ b/tests/ui/simd/masked-load-store-check-fail.rs
@@ -0,0 +1,32 @@
+// check-fail
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+    fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+    unsafe {
+        let mut arr = [4u8, 5, 6, 7];
+        let default = Simd::<u8, 4>([9; 4]);
+
+        let _x: Simd<u8, 2> = simd_masked_load(
+            Simd::<i8, 4>([-1, 0, -1, -1]),
+            arr.as_ptr(),
+            Simd::<u8, 4>([9; 4])
+        );
+        //~^^ ERROR mismatched types
+
+        let _x: Simd<u32, 4> = simd_masked_load(
+            Simd::<u8, 4>([1, 0, 1, 1]),
+            arr.as_ptr(),
+            default
+        );
+        //~^^ ERROR mismatched types
+    }
+}
diff --git a/tests/ui/simd/masked-load-store-check-fail.stderr b/tests/ui/simd/masked-load-store-check-fail.stderr
new file mode 100644
index 00000000000..5d205d607c9
--- /dev/null
+++ b/tests/ui/simd/masked-load-store-check-fail.stderr
@@ -0,0 +1,59 @@
+error[E0308]: mismatched types
+  --> $DIR/masked-load-store-check-fail.rs:21:13
+   |
+LL |         let _x: Simd<u8, 2> = simd_masked_load(
+   |                               ---------------- arguments to this function are incorrect
+...
+LL |             Simd::<u8, 4>([9; 4])
+   |             ^^^^^^^^^^^^^^^^^^^^^ expected `2`, found `4`
+   |
+   = note: expected struct `Simd<_, 2>`
+              found struct `Simd<_, 4>`
+help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed
+  --> $DIR/masked-load-store-check-fail.rs:18:31
+   |
+LL |           let _x: Simd<u8, 2> = simd_masked_load(
+   |  _______________________________^
+LL | |             Simd::<i8, 4>([-1, 0, -1, -1]),
+LL | |             arr.as_ptr(),
+LL | |             Simd::<u8, 4>([9; 4])
+   | |             --------------------- this argument influences the return type of `simd_masked_load`
+LL | |         );
+   | |_________^
+note: function defined here
+  --> $DIR/masked-load-store-check-fail.rs:5:8
+   |
+LL |     fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+   |        ^^^^^^^^^^^^^^^^
+
+error[E0308]: mismatched types
+  --> $DIR/masked-load-store-check-fail.rs:28:13
+   |
+LL |         let _x: Simd<u32, 4> = simd_masked_load(
+   |                                ---------------- arguments to this function are incorrect
+...
+LL |             default
+   |             ^^^^^^^ expected `Simd<u32, 4>`, found `Simd<u8, 4>`
+   |
+   = note: expected struct `Simd<u32, _>`
+              found struct `Simd<u8, _>`
+help: the return type of this call is `Simd<u8, 4>` due to the type of the argument passed
+  --> $DIR/masked-load-store-check-fail.rs:25:32
+   |
+LL |           let _x: Simd<u32, 4> = simd_masked_load(
+   |  ________________________________^
+LL | |             Simd::<u8, 4>([1, 0, 1, 1]),
+LL | |             arr.as_ptr(),
+LL | |             default
+   | |             ------- this argument influences the return type of `simd_masked_load`
+LL | |         );
+   | |_________^
+note: function defined here
+  --> $DIR/masked-load-store-check-fail.rs:5:8
+   |
+LL |     fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+   |        ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/simd/masked-load-store.rs b/tests/ui/simd/masked-load-store.rs
new file mode 100644
index 00000000000..74ee652ec6e
--- /dev/null
+++ b/tests/ui/simd/masked-load-store.rs
@@ -0,0 +1,33 @@
+// run-pass
+#![feature(repr_simd, platform_intrinsics)]
+
+extern "platform-intrinsic" {
+    fn simd_masked_load<M, P, T>(mask: M, pointer: P, values: T) -> T;
+    fn simd_masked_store<M, P, T>(mask: M, pointer: P, values: T) -> ();
+}
+
+#[derive(Copy, Clone)]
+#[repr(simd)]
+struct Simd<T, const N: usize>([T; N]);
+
+fn main() {
+    unsafe {
+        let a = Simd::<u8, 4>([0, 1, 2, 3]);
+        let b_src = [4u8, 5, 6, 7];
+        let b_default = Simd::<u8, 4>([9; 4]);
+        let b: Simd::<u8, 4> = simd_masked_load(
+            Simd::<i8, 4>([-1, 0, -1, -1]),
+            b_src.as_ptr(),
+            b_default
+        );
+
+        assert_eq!(&b.0, &[4, 9, 6, 7]);
+
+        let mut output = [u8::MAX; 5];
+
+        simd_masked_store(Simd::<i8, 4>([-1, -1, -1, 0]), output.as_mut_ptr(), a);
+        assert_eq!(&output, &[0, 1, 2, u8::MAX, u8::MAX]);
+        simd_masked_store(Simd::<i8, 4>([0, -1, -1, 0]), output[1..].as_mut_ptr(), b);
+        assert_eq!(&output, &[0, 1, 9, 6, u8::MAX]);
+    }
+}
diff --git a/tests/ui/static/static-reference-to-fn-1.stderr b/tests/ui/static/static-reference-to-fn-1.stderr
index ce9b6a739cf..6bf64974ef5 100644
--- a/tests/ui/static/static-reference-to-fn-1.stderr
+++ b/tests/ui/static/static-reference-to-fn-1.stderr
@@ -4,8 +4,8 @@ error[E0308]: mismatched types
 LL |         func: &foo,
    |               ^^^^ expected `&fn() -> Option<isize>`, found `&fn() -> Option<isize> {foo}`
    |
-   = note: expected reference `&fn() -> Option<isize>`
-              found reference `&fn() -> Option<isize> {foo}`
+   = note: expected reference `&fn() -> Option<_>`
+              found reference `&fn() -> Option<_> {foo}`
    = note: fn items are distinct from fn pointers
 help: consider casting to a fn pointer
    |
diff --git a/tests/ui/suggestions/as-ref.stderr b/tests/ui/suggestions/as-ref.stderr
index c5b2bb1260f..a42e2af3164 100644
--- a/tests/ui/suggestions/as-ref.stderr
+++ b/tests/ui/suggestions/as-ref.stderr
@@ -78,8 +78,8 @@ LL |     let y: Option<&usize> = x;
    |            |
    |            expected due to this
    |
-   = note:   expected enum `Option<&usize>`
-           found reference `&Option<usize>`
+   = note:   expected enum `Option<&_>`
+           found reference `&Option<_>`
 help: try using `.as_ref()` to convert `&Option<usize>` to `Option<&usize>`
    |
 LL |     let y: Option<&usize> = x.as_ref();
@@ -93,8 +93,8 @@ LL |     let y: Result<&usize, &usize> = x;
    |            |
    |            expected due to this
    |
-   = note:   expected enum `Result<&usize, &usize>`
-           found reference `&Result<usize, usize>`
+   = note:   expected enum `Result<&_, &_>`
+           found reference `&Result<_, _>`
 help: try using `.as_ref()` to convert `&Result<usize, usize>` to `Result<&usize, &usize>`
    |
 LL |     let y: Result<&usize, &usize> = x.as_ref();
@@ -108,8 +108,8 @@ LL |     let y: Result<&usize, usize> = x;
    |            |
    |            expected due to this
    |
-   = note:   expected enum `Result<&usize, usize>`
-           found reference `&Result<usize, usize>`
+   = note:   expected enum `Result<&_, _>`
+           found reference `&Result<_, _>`
 
 error[E0308]: mismatched types
   --> $DIR/as-ref.rs:22:42
diff --git a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
index 8c973995c34..afbb9c32d51 100644
--- a/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
+++ b/tests/ui/suggestions/clone-on-unconstrained-borrowed-type-param.stderr
@@ -8,8 +8,8 @@ LL | fn wat<T>(t: &T) -> T {
 LL |     t.clone()
    |     ^^^^^^^^^ expected type parameter `T`, found `&T`
    |
-   = note: expected type parameter `T`
-                   found reference `&T`
+   = note: expected type parameter `_`
+                   found reference `&_`
 note: `T` does not implement `Clone`, so `&T` was cloned instead
   --> $DIR/clone-on-unconstrained-borrowed-type-param.rs:3:5
    |
diff --git a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
index 54a16b8efa7..b1fb0254cd9 100644
--- a/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
+++ b/tests/ui/suggestions/method-access-to-range-literal-typo.stderr
@@ -18,8 +18,8 @@ LL |     fn method(&self) -> Option<&Vec<u8>> {
 LL |         self.option..as_ref().map(|x| x)
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Option<&Vec<u8>>`, found `Range<Option<Vec<u8>>>`
    |
-   = note: expected enum `Option<&Vec<u8>>`
-            found struct `std::ops::Range<Option<Vec<u8>>>`
+   = note: expected enum `Option<&Vec<_>>`
+            found struct `std::ops::Range<Option<Vec<_>>>`
 help: you likely meant to write a method call instead of a range
    |
 LL -         self.option..as_ref().map(|x| x)
diff --git a/tests/ui/suggestions/mut-ref-reassignment.stderr b/tests/ui/suggestions/mut-ref-reassignment.stderr
index b86a04c7cd3..a225b34f8c3 100644
--- a/tests/ui/suggestions/mut-ref-reassignment.stderr
+++ b/tests/ui/suggestions/mut-ref-reassignment.stderr
@@ -32,8 +32,8 @@ LL | fn suggestion2(opt: &mut Option<String>) {
 LL |     opt = Some(String::new())
    |           ^^^^^^^^^^^^^^^^^^^ expected `&mut Option<String>`, found `Option<String>`
    |
-   = note: expected mutable reference `&mut Option<String>`
-                           found enum `Option<String>`
+   = note: expected mutable reference `&mut Option<_>`
+                           found enum `Option<_>`
 help: consider dereferencing here to assign to the mutably borrowed value
    |
 LL |     *opt = Some(String::new())
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed
new file mode 100644
index 00000000000..61f06d802b6
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.fixed
@@ -0,0 +1,30 @@
+// run-rustfix
+
+struct A {}
+
+impl A {
+    fn hello(_a: i32) {}
+    fn test(_a: Self, _b: i32) {}
+}
+
+struct B<T> {
+    _b: T
+}
+impl<T> B<T> {
+    fn hello(_a: i32) {}
+    fn test(_a: Self, _b: i32) {}
+}
+
+fn main() {
+    let _a = A {};
+    A::hello(1);
+    //~^ ERROR no method named `hello` found
+    A::test(_a, 1);
+    //~^ ERROR no method named `test` found
+
+    let _b = B {_b: ""};
+    B::<&str>::hello(1);
+    //~^ ERROR no method named `hello` found
+    B::<&str>::test(_b, 1);
+    //~^ ERROR no method named `test` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs
new file mode 100644
index 00000000000..07e614f0c15
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.rs
@@ -0,0 +1,30 @@
+// run-rustfix
+
+struct A {}
+
+impl A {
+    fn hello(_a: i32) {}
+    fn test(_a: Self, _b: i32) {}
+}
+
+struct B<T> {
+    _b: T
+}
+impl<T> B<T> {
+    fn hello(_a: i32) {}
+    fn test(_a: Self, _b: i32) {}
+}
+
+fn main() {
+    let _a = A {};
+    _a.hello(1);
+    //~^ ERROR no method named `hello` found
+    _a.test(1);
+    //~^ ERROR no method named `test` found
+
+    let _b = B {_b: ""};
+    _b.hello(1);
+    //~^ ERROR no method named `hello` found
+    _b.test(1);
+    //~^ ERROR no method named `test` found
+}
diff --git a/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr
new file mode 100644
index 00000000000..793595784d9
--- /dev/null
+++ b/tests/ui/suggestions/suggest-assoc-fn-call-without-receiver.stderr
@@ -0,0 +1,79 @@
+error[E0599]: no method named `hello` found for struct `A` in the current scope
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:20:8
+   |
+LL | struct A {}
+   | -------- method `hello` not found for this struct
+...
+LL |     _a.hello(1);
+   |     ---^^^^^---
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `A::hello(1)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `A`
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:6:5
+   |
+LL |     fn hello(_a: i32) {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `test` found for struct `A` in the current scope
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:22:8
+   |
+LL | struct A {}
+   | -------- method `test` not found for this struct
+...
+LL |     _a.test(1);
+   |     ---^^^^---
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `A::test(_a, 1)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `A`
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:7:5
+   |
+LL |     fn test(_a: Self, _b: i32) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `hello` found for struct `B<&str>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:26:8
+   |
+LL | struct B<T> {
+   | ----------- method `hello` not found for this struct
+...
+LL |     _b.hello(1);
+   |     ---^^^^^---
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `B::<&str>::hello(1)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `B<T>`
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:14:5
+   |
+LL |     fn hello(_a: i32) {}
+   |     ^^^^^^^^^^^^^^^^^
+
+error[E0599]: no method named `test` found for struct `B<&str>` in the current scope
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:28:8
+   |
+LL | struct B<T> {
+   | ----------- method `test` not found for this struct
+...
+LL |     _b.test(1);
+   |     ---^^^^---
+   |     |  |
+   |     |  this is an associated function, not a method
+   |     help: use associated function syntax instead: `B::<&str>::test(_b, 1)`
+   |
+   = note: found the following associated functions; to be used as methods, functions must have a `self` parameter
+note: the candidate is defined in an impl for the type `B<T>`
+  --> $DIR/suggest-assoc-fn-call-without-receiver.rs:15:5
+   |
+LL |     fn test(_a: Self, _b: i32) {}
+   |     ^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/thir-print/thir-flat-const-variant.stdout b/tests/ui/thir-print/thir-flat-const-variant.stdout
index 7bddc925996..1840be7885b 100644
--- a/tests/ui/thir-print/thir-flat-const-variant.stdout
+++ b/tests/ui/thir-print/thir-flat-const-variant.stdout
@@ -66,18 +66,6 @@ Thir {
             ),
             span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(3),
-                lint_level: Inherited,
-                value: e3,
-            },
-            ty: Foo,
-            temp_lifetime: Some(
-                Node(3),
-            ),
-            span: $DIR/thir-flat-const-variant.rs:12:23: 12:35 (#0),
-        },
     ],
     stmts: [],
     params: [],
@@ -151,18 +139,6 @@ Thir {
             ),
             span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(3),
-                lint_level: Inherited,
-                value: e3,
-            },
-            ty: Foo,
-            temp_lifetime: Some(
-                Node(3),
-            ),
-            span: $DIR/thir-flat-const-variant.rs:13:23: 13:36 (#0),
-        },
     ],
     stmts: [],
     params: [],
@@ -236,18 +212,6 @@ Thir {
             ),
             span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(3),
-                lint_level: Inherited,
-                value: e3,
-            },
-            ty: Foo,
-            temp_lifetime: Some(
-                Node(3),
-            ),
-            span: $DIR/thir-flat-const-variant.rs:14:24: 14:36 (#0),
-        },
     ],
     stmts: [],
     params: [],
@@ -321,18 +285,6 @@ Thir {
             ),
             span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(3),
-                lint_level: Inherited,
-                value: e3,
-            },
-            ty: Foo,
-            temp_lifetime: Some(
-                Node(3),
-            ),
-            span: $DIR/thir-flat-const-variant.rs:15:24: 15:37 (#0),
-        },
     ],
     stmts: [],
     params: [],
@@ -348,7 +300,6 @@ Thir {
         Block {
             targeted_by_break: false,
             region_scope: Node(1),
-            opt_destruction_scope: None,
             span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0),
             stmts: [],
             expr: None,
@@ -380,18 +331,6 @@ Thir {
             ),
             span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(2),
-                lint_level: Inherited,
-                value: e1,
-            },
-            ty: (),
-            temp_lifetime: Some(
-                Node(2),
-            ),
-            span: $DIR/thir-flat-const-variant.rs:18:11: 18:13 (#0),
-        },
     ],
     stmts: [],
     params: [],
diff --git a/tests/ui/thir-print/thir-flat.stdout b/tests/ui/thir-print/thir-flat.stdout
index b0aa44b56aa..a31d08adab6 100644
--- a/tests/ui/thir-print/thir-flat.stdout
+++ b/tests/ui/thir-print/thir-flat.stdout
@@ -8,7 +8,6 @@ Thir {
         Block {
             targeted_by_break: false,
             region_scope: Node(1),
-            opt_destruction_scope: None,
             span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
             stmts: [],
             expr: None,
@@ -40,18 +39,6 @@ Thir {
             ),
             span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
         },
-        Expr {
-            kind: Scope {
-                region_scope: Destruction(2),
-                lint_level: Inherited,
-                value: e1,
-            },
-            ty: (),
-            temp_lifetime: Some(
-                Node(2),
-            ),
-            span: $DIR/thir-flat.rs:4:15: 4:17 (#0),
-        },
     ],
     stmts: [],
     params: [],
diff --git a/tests/ui/thir-print/thir-tree-match.stdout b/tests/ui/thir-print/thir-tree-match.stdout
index 3fc130f0176..60c9283abcf 100644
--- a/tests/ui/thir-print/thir-tree-match.stdout
+++ b/tests/ui/thir-print/thir-tree-match.stdout
@@ -31,262 +31,217 @@ body:
         span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
         kind: 
             Scope {
-                region_scope: Destruction(26)
-                lint_level: Inherited
+                region_scope: Node(26)
+                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26))
                 value:
                     Expr {
                         ty: bool
                         temp_lifetime: Some(Node(26))
                         span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
                         kind: 
-                            Scope {
-                                region_scope: Node(26)
-                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).26))
-                                value:
+                            Block {
+                                targeted_by_break: false
+                                span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+                                region_scope: Node(25)
+                                safety_mode: Safe
+                                stmts: []
+                                expr:
                                     Expr {
                                         ty: bool
                                         temp_lifetime: Some(Node(26))
-                                        span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
+                                        span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
                                         kind: 
-                                            Block {
-                                                targeted_by_break: false
-                                                opt_destruction_scope: None
-                                                span: $DIR/thir-tree-match.rs:15:32: 21:2 (#0)
-                                                region_scope: Node(25)
-                                                safety_mode: Safe
-                                                stmts: []
-                                                expr:
+                                            Scope {
+                                                region_scope: Node(3)
+                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3))
+                                                value:
                                                     Expr {
                                                         ty: bool
                                                         temp_lifetime: Some(Node(26))
                                                         span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
                                                         kind: 
-                                                            Scope {
-                                                                region_scope: Node(3)
-                                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).3))
-                                                                value:
+                                                            Match {
+                                                                scrutinee:
                                                                     Expr {
-                                                                        ty: bool
+                                                                        ty: Foo
                                                                         temp_lifetime: Some(Node(26))
-                                                                        span: $DIR/thir-tree-match.rs:16:5: 20:6 (#0)
+                                                                        span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
                                                                         kind: 
-                                                                            Match {
-                                                                                scrutinee:
+                                                                            Scope {
+                                                                                region_scope: Node(4)
+                                                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4))
+                                                                                value:
                                                                                     Expr {
                                                                                         ty: Foo
                                                                                         temp_lifetime: Some(Node(26))
                                                                                         span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
                                                                                         kind: 
-                                                                                            Scope {
-                                                                                                region_scope: Node(4)
-                                                                                                lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).4))
-                                                                                                value:
-                                                                                                    Expr {
-                                                                                                        ty: Foo
-                                                                                                        temp_lifetime: Some(Node(26))
-                                                                                                        span: $DIR/thir-tree-match.rs:16:11: 16:14 (#0)
-                                                                                                        kind: 
-                                                                                                            VarRef {
-                                                                                                                id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2))
-                                                                                                            }
-                                                                                                    }
+                                                                                            VarRef {
+                                                                                                id: LocalVarId(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).2))
                                                                                             }
                                                                                     }
-                                                                                arms: [
-                                                                                    Arm {
-                                                                                        pattern: 
+                                                                            }
+                                                                    }
+                                                                arms: [
+                                                                    Arm {
+                                                                        pattern: 
+                                                                            Pat: {
+                                                                                ty: Foo
+                                                                                span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0)
+                                                                                kind: PatKind {
+                                                                                    Variant {
+                                                                                        adt_def: 
+                                                                                            AdtDef {
+                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+                                                                                                flags: IS_ENUM
+                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
+                                                                                        args: []
+                                                                                        variant_index: 0
+                                                                                        subpatterns: [
                                                                                             Pat: {
-                                                                                                ty: Foo
-                                                                                                span: $DIR/thir-tree-match.rs:17:9: 17:32 (#0)
+                                                                                                ty: Bar
+                                                                                                span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0)
                                                                                                 kind: PatKind {
                                                                                                     Variant {
                                                                                                         adt_def: 
                                                                                                             AdtDef {
-                                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+                                                                                                                did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar)
+                                                                                                                variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }]
                                                                                                                 flags: IS_ENUM
-                                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
+                                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 10333377570083945360 }
                                                                                                         args: []
                                                                                                         variant_index: 0
-                                                                                                        subpatterns: [
-                                                                                                            Pat: {
-                                                                                                                ty: Bar
-                                                                                                                span: $DIR/thir-tree-match.rs:17:21: 17:31 (#0)
-                                                                                                                kind: PatKind {
-                                                                                                                    Variant {
-                                                                                                                        adt_def: 
-                                                                                                                            AdtDef {
-                                                                                                                                did: DefId(0:3 ~ thir_tree_match[fcf8]::Bar)
-                                                                                                                                variants: [VariantDef { def_id: DefId(0:4 ~ thir_tree_match[fcf8]::Bar::First), ctor: Some((Const, DefId(0:5 ~ thir_tree_match[fcf8]::Bar::First::{constructor#0}))), name: "First", discr: Relative(0), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:6 ~ thir_tree_match[fcf8]::Bar::Second), ctor: Some((Const, DefId(0:7 ~ thir_tree_match[fcf8]::Bar::Second::{constructor#0}))), name: "Second", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:8 ~ thir_tree_match[fcf8]::Bar::Third), ctor: Some((Const, DefId(0:9 ~ thir_tree_match[fcf8]::Bar::Third::{constructor#0}))), name: "Third", discr: Relative(2), fields: [], flags: NO_VARIANT_FLAGS }]
-                                                                                                                                flags: IS_ENUM
-                                                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 10333377570083945360 }
-                                                                                                                        args: []
-                                                                                                                        variant_index: 0
-                                                                                                                        subpatterns: []
-                                                                                                                    }
-                                                                                                                }
-                                                                                                            }
-                                                                                                        ]
+                                                                                                        subpatterns: []
                                                                                                     }
                                                                                                 }
                                                                                             }
-                                                                                        guard: None
-                                                                                        body: 
+                                                                                        ]
+                                                                                    }
+                                                                                }
+                                                                            }
+                                                                        guard: None
+                                                                        body: 
+                                                                            Expr {
+                                                                                ty: bool
+                                                                                temp_lifetime: Some(Node(13))
+                                                                                span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
+                                                                                kind: 
+                                                                                    Scope {
+                                                                                        region_scope: Node(13)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13))
+                                                                                        value:
                                                                                             Expr {
                                                                                                 ty: bool
                                                                                                 temp_lifetime: Some(Node(13))
                                                                                                 span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
                                                                                                 kind: 
-                                                                                                    Scope {
-                                                                                                        region_scope: Destruction(13)
-                                                                                                        lint_level: Inherited
-                                                                                                        value:
-                                                                                                            Expr {
-                                                                                                                ty: bool
-                                                                                                                temp_lifetime: Some(Node(13))
-                                                                                                                span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
-                                                                                                                kind: 
-                                                                                                                    Scope {
-                                                                                                                        region_scope: Node(13)
-                                                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).13))
-                                                                                                                        value:
-                                                                                                                            Expr {
-                                                                                                                                ty: bool
-                                                                                                                                temp_lifetime: Some(Node(13))
-                                                                                                                                span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0)
-                                                                                                                                kind: 
-                                                                                                                                    Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
+                                                                                                    Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:17:36: 17:40 (#0) }, neg: false)
 
-                                                                                                                            }
-                                                                                                                    }
-                                                                                                            }
-                                                                                                    }
                                                                                             }
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12))
-                                                                                        scope: Node(12)
-                                                                                        span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
                                                                                     }
-                                                                                    Arm {
-                                                                                        pattern: 
+                                                                            }
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).12))
+                                                                        scope: Node(12)
+                                                                        span: $DIR/thir-tree-match.rs:17:9: 17:40 (#0)
+                                                                    }
+                                                                    Arm {
+                                                                        pattern: 
+                                                                            Pat: {
+                                                                                ty: Foo
+                                                                                span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0)
+                                                                                kind: PatKind {
+                                                                                    Variant {
+                                                                                        adt_def: 
+                                                                                            AdtDef {
+                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+                                                                                                flags: IS_ENUM
+                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
+                                                                                        args: []
+                                                                                        variant_index: 0
+                                                                                        subpatterns: [
                                                                                             Pat: {
-                                                                                                ty: Foo
-                                                                                                span: $DIR/thir-tree-match.rs:18:9: 18:23 (#0)
+                                                                                                ty: Bar
+                                                                                                span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0)
                                                                                                 kind: PatKind {
-                                                                                                    Variant {
-                                                                                                        adt_def: 
-                                                                                                            AdtDef {
-                                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
-                                                                                                                flags: IS_ENUM
-                                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
-                                                                                                        args: []
-                                                                                                        variant_index: 0
-                                                                                                        subpatterns: [
-                                                                                                            Pat: {
-                                                                                                                ty: Bar
-                                                                                                                span: $DIR/thir-tree-match.rs:18:21: 18:22 (#0)
-                                                                                                                kind: PatKind {
-                                                                                                                    Wild
-                                                                                                                }
-                                                                                                            }
-                                                                                                        ]
-                                                                                                    }
+                                                                                                    Wild
                                                                                                 }
                                                                                             }
-                                                                                        guard: None
-                                                                                        body: 
+                                                                                        ]
+                                                                                    }
+                                                                                }
+                                                                            }
+                                                                        guard: None
+                                                                        body: 
+                                                                            Expr {
+                                                                                ty: bool
+                                                                                temp_lifetime: Some(Node(19))
+                                                                                span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
+                                                                                kind: 
+                                                                                    Scope {
+                                                                                        region_scope: Node(19)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19))
+                                                                                        value:
                                                                                             Expr {
                                                                                                 ty: bool
                                                                                                 temp_lifetime: Some(Node(19))
                                                                                                 span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
                                                                                                 kind: 
-                                                                                                    Scope {
-                                                                                                        region_scope: Destruction(19)
-                                                                                                        lint_level: Inherited
-                                                                                                        value:
-                                                                                                            Expr {
-                                                                                                                ty: bool
-                                                                                                                temp_lifetime: Some(Node(19))
-                                                                                                                span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
-                                                                                                                kind: 
-                                                                                                                    Scope {
-                                                                                                                        region_scope: Node(19)
-                                                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).19))
-                                                                                                                        value:
-                                                                                                                            Expr {
-                                                                                                                                ty: bool
-                                                                                                                                temp_lifetime: Some(Node(19))
-                                                                                                                                span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0)
-                                                                                                                                kind: 
-                                                                                                                                    Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
+                                                                                                    Literal( lit: Spanned { node: Bool(false), span: $DIR/thir-tree-match.rs:18:27: 18:32 (#0) }, neg: false)
 
-                                                                                                                            }
-                                                                                                                    }
-                                                                                                            }
-                                                                                                    }
                                                                                             }
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18))
-                                                                                        scope: Node(18)
-                                                                                        span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
                                                                                     }
-                                                                                    Arm {
-                                                                                        pattern: 
-                                                                                            Pat: {
-                                                                                                ty: Foo
-                                                                                                span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0)
-                                                                                                kind: PatKind {
-                                                                                                    Variant {
-                                                                                                        adt_def: 
-                                                                                                            AdtDef {
-                                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
-                                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
-                                                                                                                flags: IS_ENUM
-                                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
-                                                                                                        args: []
-                                                                                                        variant_index: 1
-                                                                                                        subpatterns: []
-                                                                                                    }
-                                                                                                }
-                                                                                            }
-                                                                                        guard: None
-                                                                                        body: 
+                                                                            }
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).18))
+                                                                        scope: Node(18)
+                                                                        span: $DIR/thir-tree-match.rs:18:9: 18:32 (#0)
+                                                                    }
+                                                                    Arm {
+                                                                        pattern: 
+                                                                            Pat: {
+                                                                                ty: Foo
+                                                                                span: $DIR/thir-tree-match.rs:19:9: 19:20 (#0)
+                                                                                kind: PatKind {
+                                                                                    Variant {
+                                                                                        adt_def: 
+                                                                                            AdtDef {
+                                                                                                did: DefId(0:10 ~ thir_tree_match[fcf8]::Foo)
+                                                                                                variants: [VariantDef { def_id: DefId(0:11 ~ thir_tree_match[fcf8]::Foo::FooOne), ctor: Some((Fn, DefId(0:12 ~ thir_tree_match[fcf8]::Foo::FooOne::{constructor#0}))), name: "FooOne", discr: Relative(0), fields: [FieldDef { did: DefId(0:13 ~ thir_tree_match[fcf8]::Foo::FooOne::0), name: "0", vis: Restricted(DefId(0:0 ~ thir_tree_match[fcf8])) }], flags: NO_VARIANT_FLAGS }, VariantDef { def_id: DefId(0:14 ~ thir_tree_match[fcf8]::Foo::FooTwo), ctor: Some((Const, DefId(0:15 ~ thir_tree_match[fcf8]::Foo::FooTwo::{constructor#0}))), name: "FooTwo", discr: Relative(1), fields: [], flags: NO_VARIANT_FLAGS }]
+                                                                                                flags: IS_ENUM
+                                                                                                repr: ReprOptions { int: None, align: None, pack: None, flags: (empty), field_shuffle_seed: 3477539199540094892 }
+                                                                                        args: []
+                                                                                        variant_index: 1
+                                                                                        subpatterns: []
+                                                                                    }
+                                                                                }
+                                                                            }
+                                                                        guard: None
+                                                                        body: 
+                                                                            Expr {
+                                                                                ty: bool
+                                                                                temp_lifetime: Some(Node(24))
+                                                                                span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
+                                                                                kind: 
+                                                                                    Scope {
+                                                                                        region_scope: Node(24)
+                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24))
+                                                                                        value:
                                                                                             Expr {
                                                                                                 ty: bool
                                                                                                 temp_lifetime: Some(Node(24))
                                                                                                 span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
                                                                                                 kind: 
-                                                                                                    Scope {
-                                                                                                        region_scope: Destruction(24)
-                                                                                                        lint_level: Inherited
-                                                                                                        value:
-                                                                                                            Expr {
-                                                                                                                ty: bool
-                                                                                                                temp_lifetime: Some(Node(24))
-                                                                                                                span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
-                                                                                                                kind: 
-                                                                                                                    Scope {
-                                                                                                                        region_scope: Node(24)
-                                                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).24))
-                                                                                                                        value:
-                                                                                                                            Expr {
-                                                                                                                                ty: bool
-                                                                                                                                temp_lifetime: Some(Node(24))
-                                                                                                                                span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0)
-                                                                                                                                kind: 
-                                                                                                                                    Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
+                                                                                                    Literal( lit: Spanned { node: Bool(true), span: $DIR/thir-tree-match.rs:19:24: 19:28 (#0) }, neg: false)
 
-                                                                                                                            }
-                                                                                                                    }
-                                                                                                            }
-                                                                                                    }
                                                                                             }
-                                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23))
-                                                                                        scope: Node(23)
-                                                                                        span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
                                                                                     }
-                                                                                ]
                                                                             }
+                                                                        lint_level: Explicit(HirId(DefId(0:16 ~ thir_tree_match[fcf8]::has_match).23))
+                                                                        scope: Node(23)
+                                                                        span: $DIR/thir-tree-match.rs:19:9: 19:28 (#0)
                                                                     }
+                                                                ]
                                                             }
                                                     }
                                             }
@@ -307,33 +262,21 @@ body:
         span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
         kind: 
             Scope {
-                region_scope: Destruction(2)
-                lint_level: Inherited
+                region_scope: Node(2)
+                lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[fcf8]::main).2))
                 value:
                     Expr {
                         ty: ()
                         temp_lifetime: Some(Node(2))
                         span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
                         kind: 
-                            Scope {
-                                region_scope: Node(2)
-                                lint_level: Explicit(HirId(DefId(0:17 ~ thir_tree_match[fcf8]::main).2))
-                                value:
-                                    Expr {
-                                        ty: ()
-                                        temp_lifetime: Some(Node(2))
-                                        span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
-                                        kind: 
-                                            Block {
-                                                targeted_by_break: false
-                                                opt_destruction_scope: None
-                                                span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
-                                                region_scope: Node(1)
-                                                safety_mode: Safe
-                                                stmts: []
-                                                expr: []
-                                            }
-                                    }
+                            Block {
+                                targeted_by_break: false
+                                span: $DIR/thir-tree-match.rs:23:11: 23:13 (#0)
+                                region_scope: Node(1)
+                                safety_mode: Safe
+                                stmts: []
+                                expr: []
                             }
                     }
             }
diff --git a/tests/ui/thir-print/thir-tree.stdout b/tests/ui/thir-print/thir-tree.stdout
index 1b478dbef99..ef6db368dbe 100644
--- a/tests/ui/thir-print/thir-tree.stdout
+++ b/tests/ui/thir-print/thir-tree.stdout
@@ -8,33 +8,21 @@ body:
         span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
         kind: 
             Scope {
-                region_scope: Destruction(2)
-                lint_level: Inherited
+                region_scope: Node(2)
+                lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[7aaa]::main).2))
                 value:
                     Expr {
                         ty: ()
                         temp_lifetime: Some(Node(2))
                         span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
                         kind: 
-                            Scope {
-                                region_scope: Node(2)
-                                lint_level: Explicit(HirId(DefId(0:3 ~ thir_tree[7aaa]::main).2))
-                                value:
-                                    Expr {
-                                        ty: ()
-                                        temp_lifetime: Some(Node(2))
-                                        span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
-                                        kind: 
-                                            Block {
-                                                targeted_by_break: false
-                                                opt_destruction_scope: None
-                                                span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
-                                                region_scope: Node(1)
-                                                safety_mode: Safe
-                                                stmts: []
-                                                expr: []
-                                            }
-                                    }
+                            Block {
+                                targeted_by_break: false
+                                span: $DIR/thir-tree.rs:4:15: 4:17 (#0)
+                                region_scope: Node(1)
+                                safety_mode: Safe
+                                stmts: []
+                                expr: []
                             }
                     }
             }
diff --git a/tests/ui/traits/impl-method-mismatch.stderr b/tests/ui/traits/impl-method-mismatch.stderr
index 2655d465f23..2061fc78575 100644
--- a/tests/ui/traits/impl-method-mismatch.stderr
+++ b/tests/ui/traits/impl-method-mismatch.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     fn jumbo(&self, x: &usize) -> usize;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected signature `fn(&usize, &usize) -> usize`
-              found signature `unsafe fn(&usize, &usize)`
+   = note: expected signature `fn(&_, &_) -> usize`
+              found signature `unsafe fn(&_, &_)`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.rs b/tests/ui/traits/new-solver/alias-bound-unsound.rs
index 825e874d71b..907a3010355 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.rs
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.rs
@@ -23,7 +23,7 @@ fn main() {
     let x = String::from("hello, world");
     drop(<() as Foo>::copy_me(&x));
     //~^ ERROR overflow evaluating the requirement `<() as Foo>::Item: Sized`
-    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item == _`
+    //~| ERROR overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
     //~| ERROR overflow evaluating the requirement `<() as Foo>::Item well-formed`
     //~| ERROR overflow evaluating the requirement `String <: <() as Foo>::Item`
     //~| ERROR overflow evaluating the requirement `&<() as Foo>::Item well-formed`
diff --git a/tests/ui/traits/new-solver/alias-bound-unsound.stderr b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
index ca4b5c90ff2..29d4d983c03 100644
--- a/tests/ui/traits/new-solver/alias-bound-unsound.stderr
+++ b/tests/ui/traits/new-solver/alias-bound-unsound.stderr
@@ -19,7 +19,7 @@ LL |     drop(<() as Foo>::copy_me(&x));
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`alias_bound_unsound`)
 
-error[E0275]: overflow evaluating the requirement `<() as Foo>::Item == _`
+error[E0275]: overflow evaluating the requirement `<() as Foo>::Item normalizes-to _`
   --> $DIR/alias-bound-unsound.rs:24:10
    |
 LL |     drop(<() as Foo>::copy_me(&x));
diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
index 44e763ef990..07c7d4fb29c 100644
--- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.rs
@@ -3,8 +3,12 @@
 // Proving `W<?0>: Trait` instantiates `?0` with `(W<?1>, W<?2>)` and then
 // proves `W<?1>: Trait` and `W<?2>: Trait`, resulting in a coinductive cycle.
 //
-// Proving coinductive cycles runs until we reach a fixpoint. This fixpoint is
-// never reached here and each step doubles the amount of nested obligations.
+// Proving coinductive cycles runs until we reach a fixpoint. However, after
+// computing `try_evaluate_added_goals` in the second fixpoint iteration, the
+// self type already has a depth equal to the number of steps. This results
+// in enormous constraints, causing the canonicalizer to hang without ever
+// reaching the recursion limit. We currently avoid that by erasing the constraints
+// from overflow.
 //
 // This previously caused a hang in the trait solver, see
 // https://github.com/rust-lang/trait-system-refactor-initiative/issues/13.
diff --git a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
index 05aaf6108f1..150100f2c53 100644
--- a/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
+++ b/tests/ui/traits/new-solver/cycles/coinduction/fixpoint-exponential-growth.stderr
@@ -1,12 +1,12 @@
 error[E0275]: overflow evaluating the requirement `W<_>: Trait`
-  --> $DIR/fixpoint-exponential-growth.rs:29:13
+  --> $DIR/fixpoint-exponential-growth.rs:33:13
    |
 LL |     impls::<W<_>>();
    |             ^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`fixpoint_exponential_growth`)
 note: required by a bound in `impls`
-  --> $DIR/fixpoint-exponential-growth.rs:26:13
+  --> $DIR/fixpoint-exponential-growth.rs:30:13
    |
 LL | fn impls<T: Trait>() {}
    |             ^^^^^ required by this bound in `impls`
diff --git a/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs
new file mode 100644
index 00000000000..062c6ae98d5
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.rs
@@ -0,0 +1,33 @@
+// compile-flags: -Ztrait-solver=next
+
+// This currently hangs if we do not erase constraints from
+// overflow.
+//
+// We set the provisional result of `W<?0>` to `?0 := W<_>`.
+// The next iteration does not simply result in a `?0 := W<W<_>` constraint as
+// one might expect, but instead each time we evaluate the nested `W<T>` goal we
+// apply the previously returned constraints: the first fixpoint iteration goes
+// as follows: `W<?1>: Trait` constrains `?1` to `W<?2>`, we then evaluate
+// `W<W<?2>>: Trait` the next time we try to prove the nested goal. This results
+// inn `W<W<W<?3>>>` and so on. This goes on until we reach overflow in
+// `try_evaluate_added_goals`.  This means the provisional result after the
+// second fixpoint iteration is already `W<W<W<...>>>` with a size proportional
+// to the number of steps in `try_evaluate_added_goals`. The size then continues
+// to grow. The exponential blowup from having 2 nested goals per impl causes
+// the solver to hang without hitting the recursion limit.
+trait Trait {}
+
+struct W<T: ?Sized>(*const T);
+
+impl<T: ?Sized> Trait for W<W<T>>
+where
+    W<T>: Trait,
+    W<T>: Trait,
+{}
+
+fn impls_trait<T: Trait>() {}
+
+fn main() {
+    impls_trait::<W<_>>();
+    //~^ ERROR overflow evaluating the requirement
+}
diff --git a/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr
new file mode 100644
index 00000000000..42451920744
--- /dev/null
+++ b/tests/ui/traits/new-solver/cycles/inductive-fixpoint-hang.stderr
@@ -0,0 +1,16 @@
+error[E0275]: overflow evaluating the requirement `W<_>: Trait`
+  --> $DIR/inductive-fixpoint-hang.rs:31:19
+   |
+LL |     impls_trait::<W<_>>();
+   |                   ^^^^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inductive_fixpoint_hang`)
+note: required by a bound in `impls_trait`
+  --> $DIR/inductive-fixpoint-hang.rs:28:19
+   |
+LL | fn impls_trait<T: Trait>() {}
+   |                   ^^^^^ required by this bound in `impls_trait`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
index 94d645a9859..7fe242f4714 100644
--- a/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
+++ b/tests/ui/traits/new-solver/generalize/generalize-proj-new-universe-index-2.rs
@@ -1,5 +1,7 @@
 // compile-flags: -Ztrait-solver=next
 // known-bug: trait-system-refactor-initiative#60
+// dont-check-failure-status
+// dont-check-compiler-stderr
 
 // Generalizing a projection containing an inference variable
 // which cannot be named by the `root_vid` can result in ambiguity.
diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr
index 34c2f0438c7..ad8b24a39c7 100644
--- a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr
+++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.next.stderr
@@ -1,9 +1,11 @@
-error[E0271]: type mismatch resolving `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
-  --> $DIR/occurs-check-nested-alias.rs:35:9
+error[E0275]: overflow evaluating the requirement `<<T as Id<_>>::Id as Unnormalizable>::Assoc == _`
+  --> $DIR/occurs-check-nested-alias.rs:36:9
    |
 LL |     x = y;
-   |         ^ types differ
+   |         ^
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`occurs_check_nested_alias`)
 
 error: aborting due to 1 previous error
 
-For more information about this error, try `rustc --explain E0271`.
+For more information about this error, try `rustc --explain E0275`.
diff --git a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs
index a2113b2a8b3..02ac091c0a8 100644
--- a/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs
+++ b/tests/ui/traits/new-solver/generalize/occurs-check-nested-alias.rs
@@ -1,7 +1,8 @@
 // revisions: old next
 //[old] check-pass
 
-// Need to emit an alias-relate instead of a `Projection` goal here.
+// Currently always fails to generalize the outer alias, even if it
+// is treated as rigid by `alias-relate`.
 //[next] compile-flags: -Ztrait-solver=next
 //[next] known-bug: trait-system-refactor-initiative#8
 #![crate_type = "lib"]
diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs
new file mode 100644
index 00000000000..e36d574efe2
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-1.rs
@@ -0,0 +1,14 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1
+// a minimization of a pattern in core.
+fn next<T: Iterator<Item = U>, U>(t: &mut T) -> Option<U> {
+    t.next()
+}
+
+fn foo<T: Iterator>(t: &mut T) {
+    let _: Option<T::Item> = next(t);
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs
new file mode 100644
index 00000000000..c8050997a1d
--- /dev/null
+++ b/tests/ui/traits/new-solver/projection/param-env-trait-candidate-2.rs
@@ -0,0 +1,29 @@
+// check-pass
+// compile-flags: -Ztrait-solver=next
+
+// See https://github.com/rust-lang/trait-system-refactor-initiative/issues/1,
+// a minimization of a pattern in core.
+
+trait Iterator {
+    type Item;
+}
+
+struct Flatten<I>(I);
+
+impl<I, U> Iterator for Flatten<I>
+where
+    I: Iterator<Item = U>,
+{
+    type Item = U;
+}
+
+fn needs_iterator<I: Iterator>() {}
+
+fn environment<J>()
+where
+    J: Iterator,
+{
+    needs_iterator::<Flatten<J>>();
+}
+
+fn main() {}
diff --git a/tests/ui/traits/new-solver/specialization-transmute.stderr b/tests/ui/traits/new-solver/specialization-transmute.stderr
index 18965a465b3..eaf32a475ac 100644
--- a/tests/ui/traits/new-solver/specialization-transmute.stderr
+++ b/tests/ui/traits/new-solver/specialization-transmute.stderr
@@ -8,13 +8,11 @@ LL | #![feature(specialization)]
    = help: consider using `min_specialization` instead, which is more stable and complete
    = note: `#[warn(incomplete_features)]` on by default
 
-error[E0284]: type annotations needed
+error[E0284]: type annotations needed: cannot satisfy `<T as Default>::Id normalizes-to _`
   --> $DIR/specialization-transmute.rs:15:23
    |
 LL |     fn intu(&self) -> &Self::Id {
-   |                       ^^^^^^^^^ cannot infer type
-   |
-   = note: cannot satisfy `<T as Default>::Id == _`
+   |                       ^^^^^^^^^ cannot satisfy `<T as Default>::Id normalizes-to _`
 
 error[E0282]: type annotations needed
   --> $DIR/specialization-transmute.rs:13:23
diff --git a/tests/ui/traits/wrong-mul-method-signature.stderr b/tests/ui/traits/wrong-mul-method-signature.stderr
index 25a92f5ec12..91162cbc123 100644
--- a/tests/ui/traits/wrong-mul-method-signature.stderr
+++ b/tests/ui/traits/wrong-mul-method-signature.stderr
@@ -7,8 +7,8 @@ LL |     fn mul(self, s: &f64) -> Vec1 {
    |                     expected `f64`, found `&f64`
    |                     help: change the parameter type to match the trait: `f64`
    |
-   = note: expected signature `fn(Vec1, f64) -> Vec1`
-              found signature `fn(Vec1, &f64) -> Vec1`
+   = note: expected signature `fn(Vec1, _) -> Vec1`
+              found signature `fn(Vec1, &_) -> Vec1`
 
 error[E0053]: method `mul` has an incompatible type for trait
   --> $DIR/wrong-mul-method-signature.rs:33:21
diff --git a/tests/ui/type/type-check/point-at-inference-2.stderr b/tests/ui/type/type-check/point-at-inference-2.stderr
index 1d2777ad69a..8b559ffff7e 100644
--- a/tests/ui/type/type-check/point-at-inference-2.stderr
+++ b/tests/ui/type/type-check/point-at-inference-2.stderr
@@ -25,8 +25,8 @@ LL |     bar(v);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected struct `Vec<i32>`
-              found struct `Vec<&i32>`
+   = note: expected struct `Vec<_>`
+              found struct `Vec<&_>`
 note: function defined here
   --> $DIR/point-at-inference-2.rs:1:4
    |
@@ -43,8 +43,8 @@ LL |     bar(v);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected struct `Vec<i32>`
-              found struct `Vec<&i32>`
+   = note: expected struct `Vec<_>`
+              found struct `Vec<&_>`
 note: function defined here
   --> $DIR/point-at-inference-2.rs:1:4
    |
diff --git a/tests/ui/type/type-mismatch.stderr b/tests/ui/type/type-mismatch.stderr
index ce6f29d354f..aca96978ac9 100644
--- a/tests/ui/type/type-mismatch.stderr
+++ b/tests/ui/type/type-mismatch.stderr
@@ -382,8 +382,8 @@ LL |     want::<&Foo<foo>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo>`
-                 found struct `Foo<foo>`
+   = note: expected reference `&Foo<_>`
+                 found struct `Foo<_>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
@@ -402,8 +402,8 @@ LL |     want::<&Foo<foo, B>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo, B>`
-                 found struct `Foo<foo>`
+   = note: expected reference `&Foo<_, B>`
+                 found struct `Foo<_, A>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
@@ -546,8 +546,8 @@ LL |     want::<&Foo<foo>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo>`
-                 found struct `Foo<foo, B>`
+   = note: expected reference `&Foo<_, A>`
+                 found struct `Foo<_, B>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
@@ -562,8 +562,8 @@ LL |     want::<&Foo<foo, B>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo, B>`
-                 found struct `Foo<foo, B>`
+   = note: expected reference `&Foo<_, _>`
+                 found struct `Foo<_, _>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
@@ -726,8 +726,8 @@ LL |     want::<&Foo<foo>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo>`
-                 found struct `Foo<foo, B, A>`
+   = note: expected reference `&Foo<_, A, B>`
+                 found struct `Foo<_, B, A>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
@@ -742,8 +742,8 @@ LL |     want::<&Foo<foo, B>>(f);
    |     |
    |     arguments to this function are incorrect
    |
-   = note: expected reference `&Foo<foo, B>`
-                 found struct `Foo<foo, B, A>`
+   = note: expected reference `&Foo<_, _, B>`
+                 found struct `Foo<_, _, A>`
 note: function defined here
   --> $DIR/type-mismatch.rs:14:4
    |
diff --git a/tests/ui/typeck/bad-index-due-to-nested.stderr b/tests/ui/typeck/bad-index-due-to-nested.stderr
index 0b705d467ff..bd7fd0392c3 100644
--- a/tests/ui/typeck/bad-index-due-to-nested.stderr
+++ b/tests/ui/typeck/bad-index-due-to-nested.stderr
@@ -44,8 +44,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
 LL |     map[k]
    |         ^ expected `&K`, found type parameter `K`
    |
-   = note:   expected reference `&K`
-           found type parameter `K`
+   = note:   expected reference `&_`
+           found type parameter `_`
 help: consider borrowing here
    |
 LL |     map[&k]
@@ -59,8 +59,8 @@ LL | fn index<'a, K, V>(map: &'a HashMap<K, V>, k: K) -> &'a V {
 LL |     map[k]
    |     ^^^^^^ expected `&V`, found type parameter `V`
    |
-   = note:   expected reference `&'a V`
-           found type parameter `V`
+   = note:   expected reference `&'a _`
+           found type parameter `_`
 help: consider borrowing here
    |
 LL |     &map[k]
diff --git a/tests/ui/typeck/mismatched-map-under-self.stderr b/tests/ui/typeck/mismatched-map-under-self.stderr
index 41391720a28..13678b4b827 100644
--- a/tests/ui/typeck/mismatched-map-under-self.stderr
+++ b/tests/ui/typeck/mismatched-map-under-self.stderr
@@ -12,8 +12,8 @@ note: type in trait
    |
 LL |     fn values(&self) -> Self::Values;
    |               ^^^^^
-   = note: expected signature `fn(&Option<T>)`
-              found signature `fn(Option<T>)`
+   = note: expected signature `fn(&Option<_>)`
+              found signature `fn(Option<_>)`
 
 error[E0631]: type mismatch in function arguments
   --> $DIR/mismatched-map-under-self.rs:12:18
diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.rs b/tests/ui/ufcs/ufcs-explicit-self-bad.rs
index 9b0f99a189a..3bb3d906d11 100644
--- a/tests/ui/ufcs/ufcs-explicit-self-bad.rs
+++ b/tests/ui/ufcs/ufcs-explicit-self-bad.rs
@@ -39,12 +39,12 @@ impl<'a, T> SomeTrait for &'a Bar<T> {
     //~| ERROR has an incompatible type for trait
     fn dummy3(self: &&Bar<T>) {}
     //~^ ERROR mismatched `self` parameter type
-    //~| expected reference `&'a Bar<T>`
-    //~| found reference `&Bar<T>`
+    //~| expected reference `&'a Bar<_>`
+    //~| found reference `&Bar<_>`
     //~| lifetime mismatch
     //~| ERROR mismatched `self` parameter type
-    //~| expected reference `&'a Bar<T>`
-    //~| found reference `&Bar<T>`
+    //~| expected reference `&'a Bar<_>`
+    //~| found reference `&Bar<_>`
     //~| lifetime mismatch
 }
 
diff --git a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
index 0efaa41d48a..4c2cb0eb753 100644
--- a/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
+++ b/tests/ui/ufcs/ufcs-explicit-self-bad.stderr
@@ -31,8 +31,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn dummy2(self: &Bar<T>) {}
    |                     ^^^^^^^ lifetime mismatch
    |
-   = note: expected reference `&'a Bar<T>`
-              found reference `&Bar<T>`
+   = note: expected reference `&'a Bar<_>`
+              found reference `&Bar<_>`
 note: the anonymous lifetime defined here...
   --> $DIR/ufcs-explicit-self-bad.rs:37:21
    |
@@ -50,8 +50,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn dummy2(self: &Bar<T>) {}
    |                     ^^^^^^^ lifetime mismatch
    |
-   = note: expected reference `&'a Bar<T>`
-              found reference `&Bar<T>`
+   = note: expected reference `&'a Bar<_>`
+              found reference `&Bar<_>`
 note: the lifetime `'a` as defined here...
   --> $DIR/ufcs-explicit-self-bad.rs:35:6
    |
@@ -69,8 +69,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn dummy3(self: &&Bar<T>) {}
    |                     ^^^^^^^^ lifetime mismatch
    |
-   = note: expected reference `&'a Bar<T>`
-              found reference `&Bar<T>`
+   = note: expected reference `&'a Bar<_>`
+              found reference `&Bar<_>`
 note: the anonymous lifetime defined here...
   --> $DIR/ufcs-explicit-self-bad.rs:40:22
    |
@@ -88,8 +88,8 @@ error[E0308]: mismatched `self` parameter type
 LL |     fn dummy3(self: &&Bar<T>) {}
    |                     ^^^^^^^^ lifetime mismatch
    |
-   = note: expected reference `&'a Bar<T>`
-              found reference `&Bar<T>`
+   = note: expected reference `&'a Bar<_>`
+              found reference `&Bar<_>`
 note: the lifetime `'a` as defined here...
   --> $DIR/ufcs-explicit-self-bad.rs:35:6
    |
@@ -115,8 +115,8 @@ note: type in trait
    |
 LL |     fn dummy2(&self);
    |               ^^^^^
-   = note: expected signature `fn(&&'a Bar<T>)`
-              found signature `fn(&Bar<T>)`
+   = note: expected signature `fn(&&'a Bar<_>)`
+              found signature `fn(&Bar<_>)`
 
 error: aborting due to 8 previous errors
 
diff --git a/tests/ui/uninhabited/uninhabited-patterns.rs b/tests/ui/uninhabited/uninhabited-patterns.rs
index f1573b6adf0..4e90691e5c8 100644
--- a/tests/ui/uninhabited/uninhabited-patterns.rs
+++ b/tests/ui/uninhabited/uninhabited-patterns.rs
@@ -1,8 +1,6 @@
 #![feature(box_patterns)]
 #![feature(never_type)]
 #![feature(exhaustive_patterns)]
-
-
 #![deny(unreachable_patterns)]
 
 mod foo {
@@ -23,22 +21,22 @@ fn main() {
     let x: &[!] = &[];
 
     match x {
-        &[]   => (),
-        &[..] => (),    //~ ERROR unreachable pattern
+        &[] => (),
+        &[..] => (),
     };
 
     let x: Result<Box<NotSoSecretlyEmpty>, &[Result<!, !>]> = Err(&[]);
     match x {
-        Ok(box _) => (),    //~ ERROR unreachable pattern
+        Ok(box _) => (), //~ ERROR unreachable pattern
         Err(&[]) => (),
-        Err(&[..]) => (),   //~ ERROR unreachable pattern
+        Err(&[..]) => (),
     }
 
     let x: Result<foo::SecretlyEmpty, Result<NotSoSecretlyEmpty, u32>> = Err(Err(123));
     match x {
         Ok(_y) => (),
         Err(Err(_y)) => (),
-        Err(Ok(_y)) => (),  //~ ERROR unreachable pattern
+        Err(Ok(_y)) => (), //~ ERROR unreachable pattern
     }
 
     while let Some(_y) = foo() {
diff --git a/tests/ui/uninhabited/uninhabited-patterns.stderr b/tests/ui/uninhabited/uninhabited-patterns.stderr
index 655569ad6e0..a6fda88f032 100644
--- a/tests/ui/uninhabited/uninhabited-patterns.stderr
+++ b/tests/ui/uninhabited/uninhabited-patterns.stderr
@@ -1,38 +1,26 @@
 error: unreachable pattern
-  --> $DIR/uninhabited-patterns.rs:27:9
+  --> $DIR/uninhabited-patterns.rs:30:9
    |
-LL |         &[..] => (),
-   |         ^^^^^
+LL |         Ok(box _) => (),
+   |         ^^^^^^^^^
    |
 note: the lint level is defined here
-  --> $DIR/uninhabited-patterns.rs:6:9
+  --> $DIR/uninhabited-patterns.rs:4:9
    |
 LL | #![deny(unreachable_patterns)]
    |         ^^^^^^^^^^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/uninhabited-patterns.rs:32:9
-   |
-LL |         Ok(box _) => (),
-   |         ^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/uninhabited-patterns.rs:34:9
-   |
-LL |         Err(&[..]) => (),
-   |         ^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/uninhabited-patterns.rs:41:9
+  --> $DIR/uninhabited-patterns.rs:39:9
    |
 LL |         Err(Ok(_y)) => (),
    |         ^^^^^^^^^^^
 
 error: unreachable pattern
-  --> $DIR/uninhabited-patterns.rs:44:15
+  --> $DIR/uninhabited-patterns.rs:42:15
    |
 LL |     while let Some(_y) = foo() {
    |               ^^^^^^^^
 
-error: aborting due to 5 previous errors
+error: aborting due to 3 previous errors
 
diff --git a/tests/ui/unsafe/unsafe-trait-impl.rs b/tests/ui/unsafe/unsafe-trait-impl.rs
index 1fc84ca0256..9fd9ff65288 100644
--- a/tests/ui/unsafe/unsafe-trait-impl.rs
+++ b/tests/ui/unsafe/unsafe-trait-impl.rs
@@ -7,8 +7,8 @@ trait Foo {
 impl Foo for u32 {
     fn len(&self) -> u32 { *self }
     //~^ ERROR method `len` has an incompatible type for trait
-    //~| expected signature `unsafe fn(&u32) -> _`
-    //~| found signature `fn(&u32) -> _`
+    //~| expected signature `unsafe fn(&_) -> _`
+    //~| found signature `fn(&_) -> _`
 }
 
 fn main() { }
diff --git a/tests/ui/unsafe/unsafe-trait-impl.stderr b/tests/ui/unsafe/unsafe-trait-impl.stderr
index db5200e1c20..5888b674d4f 100644
--- a/tests/ui/unsafe/unsafe-trait-impl.stderr
+++ b/tests/ui/unsafe/unsafe-trait-impl.stderr
@@ -9,8 +9,8 @@ note: type in trait
    |
 LL |     unsafe fn len(&self) -> u32;
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
-   = note: expected signature `unsafe fn(&u32) -> _`
-              found signature `fn(&u32) -> _`
+   = note: expected signature `unsafe fn(&_) -> _`
+              found signature `fn(&_) -> _`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/wf/unnormalized-projection-guides-inference.rs b/tests/ui/wf/unnormalized-projection-guides-inference.rs
new file mode 100644
index 00000000000..ca2d6c2e882
--- /dev/null
+++ b/tests/ui/wf/unnormalized-projection-guides-inference.rs
@@ -0,0 +1,24 @@
+// The WF requirements of the *unnormalized* form of type annotations
+// can guide inference.
+// check-pass
+
+pub trait EqualTo {
+    type Ty;
+}
+impl<X> EqualTo for X {
+    type Ty = X;
+}
+
+trait MyTrait<U: EqualTo<Ty = Self>> {
+    type Out;
+}
+impl<T, U: EqualTo<Ty = T>> MyTrait<U> for T {
+    type Out = ();
+}
+
+fn main() {
+    let _: <_ as MyTrait<u8>>::Out;
+    // We shoud be able to infer a value for the inference variable above.
+    // The WF of the unnormalized projection requires `u8: EqualTo<Ty = _>`,
+    // which is sufficient to guide inference.
+}