about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2025-08-08 20:53:33 +0000
committerbors <bors@rust-lang.org>2025-08-08 20:53:33 +0000
commitffb9d94dcf4ade0d534842be3672d5e9f47e1333 (patch)
treefae25695be80c3e9e2f78b7e084763d52fe0462a
parentde3efa79f95852c7427587f1d535bfea7c0d6779 (diff)
parent660bf919dc5dec96d319cce59702b0355bd8452c (diff)
downloadrust-ffb9d94dcf4ade0d534842be3672d5e9f47e1333.tar.gz
rust-ffb9d94dcf4ade0d534842be3672d5e9f47e1333.zip
Auto merge of #145126 - tgross35:rollup-6w87usd, r=tgross35
Rollup of 8 pull requests

Successful merges:

 - rust-lang/rust#139451 (Add `target_env = "macabi"` and `target_env = "sim"`)
 - rust-lang/rust#144039 (Use `tcx.short_string()` in more diagnostics)
 - rust-lang/rust#144192 (atomicrmw on pointers: move integer-pointer cast hacks into backend)
 - rust-lang/rust#144545 (In rustc_pattern_analysis, put `true` witnesses before `false` witnesses)
 - rust-lang/rust#144579 (Implement declarative (`macro_rules!`) attribute macros (RFC 3697))
 - rust-lang/rust#144649 (Account for bare tuples and `Pin` methods in field searching logic)
 - rust-lang/rust#144775 (more strongly dissuade use of `skip_binder`)
 - rust-lang/rust#144987 (Enable f16 and f128 on targets that were fixed in LLVM21)

r? `@ghost`
`@rustbot` modify labels: rollup
-rw-r--r--compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs24
-rw-r--r--compiler/rustc_codegen_gcc/src/builder.rs7
-rw-r--r--compiler/rustc_codegen_llvm/src/builder.rs14
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm_util.rs24
-rw-r--r--compiler/rustc_codegen_ssa/messages.ftl2
-rw-r--r--compiler/rustc_codegen_ssa/src/back/apple.rs4
-rw-r--r--compiler/rustc_codegen_ssa/src/back/link.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/errors.rs8
-rw-r--r--compiler/rustc_codegen_ssa/src/mir/intrinsic.rs82
-rw-r--r--compiler/rustc_codegen_ssa/src/traits/builder.rs3
-rw-r--r--compiler/rustc_errors/src/diagnostic.rs5
-rw-r--r--compiler/rustc_errors/src/emitter.rs2
-rw-r--r--compiler/rustc_expand/messages.ftl3
-rw-r--r--compiler/rustc_expand/src/errors.rs18
-rw-r--r--compiler/rustc_expand/src/mbe/diagnostics.rs55
-rw-r--r--compiler/rustc_expand/src/mbe/macro_check.rs6
-rw-r--r--compiler/rustc_expand/src/mbe/macro_rules.rs264
-rw-r--r--compiler/rustc_feature/src/unstable.rs2
-rw-r--r--compiler/rustc_hir_analysis/src/check/intrinsic.rs12
-rw-r--r--compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs5
-rw-r--r--compiler/rustc_hir_typeck/messages.ftl4
-rw-r--r--compiler/rustc_hir_typeck/src/errors.rs8
-rw-r--r--compiler/rustc_hir_typeck/src/expr.rs99
-rw-r--r--compiler/rustc_hir_typeck/src/method/suggest.rs139
-rw-r--r--compiler/rustc_metadata/src/native_libs.rs2
-rw-r--r--compiler/rustc_middle/src/ty/generic_args.rs17
-rw-r--r--compiler/rustc_middle/src/ty/print/pretty.rs2
-rw-r--r--compiler/rustc_pattern_analysis/src/constructor.rs10
-rw-r--r--compiler/rustc_pattern_analysis/tests/exhaustiveness.rs3
-rw-r--r--compiler/rustc_resolve/messages.ftl2
-rw-r--r--compiler/rustc_resolve/src/ident.rs20
-rw-r--r--compiler/rustc_resolve/src/lib.rs3
-rw-r--r--compiler/rustc_resolve/src/macros.rs10
-rw-r--r--compiler/rustc_span/src/symbol.rs1
-rw-r--r--compiler/rustc_target/src/spec/base/apple/mod.rs43
-rw-r--r--compiler/rustc_target/src/spec/base/apple/tests.rs6
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i386_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs4
-rw-r--r--compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs4
-rw-r--r--compiler/rustc_trait_selection/messages.ftl2
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs15
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs32
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs57
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs119
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs4
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs67
-rw-r--r--compiler/rustc_trait_selection/src/errors.rs11
-rw-r--r--compiler/rustc_type_ir/src/binder.rs60
-rw-r--r--library/core/src/intrinsics/mod.rs30
-rw-r--r--library/core/src/sync/atomic.rs89
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios-macabi.md11
-rw-r--r--src/doc/rustc/src/platform-support/apple-ios.md14
-rw-r--r--src/tools/compiletest/src/directives/tests.rs7
-rw-r--r--src/tools/miri/src/intrinsics/atomic.rs19
-rw-r--r--src/tools/miri/src/operator.rs8
-rw-r--r--src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr2
-rw-r--r--tests/codegen-llvm/atomicptr.rs6
-rw-r--r--tests/run-make/atomic-lock-free/atomic_lock_free.rs39
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr4
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr4
-rw-r--r--tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr2
-rw-r--r--tests/ui/allocator/not-an-allocator.stderr8
-rw-r--r--tests/ui/allocator/two-allocators.stderr2
-rw-r--r--tests/ui/attributes/rustc_confusables_std_cases.stderr6
-rw-r--r--tests/ui/check-cfg/well-known-values.stderr2
-rw-r--r--tests/ui/codegen/overflow-during-mono.rs3
-rw-r--r--tests/ui/codegen/overflow-during-mono.stderr10
-rw-r--r--tests/ui/coherence/coherence-tuple-conflict.stderr2
-rw-r--r--tests/ui/confuse-field-and-method/issue-18343.stderr2
-rw-r--r--tests/ui/confuse-field-and-method/issue-2392.stderr12
-rw-r--r--tests/ui/consts/issue-19244-1.stderr2
-rw-r--r--tests/ui/custom_test_frameworks/mismatch.stderr2
-rw-r--r--tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr2
-rw-r--r--tests/ui/diagnostic-width/long-E0609.stderr1
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs1
-rw-r--r--tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr6
-rw-r--r--tests/ui/editions/never-type-fallback-breaking.e2024.stderr8
-rw-r--r--tests/ui/error-codes/E0275.rs1
-rw-r--r--tests/ui/error-codes/E0275.stderr8
-rw-r--r--tests/ui/error-codes/ex-E0612.stderr6
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-attr.rs4
-rw-r--r--tests/ui/feature-gates/feature-gate-macro-attr.stderr13
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs2
-rw-r--r--tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr16
-rw-r--r--tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs1
-rw-r--r--tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr16
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs1
-rw-r--r--tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr6
-rw-r--r--tests/ui/interior-mutability/interior-mutability.rs1
-rw-r--r--tests/ui/interior-mutability/interior-mutability.stderr4
-rw-r--r--tests/ui/intrinsics/intrinsic-atomics.rs12
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.rs32
-rw-r--r--tests/ui/intrinsics/non-integer-atomic.stderr32
-rw-r--r--tests/ui/issues/issue-41880.stderr2
-rw-r--r--tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr2
-rw-r--r--tests/ui/macros/macro-rules-attr-error.rs15
-rw-r--r--tests/ui/macros/macro-rules-attr-error.stderr22
-rw-r--r--tests/ui/macros/macro-rules-attr-infinite-recursion.rs12
-rw-r--r--tests/ui/macros/macro-rules-attr-infinite-recursion.stderr14
-rw-r--r--tests/ui/macros/macro-rules-attr-nested.rs24
-rw-r--r--tests/ui/macros/macro-rules-attr-nested.run.stdout3
-rw-r--r--tests/ui/macros/macro-rules-attr.rs90
-rw-r--r--tests/ui/macros/macro-rules-attr.run.stdout15
-rw-r--r--tests/ui/macros/macro-rules-attr.stderr21
-rw-r--r--tests/ui/methods/call_method_unknown_referent.rs2
-rw-r--r--tests/ui/methods/call_method_unknown_referent.stderr2
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.rs1
-rw-r--r--tests/ui/methods/inherent-bound-in-probe.stderr12
-rw-r--r--tests/ui/methods/method-not-found-generic-arg-elision.stderr8
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.rs1
-rw-r--r--tests/ui/methods/probe-error-on-infinite-deref.stderr8
-rw-r--r--tests/ui/methods/untrimmed-path-type.stderr2
-rw-r--r--tests/ui/never_type/defaulted-never-note.fallback.stderr2
-rw-r--r--tests/ui/never_type/defaulted-never-note.rs2
-rw-r--r--tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr2
-rw-r--r--tests/ui/offset-of/offset-of-tuple-field.stderr36
-rw-r--r--tests/ui/parser/float-field.stderr6
-rw-r--r--tests/ui/parser/macro/macro-attr-bad.rs32
-rw-r--r--tests/ui/parser/macro/macro-attr-bad.stderr80
-rw-r--r--tests/ui/parser/macro/macro-attr-recovery.rs19
-rw-r--r--tests/ui/parser/macro/macro-attr-recovery.stderr31
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs2
-rw-r--r--tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr6
-rw-r--r--tests/ui/pattern/usefulness/unions.rs2
-rw-r--r--tests/ui/pattern/usefulness/unions.stderr4
-rw-r--r--tests/ui/proc-macro/span-from-proc-macro.stderr2
-rw-r--r--tests/ui/recursion/issue-23122-2.rs1
-rw-r--r--tests/ui/recursion/issue-23122-2.stderr8
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs1
-rw-r--r--tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr6
-rw-r--r--tests/ui/recursion/issue-83150.rs2
-rw-r--r--tests/ui/recursion/issue-83150.stderr6
-rw-r--r--tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr2
-rw-r--r--tests/ui/self/arbitrary_self_type_infinite_recursion.stderr2
-rw-r--r--tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr4
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs2
-rw-r--r--tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr2
-rw-r--r--tests/ui/simd/libm_no_std_cant_float.stderr12
-rw-r--r--tests/ui/structs/tuple-struct-field-naming-47073.stderr6
-rw-r--r--tests/ui/suggestions/enum-method-probe.fixed12
-rw-r--r--tests/ui/suggestions/enum-method-probe.rs12
-rw-r--r--tests/ui/suggestions/enum-method-probe.stderr12
-rw-r--r--tests/ui/suggestions/field-has-method.rs2
-rw-r--r--tests/ui/suggestions/field-has-method.stderr2
-rw-r--r--tests/ui/suggestions/inner_type.fixed10
-rw-r--r--tests/ui/suggestions/inner_type.rs10
-rw-r--r--tests/ui/suggestions/inner_type.stderr10
-rw-r--r--tests/ui/suggestions/inner_type2.rs4
-rw-r--r--tests/ui/suggestions/inner_type2.stderr4
-rw-r--r--tests/ui/test-attrs/issue-12997-2.stderr2
-rw-r--r--tests/ui/test-attrs/test-function-signature.stderr2
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.rs2
-rw-r--r--tests/ui/traits/issue-91949-hangs-on-recursion.stderr4
-rw-r--r--tests/ui/traits/well-formed-recursion-limit.stderr4
-rw-r--r--tests/ui/tuple/index-invalid.stderr6
-rw-r--r--tests/ui/tuple/missing-field-access.rs16
-rw-r--r--tests/ui/tuple/missing-field-access.stderr28
-rw-r--r--tests/ui/tuple/tuple-index-out-of-bounds.stderr8
179 files changed, 1734 insertions, 791 deletions
diff --git a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
index 4ff5773a06c..ed40901ac9b 100644
--- a/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
+++ b/compiler/rustc_codegen_cranelift/src/intrinsics/mod.rs
@@ -969,7 +969,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = amount.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -982,7 +982,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let old =
                 fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Add, ptr, amount);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_xsub => {
@@ -991,7 +991,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = amount.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1004,7 +1004,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
             let old =
                 fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Sub, ptr, amount);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_and => {
@@ -1013,7 +1013,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1025,7 +1025,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::And, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_or => {
@@ -1034,7 +1034,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1046,7 +1046,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Or, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_xor => {
@@ -1055,7 +1055,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1067,7 +1067,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Xor, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_nand => {
@@ -1076,7 +1076,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let layout = src.layout();
             match layout.ty.kind() {
-                ty::Uint(_) | ty::Int(_) | ty::RawPtr(..) => {}
+                ty::Uint(_) | ty::Int(_) => {}
                 _ => {
                     report_atomic_type_validation_error(fx, intrinsic, source_info.span, layout.ty);
                     return Ok(());
@@ -1088,7 +1088,7 @@ fn codegen_regular_intrinsic_call<'tcx>(
 
             let old = fx.bcx.ins().atomic_rmw(ty, MemFlags::trusted(), AtomicRmwOp::Nand, ptr, src);
 
-            let old = CValue::by_val(old, layout);
+            let old = CValue::by_val(old, ret.layout());
             ret.write_cvalue(fx, old);
         }
         sym::atomic_max => {
diff --git a/compiler/rustc_codegen_gcc/src/builder.rs b/compiler/rustc_codegen_gcc/src/builder.rs
index 34ade3d025f..f7a7a3f8c7e 100644
--- a/compiler/rustc_codegen_gcc/src/builder.rs
+++ b/compiler/rustc_codegen_gcc/src/builder.rs
@@ -1671,6 +1671,7 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         dst: RValue<'gcc>,
         src: RValue<'gcc>,
         order: AtomicOrdering,
+        ret_ptr: bool,
     ) -> RValue<'gcc> {
         let size = get_maybe_pointer_size(src);
         let name = match op {
@@ -1698,6 +1699,9 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let atomic_function = self.context.get_builtin_function(name);
         let order = self.context.new_rvalue_from_int(self.i32_type, order.to_gcc());
 
+        // FIXME: If `ret_ptr` is true and `src` is an integer, we should really tell GCC
+        // that this is a pointer operation that needs to preserve provenance -- but like LLVM,
+        // GCC does not currently seems to support that.
         let void_ptr_type = self.context.new_type::<*mut ()>();
         let volatile_void_ptr_type = void_ptr_type.make_volatile();
         let dst = self.context.new_cast(self.location, dst, volatile_void_ptr_type);
@@ -1705,7 +1709,8 @@ impl<'a, 'gcc, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'gcc, 'tcx> {
         let new_src_type = atomic_function.get_param(1).to_rvalue().get_type();
         let src = self.context.new_bitcast(self.location, src, new_src_type);
         let res = self.context.new_call(self.location, atomic_function, &[dst, src, order]);
-        self.context.new_cast(self.location, res, src.get_type())
+        let res_type = if ret_ptr { void_ptr_type } else { src.get_type() };
+        self.context.new_cast(self.location, res, res_type)
     }
 
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope) {
diff --git a/compiler/rustc_codegen_llvm/src/builder.rs b/compiler/rustc_codegen_llvm/src/builder.rs
index bd175e560c7..32cdef075e7 100644
--- a/compiler/rustc_codegen_llvm/src/builder.rs
+++ b/compiler/rustc_codegen_llvm/src/builder.rs
@@ -1327,15 +1327,13 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
         &mut self,
         op: rustc_codegen_ssa::common::AtomicRmwBinOp,
         dst: &'ll Value,
-        mut src: &'ll Value,
+        src: &'ll Value,
         order: rustc_middle::ty::AtomicOrdering,
+        ret_ptr: bool,
     ) -> &'ll Value {
-        // The only RMW operation that LLVM supports on pointers is compare-exchange.
-        let requires_cast_to_int = self.val_ty(src) == self.type_ptr()
-            && op != rustc_codegen_ssa::common::AtomicRmwBinOp::AtomicXchg;
-        if requires_cast_to_int {
-            src = self.ptrtoint(src, self.type_isize());
-        }
+        // FIXME: If `ret_ptr` is true and `src` is not a pointer, we *should* tell LLVM that the
+        // LHS is a pointer and the operation should be provenance-preserving, but LLVM does not
+        // currently support that (https://github.com/llvm/llvm-project/issues/120837).
         let mut res = unsafe {
             llvm::LLVMBuildAtomicRMW(
                 self.llbuilder,
@@ -1346,7 +1344,7 @@ impl<'a, 'll, 'tcx> BuilderMethods<'a, 'tcx> for Builder<'a, 'll, 'tcx> {
                 llvm::False, // SingleThreaded
             )
         };
-        if requires_cast_to_int {
+        if ret_ptr && self.val_ty(res) != self.type_ptr() {
             res = self.inttoptr(res, self.type_ptr());
         }
         res
diff --git a/compiler/rustc_codegen_llvm/src/llvm_util.rs b/compiler/rustc_codegen_llvm/src/llvm_util.rs
index 3b290e5a129..28d2100f478 100644
--- a/compiler/rustc_codegen_llvm/src/llvm_util.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm_util.rs
@@ -377,24 +377,25 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
     let target_abi = sess.target.options.abi.as_ref();
     let target_pointer_width = sess.target.pointer_width;
     let version = get_version();
+    let lt_20_1_1 = version < (20, 1, 1);
+    let lt_21_0_0 = version < (21, 0, 0);
 
     cfg.has_reliable_f16 = match (target_arch, target_os) {
-        // Selection failure <https://github.com/llvm/llvm-project/issues/50374>
-        ("s390x", _) => false,
-        // LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (now fixed)
+        // LLVM crash without neon <https://github.com/llvm/llvm-project/issues/129394> (fixed in llvm20)
         ("aarch64", _)
-            if !cfg.target_features.iter().any(|f| f.as_str() == "neon")
-                && version < (20, 1, 1) =>
+            if !cfg.target_features.iter().any(|f| f.as_str() == "neon") && lt_20_1_1 =>
         {
             false
         }
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
         ("arm64ec", _) => false,
+        // Selection failure <https://github.com/llvm/llvm-project/issues/50374> (fixed in llvm21)
+        ("s390x", _) if lt_21_0_0 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
         ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
         // Infinite recursion <https://github.com/llvm/llvm-project/issues/97981>
         ("csky", _) => false,
-        ("hexagon", _) => false,
+        ("hexagon", _) if lt_21_0_0 => false, // (fixed in llvm21)
         ("powerpc" | "powerpc64", _) => false,
         ("sparc" | "sparc64", _) => false,
         ("wasm32" | "wasm64", _) => false,
@@ -407,9 +408,10 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
     cfg.has_reliable_f128 = match (target_arch, target_os) {
         // Unsupported <https://github.com/llvm/llvm-project/issues/94434>
         ("arm64ec", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/96432>
-        ("mips64" | "mips64r6", _) => false,
-        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>
+        // Selection bug <https://github.com/llvm/llvm-project/issues/96432> (fixed in llvm20)
+        ("mips64" | "mips64r6", _) if lt_20_1_1 => false,
+        // Selection bug <https://github.com/llvm/llvm-project/issues/95471>. This issue is closed
+        // but basic math still does not work.
         ("nvptx64", _) => false,
         // Unsupported https://github.com/llvm/llvm-project/issues/121122
         ("amdgpu", _) => false,
@@ -419,8 +421,8 @@ fn update_target_reliable_float_cfg(sess: &Session, cfg: &mut TargetConfig) {
         // ABI unsupported  <https://github.com/llvm/llvm-project/issues/41838>
         ("sparc", _) => false,
         // Stack alignment bug <https://github.com/llvm/llvm-project/issues/77401>. NB: tests may
-        // not fail if our compiler-builtins is linked.
-        ("x86", _) => false,
+        // not fail if our compiler-builtins is linked. (fixed in llvm21)
+        ("x86", _) if lt_21_0_0 => false,
         // MinGW ABI bugs <https://gcc.gnu.org/bugzilla/show_bug.cgi?id=115054>
         ("x86_64", "windows") if target_env == "gnu" && target_abi != "llvm" => false,
         // There are no known problems on other platforms, so the only requirement is that symbols
diff --git a/compiler/rustc_codegen_ssa/messages.ftl b/compiler/rustc_codegen_ssa/messages.ftl
index a70d0011d16..36ad5ede7c2 100644
--- a/compiler/rustc_codegen_ssa/messages.ftl
+++ b/compiler/rustc_codegen_ssa/messages.ftl
@@ -101,6 +101,8 @@ codegen_ssa_invalid_monomorphization_basic_float_type = invalid monomorphization
 
 codegen_ssa_invalid_monomorphization_basic_integer_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer type, found `{$ty}`
 
+codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type = invalid monomorphization of `{$name}` intrinsic: expected basic integer or pointer type, found `{$ty}`
+
 codegen_ssa_invalid_monomorphization_cannot_return = invalid monomorphization of `{$name}` intrinsic: cannot return `{$ret_ty}`, expected `u{$expected_int_bits}` or `[u8; {$expected_bytes}]`
 
 codegen_ssa_invalid_monomorphization_cast_wide_pointer = invalid monomorphization of `{$name}` intrinsic: cannot cast wide pointer `{$ty}`
diff --git a/compiler/rustc_codegen_ssa/src/back/apple.rs b/compiler/rustc_codegen_ssa/src/back/apple.rs
index d242efaf4fd..2f68bad1695 100644
--- a/compiler/rustc_codegen_ssa/src/back/apple.rs
+++ b/compiler/rustc_codegen_ssa/src/back/apple.rs
@@ -17,7 +17,7 @@ mod tests;
 
 /// The canonical name of the desired SDK for a given target.
 pub(super) fn sdk_name(target: &Target) -> &'static str {
-    match (&*target.os, &*target.abi) {
+    match (&*target.os, &*target.env) {
         ("macos", "") => "MacOSX",
         ("ios", "") => "iPhoneOS",
         ("ios", "sim") => "iPhoneSimulator",
@@ -34,7 +34,7 @@ pub(super) fn sdk_name(target: &Target) -> &'static str {
 }
 
 pub(super) fn macho_platform(target: &Target) -> u32 {
-    match (&*target.os, &*target.abi) {
+    match (&*target.os, &*target.env) {
         ("macos", _) => object::macho::PLATFORM_MACOS,
         ("ios", "macabi") => object::macho::PLATFORM_MACCATALYST,
         ("ios", "sim") => object::macho::PLATFORM_IOSSIMULATOR,
diff --git a/compiler/rustc_codegen_ssa/src/back/link.rs b/compiler/rustc_codegen_ssa/src/back/link.rs
index b69fbf61185..6e21f54587f 100644
--- a/compiler/rustc_codegen_ssa/src/back/link.rs
+++ b/compiler/rustc_codegen_ssa/src/back/link.rs
@@ -3026,7 +3026,7 @@ pub(crate) fn are_upstream_rust_objects_already_included(sess: &Session) -> bool
 /// We need to communicate five things to the linker on Apple/Darwin targets:
 /// - The architecture.
 /// - The operating system (and that it's an Apple platform).
-/// - The environment / ABI.
+/// - The environment.
 /// - The deployment target.
 /// - The SDK version.
 fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavor) {
@@ -3040,7 +3040,7 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
     // `sess.target.arch` (`target_arch`) is not detailed enough.
     let llvm_arch = sess.target.llvm_target.split_once('-').expect("LLVM target must have arch").0;
     let target_os = &*sess.target.os;
-    let target_abi = &*sess.target.abi;
+    let target_env = &*sess.target.env;
 
     // The architecture name to forward to the linker.
     //
@@ -3091,14 +3091,14 @@ fn add_apple_link_args(cmd: &mut dyn Linker, sess: &Session, flavor: LinkerFlavo
         // > - visionos-simulator
         // > - xros-simulator
         // > - driverkit
-        let platform_name = match (target_os, target_abi) {
+        let platform_name = match (target_os, target_env) {
             (os, "") => os,
             ("ios", "macabi") => "mac-catalyst",
             ("ios", "sim") => "ios-simulator",
             ("tvos", "sim") => "tvos-simulator",
             ("watchos", "sim") => "watchos-simulator",
             ("visionos", "sim") => "visionos-simulator",
-            _ => bug!("invalid OS/ABI combination for Apple target: {target_os}, {target_abi}"),
+            _ => bug!("invalid OS/env combination for Apple target: {target_os}, {target_env}"),
         };
 
         let min_version = sess.apple_deployment_target().fmt_full().to_string();
diff --git a/compiler/rustc_codegen_ssa/src/errors.rs b/compiler/rustc_codegen_ssa/src/errors.rs
index 3d787d8bdbd..af4adcd1954 100644
--- a/compiler/rustc_codegen_ssa/src/errors.rs
+++ b/compiler/rustc_codegen_ssa/src/errors.rs
@@ -764,6 +764,14 @@ pub enum InvalidMonomorphization<'tcx> {
         ty: Ty<'tcx>,
     },
 
+    #[diag(codegen_ssa_invalid_monomorphization_basic_integer_or_ptr_type, code = E0511)]
+    BasicIntegerOrPtrType {
+        #[primary_span]
+        span: Span,
+        name: Symbol,
+        ty: Ty<'tcx>,
+    },
+
     #[diag(codegen_ssa_invalid_monomorphization_basic_float_type, code = E0511)]
     BasicFloatType {
         #[primary_span]
diff --git a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
index fc95f62b4a4..3c667b8e882 100644
--- a/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
+++ b/compiler/rustc_codegen_ssa/src/mir/intrinsic.rs
@@ -92,6 +92,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
         let invalid_monomorphization_int_type = |ty| {
             bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerType { span, name, ty });
         };
+        let invalid_monomorphization_int_or_ptr_type = |ty| {
+            bx.tcx().dcx().emit_err(InvalidMonomorphization::BasicIntegerOrPtrType {
+                span,
+                name,
+                ty,
+            });
+        };
 
         let parse_atomic_ordering = |ord: ty::Value<'tcx>| {
             let discr = ord.valtree.unwrap_branch()[0].unwrap_leaf();
@@ -351,7 +358,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::atomic_load => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let ordering = fn_args.const_at(1).to_value();
@@ -367,7 +374,7 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
             sym::atomic_store => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let ordering = fn_args.const_at(1).to_value();
@@ -377,10 +384,11 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                 bx.atomic_store(val, ptr, parse_atomic_ordering(ordering), size);
                 return Ok(());
             }
+            // These are all AtomicRMW ops
             sym::atomic_cxchg | sym::atomic_cxchgweak => {
                 let ty = fn_args.type_at(0);
                 if !(int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr()) {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty);
                     return Ok(());
                 }
                 let succ_ordering = fn_args.const_at(1).to_value();
@@ -407,7 +415,6 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
 
                 return Ok(());
             }
-            // These are all AtomicRMW ops
             sym::atomic_max | sym::atomic_min => {
                 let atom_op = if name == sym::atomic_max {
                     AtomicRmwBinOp::AtomicMax
@@ -420,7 +427,13 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let ordering = fn_args.const_at(1).to_value();
                     let ptr = args[0].immediate();
                     let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ false,
+                    )
                 } else {
                     invalid_monomorphization_int_type(ty);
                     return Ok(());
@@ -438,21 +451,44 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     let ordering = fn_args.const_at(1).to_value();
                     let ptr = args[0].immediate();
                     let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ false,
+                    )
                 } else {
                     invalid_monomorphization_int_type(ty);
                     return Ok(());
                 }
             }
-            sym::atomic_xchg
-            | sym::atomic_xadd
+            sym::atomic_xchg => {
+                let ty = fn_args.type_at(0);
+                let ordering = fn_args.const_at(1).to_value();
+                if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
+                    let ptr = args[0].immediate();
+                    let val = args[1].immediate();
+                    let atomic_op = AtomicRmwBinOp::AtomicXchg;
+                    bx.atomic_rmw(
+                        atomic_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ ty.is_raw_ptr(),
+                    )
+                } else {
+                    invalid_monomorphization_int_or_ptr_type(ty);
+                    return Ok(());
+                }
+            }
+            sym::atomic_xadd
             | sym::atomic_xsub
             | sym::atomic_and
             | sym::atomic_nand
             | sym::atomic_or
             | sym::atomic_xor => {
                 let atom_op = match name {
-                    sym::atomic_xchg => AtomicRmwBinOp::AtomicXchg,
                     sym::atomic_xadd => AtomicRmwBinOp::AtomicAdd,
                     sym::atomic_xsub => AtomicRmwBinOp::AtomicSub,
                     sym::atomic_and => AtomicRmwBinOp::AtomicAnd,
@@ -462,14 +498,28 @@ impl<'a, 'tcx, Bx: BuilderMethods<'a, 'tcx>> FunctionCx<'a, 'tcx, Bx> {
                     _ => unreachable!(),
                 };
 
-                let ty = fn_args.type_at(0);
-                if int_type_width_signed(ty, bx.tcx()).is_some() || ty.is_raw_ptr() {
-                    let ordering = fn_args.const_at(1).to_value();
-                    let ptr = args[0].immediate();
-                    let val = args[1].immediate();
-                    bx.atomic_rmw(atom_op, ptr, val, parse_atomic_ordering(ordering))
+                // The type of the in-memory data.
+                let ty_mem = fn_args.type_at(0);
+                // The type of the 2nd operand, given by-value.
+                let ty_op = fn_args.type_at(1);
+
+                let ordering = fn_args.const_at(2).to_value();
+                // We require either both arguments to have the same integer type, or the first to
+                // be a pointer and the second to be `usize`.
+                if (int_type_width_signed(ty_mem, bx.tcx()).is_some() && ty_op == ty_mem)
+                    || (ty_mem.is_raw_ptr() && ty_op == bx.tcx().types.usize)
+                {
+                    let ptr = args[0].immediate(); // of type "pointer to `ty_mem`"
+                    let val = args[1].immediate(); // of type `ty_op`
+                    bx.atomic_rmw(
+                        atom_op,
+                        ptr,
+                        val,
+                        parse_atomic_ordering(ordering),
+                        /* ret_ptr */ ty_mem.is_raw_ptr(),
+                    )
                 } else {
-                    invalid_monomorphization_int_type(ty);
+                    invalid_monomorphization_int_or_ptr_type(ty_mem);
                     return Ok(());
                 }
             }
diff --git a/compiler/rustc_codegen_ssa/src/traits/builder.rs b/compiler/rustc_codegen_ssa/src/traits/builder.rs
index 4b18146863b..f417d1a7bf7 100644
--- a/compiler/rustc_codegen_ssa/src/traits/builder.rs
+++ b/compiler/rustc_codegen_ssa/src/traits/builder.rs
@@ -548,12 +548,15 @@ pub trait BuilderMethods<'a, 'tcx>:
         failure_order: AtomicOrdering,
         weak: bool,
     ) -> (Self::Value, Self::Value);
+    /// `ret_ptr` indicates whether the return type (which is also the type `dst` points to)
+    /// is a pointer or the same type as `src`.
     fn atomic_rmw(
         &mut self,
         op: AtomicRmwBinOp,
         dst: Self::Value,
         src: Self::Value,
         order: AtomicOrdering,
+        ret_ptr: bool,
     ) -> Self::Value;
     fn atomic_fence(&mut self, order: AtomicOrdering, scope: SynchronizationScope);
     fn set_invariant_load(&mut self, load: Self::Value);
diff --git a/compiler/rustc_errors/src/diagnostic.rs b/compiler/rustc_errors/src/diagnostic.rs
index 96c7ba6ed27..5a5563c7bb2 100644
--- a/compiler/rustc_errors/src/diagnostic.rs
+++ b/compiler/rustc_errors/src/diagnostic.rs
@@ -1382,6 +1382,11 @@ impl<'a, G: EmissionGuarantee> Diag<'a, G> {
         &mut self.long_ty_path
     }
 
+    pub fn with_long_ty_path(mut self, long_ty_path: Option<PathBuf>) -> Self {
+        self.long_ty_path = long_ty_path;
+        self
+    }
+
     /// Most `emit_producing_guarantee` functions use this as a starting point.
     fn emit_producing_nothing(mut self) {
         let diag = self.take_diag();
diff --git a/compiler/rustc_errors/src/emitter.rs b/compiler/rustc_errors/src/emitter.rs
index 84970e7c162..0c839f94f7f 100644
--- a/compiler/rustc_errors/src/emitter.rs
+++ b/compiler/rustc_errors/src/emitter.rs
@@ -409,7 +409,7 @@ pub trait Emitter {
                 if !redundant_span || always_backtrace {
                     let msg: Cow<'static, _> = match trace.kind {
                         ExpnKind::Macro(MacroKind::Attr, _) => {
-                            "this procedural macro expansion".into()
+                            "this attribute macro expansion".into()
                         }
                         ExpnKind::Macro(MacroKind::Derive, _) => {
                             "this derive macro expansion".into()
diff --git a/compiler/rustc_expand/messages.ftl b/compiler/rustc_expand/messages.ftl
index 5a53670c865..1f8f3be6809 100644
--- a/compiler/rustc_expand/messages.ftl
+++ b/compiler/rustc_expand/messages.ftl
@@ -70,6 +70,9 @@ expand_invalid_fragment_specifier =
     invalid fragment specifier `{$fragment}`
     .help = {$help}
 
+expand_macro_args_bad_delim = macro attribute argument matchers require parentheses
+expand_macro_args_bad_delim_sugg = the delimiters should be `(` and `)`
+
 expand_macro_body_stability =
     macros cannot have body stability attributes
     .label = invalid body stability attribute
diff --git a/compiler/rustc_expand/src/errors.rs b/compiler/rustc_expand/src/errors.rs
index fd1391a554a..e58269991fc 100644
--- a/compiler/rustc_expand/src/errors.rs
+++ b/compiler/rustc_expand/src/errors.rs
@@ -482,3 +482,21 @@ mod metavar_exprs {
         pub key: MacroRulesNormalizedIdent,
     }
 }
+
+#[derive(Diagnostic)]
+#[diag(expand_macro_args_bad_delim)]
+pub(crate) struct MacroArgsBadDelim {
+    #[primary_span]
+    pub span: Span,
+    #[subdiagnostic]
+    pub sugg: MacroArgsBadDelimSugg,
+}
+
+#[derive(Subdiagnostic)]
+#[multipart_suggestion(expand_macro_args_bad_delim_sugg, applicability = "machine-applicable")]
+pub(crate) struct MacroArgsBadDelimSugg {
+    #[suggestion_part(code = "(")]
+    pub open: Span,
+    #[suggestion_part(code = ")")]
+    pub close: Span,
+}
diff --git a/compiler/rustc_expand/src/mbe/diagnostics.rs b/compiler/rustc_expand/src/mbe/diagnostics.rs
index 7a280d671f4..5b9d56ee2bc 100644
--- a/compiler/rustc_expand/src/mbe/diagnostics.rs
+++ b/compiler/rustc_expand/src/mbe/diagnostics.rs
@@ -7,29 +7,40 @@ use rustc_macros::Subdiagnostic;
 use rustc_parse::parser::{Parser, Recovery, token_descr};
 use rustc_session::parse::ParseSess;
 use rustc_span::source_map::SourceMap;
-use rustc_span::{ErrorGuaranteed, Ident, Span};
+use rustc_span::{DUMMY_SP, ErrorGuaranteed, Ident, Span};
 use tracing::debug;
 
 use super::macro_rules::{MacroRule, NoopTracker, parser_from_cx};
 use crate::expand::{AstFragmentKind, parse_ast_fragment};
 use crate::mbe::macro_parser::ParseResult::*;
 use crate::mbe::macro_parser::{MatcherLoc, NamedParseResult, TtParser};
-use crate::mbe::macro_rules::{Tracker, try_match_macro};
+use crate::mbe::macro_rules::{Tracker, try_match_macro, try_match_macro_attr};
 
 pub(super) fn failed_to_match_macro(
     psess: &ParseSess,
     sp: Span,
     def_span: Span,
     name: Ident,
-    arg: TokenStream,
+    attr_args: Option<&TokenStream>,
+    body: &TokenStream,
     rules: &[MacroRule],
 ) -> (Span, ErrorGuaranteed) {
     debug!("failed to match macro");
+    let def_head_span = if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
+        psess.source_map().guess_head_span(def_span)
+    } else {
+        DUMMY_SP
+    };
+
     // An error occurred, try the expansion again, tracking the expansion closely for better
     // diagnostics.
     let mut tracker = CollectTrackerAndEmitter::new(psess.dcx(), sp);
 
-    let try_success_result = try_match_macro(psess, name, &arg, rules, &mut tracker);
+    let try_success_result = if let Some(attr_args) = attr_args {
+        try_match_macro_attr(psess, name, attr_args, body, rules, &mut tracker)
+    } else {
+        try_match_macro(psess, name, body, rules, &mut tracker)
+    };
 
     if try_success_result.is_ok() {
         // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -47,6 +58,18 @@ pub(super) fn failed_to_match_macro(
 
     let Some(BestFailure { token, msg: label, remaining_matcher, .. }) = tracker.best_failure
     else {
+        // FIXME: we should report this at macro resolution time, as we do for
+        // `resolve_macro_cannot_use_as_attr`. We can do that once we track multiple macro kinds for a
+        // Def.
+        if attr_args.is_none() && !rules.iter().any(|rule| matches!(rule, MacroRule::Func { .. })) {
+            let msg = format!("macro has no rules for function-like invocation `{name}!`");
+            let mut err = psess.dcx().struct_span_err(sp, msg);
+            if !def_head_span.is_dummy() {
+                let msg = "this macro has no rules for function-like invocation";
+                err.span_label(def_head_span, msg);
+            }
+            return (sp, err.emit());
+        }
         return (sp, psess.dcx().span_delayed_bug(sp, "failed to match a macro"));
     };
 
@@ -54,8 +77,8 @@ pub(super) fn failed_to_match_macro(
 
     let mut err = psess.dcx().struct_span_err(span, parse_failure_msg(&token, None));
     err.span_label(span, label);
-    if !def_span.is_dummy() && !psess.source_map().is_imported(def_span) {
-        err.span_label(psess.source_map().guess_head_span(def_span), "when calling this macro");
+    if !def_head_span.is_dummy() {
+        err.span_label(def_head_span, "when calling this macro");
     }
 
     annotate_doc_comment(&mut err, psess.source_map(), span);
@@ -79,13 +102,16 @@ pub(super) fn failed_to_match_macro(
     }
 
     // Check whether there's a missing comma in this macro call, like `println!("{}" a);`
-    if let Some((arg, comma_span)) = arg.add_comma() {
+    if attr_args.is_none()
+        && let Some((body, comma_span)) = body.add_comma()
+    {
         for rule in rules {
-            let parser = parser_from_cx(psess, arg.clone(), Recovery::Allowed);
+            let MacroRule::Func { lhs, .. } = rule else { continue };
+            let parser = parser_from_cx(psess, body.clone(), Recovery::Allowed);
             let mut tt_parser = TtParser::new(name);
 
             if let Success(_) =
-                tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &rule.lhs, &mut NoopTracker)
+                tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, &mut NoopTracker)
             {
                 if comma_span.is_dummy() {
                     err.note("you might be missing a comma");
@@ -116,13 +142,13 @@ struct CollectTrackerAndEmitter<'dcx, 'matcher> {
 
 struct BestFailure {
     token: Token,
-    position_in_tokenstream: u32,
+    position_in_tokenstream: (bool, u32),
     msg: &'static str,
     remaining_matcher: MatcherLoc,
 }
 
 impl BestFailure {
-    fn is_better_position(&self, position: u32) -> bool {
+    fn is_better_position(&self, position: (bool, u32)) -> bool {
         position > self.position_in_tokenstream
     }
 }
@@ -142,7 +168,7 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
         }
     }
 
-    fn after_arm(&mut self, result: &NamedParseResult<Self::Failure>) {
+    fn after_arm(&mut self, in_body: bool, result: &NamedParseResult<Self::Failure>) {
         match result {
             Success(_) => {
                 // Nonterminal parser recovery might turn failed matches into successful ones,
@@ -155,14 +181,15 @@ impl<'dcx, 'matcher> Tracker<'matcher> for CollectTrackerAndEmitter<'dcx, 'match
             Failure((token, approx_position, msg)) => {
                 debug!(?token, ?msg, "a new failure of an arm");
 
+                let position_in_tokenstream = (in_body, *approx_position);
                 if self
                     .best_failure
                     .as_ref()
-                    .is_none_or(|failure| failure.is_better_position(*approx_position))
+                    .is_none_or(|failure| failure.is_better_position(position_in_tokenstream))
                 {
                     self.best_failure = Some(BestFailure {
                         token: *token,
-                        position_in_tokenstream: *approx_position,
+                        position_in_tokenstream,
                         msg,
                         remaining_matcher: self
                             .remaining_matcher
diff --git a/compiler/rustc_expand/src/mbe/macro_check.rs b/compiler/rustc_expand/src/mbe/macro_check.rs
index bbdff866feb..25987a50366 100644
--- a/compiler/rustc_expand/src/mbe/macro_check.rs
+++ b/compiler/rustc_expand/src/mbe/macro_check.rs
@@ -193,15 +193,19 @@ struct MacroState<'a> {
 /// Arguments:
 /// - `psess` is used to emit diagnostics and lints
 /// - `node_id` is used to emit lints
-/// - `lhs` and `rhs` represent the rule
+/// - `args`, `lhs`, and `rhs` represent the rule
 pub(super) fn check_meta_variables(
     psess: &ParseSess,
     node_id: NodeId,
+    args: Option<&TokenTree>,
     lhs: &TokenTree,
     rhs: &TokenTree,
 ) -> Result<(), ErrorGuaranteed> {
     let mut guar = None;
     let mut binders = Binders::default();
+    if let Some(args) = args {
+        check_binders(psess, node_id, args, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
+    }
     check_binders(psess, node_id, lhs, &Stack::Empty, &mut binders, &Stack::Empty, &mut guar);
     check_occurrences(psess, node_id, rhs, &Stack::Empty, &binders, &Stack::Empty, &mut guar);
     guar.map_or(Ok(()), Err)
diff --git a/compiler/rustc_expand/src/mbe/macro_rules.rs b/compiler/rustc_expand/src/mbe/macro_rules.rs
index 52d38c35f98..37b236a2e26 100644
--- a/compiler/rustc_expand/src/mbe/macro_rules.rs
+++ b/compiler/rustc_expand/src/mbe/macro_rules.rs
@@ -6,12 +6,12 @@ use std::{mem, slice};
 use ast::token::IdentIsRaw;
 use rustc_ast::token::NtPatKind::*;
 use rustc_ast::token::TokenKind::*;
-use rustc_ast::token::{self, NonterminalKind, Token, TokenKind};
-use rustc_ast::tokenstream::{DelimSpan, TokenStream};
+use rustc_ast::token::{self, Delimiter, NonterminalKind, Token, TokenKind};
+use rustc_ast::tokenstream::{self, DelimSpan, TokenStream};
 use rustc_ast::{self as ast, DUMMY_NODE_ID, NodeId};
 use rustc_ast_pretty::pprust;
 use rustc_data_structures::fx::{FxHashMap, FxIndexMap};
-use rustc_errors::{Applicability, Diag, ErrorGuaranteed};
+use rustc_errors::{Applicability, Diag, ErrorGuaranteed, MultiSpan};
 use rustc_feature::Features;
 use rustc_hir as hir;
 use rustc_hir::attrs::AttributeKind;
@@ -23,23 +23,26 @@ use rustc_lint_defs::builtin::{
 use rustc_parse::exp;
 use rustc_parse::parser::{Parser, Recovery};
 use rustc_session::Session;
-use rustc_session::parse::ParseSess;
+use rustc_session::parse::{ParseSess, feature_err};
 use rustc_span::edition::Edition;
 use rustc_span::hygiene::Transparency;
 use rustc_span::{Ident, Span, kw, sym};
 use tracing::{debug, instrument, trace, trace_span};
 
+use super::diagnostics::failed_to_match_macro;
 use super::macro_parser::{NamedMatches, NamedParseResult};
 use super::{SequenceRepetition, diagnostics};
 use crate::base::{
-    DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult, SyntaxExtension,
-    SyntaxExtensionKind, TTMacroExpander,
+    AttrProcMacro, DummyResult, ExpandResult, ExtCtxt, MacResult, MacroExpanderResult,
+    SyntaxExtension, SyntaxExtensionKind, TTMacroExpander,
 };
+use crate::errors;
 use crate::expand::{AstFragment, AstFragmentKind, ensure_complete_parse, parse_ast_fragment};
+use crate::mbe::macro_check::check_meta_variables;
 use crate::mbe::macro_parser::{Error, ErrorReported, Failure, MatcherLoc, Success, TtParser};
 use crate::mbe::quoted::{RulePart, parse_one_tt};
 use crate::mbe::transcribe::transcribe;
-use crate::mbe::{self, KleeneOp, macro_check};
+use crate::mbe::{self, KleeneOp};
 
 pub(crate) struct ParserAnyMacro<'a> {
     parser: Parser<'a>,
@@ -123,10 +126,17 @@ impl<'a> ParserAnyMacro<'a> {
     }
 }
 
-pub(super) struct MacroRule {
-    pub(super) lhs: Vec<MatcherLoc>,
-    lhs_span: Span,
-    rhs: mbe::TokenTree,
+pub(super) enum MacroRule {
+    /// A function-style rule, for use with `m!()`
+    Func { lhs: Vec<MatcherLoc>, lhs_span: Span, rhs: mbe::TokenTree },
+    /// An attr rule, for use with `#[m]`
+    Attr {
+        args: Vec<MatcherLoc>,
+        args_span: Span,
+        body: Vec<MatcherLoc>,
+        body_span: Span,
+        rhs: mbe::TokenTree,
+    },
 }
 
 pub struct MacroRulesMacroExpander {
@@ -138,10 +148,15 @@ pub struct MacroRulesMacroExpander {
 }
 
 impl MacroRulesMacroExpander {
-    pub fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, Span)> {
+    pub fn get_unused_rule(&self, rule_i: usize) -> Option<(&Ident, MultiSpan)> {
         // If the rhs contains an invocation like `compile_error!`, don't report it as unused.
-        let rule = &self.rules[rule_i];
-        if has_compile_error_macro(&rule.rhs) { None } else { Some((&self.name, rule.lhs_span)) }
+        let (span, rhs) = match self.rules[rule_i] {
+            MacroRule::Func { lhs_span, ref rhs, .. } => (MultiSpan::from_span(lhs_span), rhs),
+            MacroRule::Attr { args_span, body_span, ref rhs, .. } => {
+                (MultiSpan::from_spans(vec![args_span, body_span]), rhs)
+            }
+        };
+        if has_compile_error_macro(rhs) { None } else { Some((&self.name, span)) }
     }
 }
 
@@ -165,6 +180,28 @@ impl TTMacroExpander for MacroRulesMacroExpander {
     }
 }
 
+impl AttrProcMacro for MacroRulesMacroExpander {
+    fn expand(
+        &self,
+        cx: &mut ExtCtxt<'_>,
+        sp: Span,
+        args: TokenStream,
+        body: TokenStream,
+    ) -> Result<TokenStream, ErrorGuaranteed> {
+        expand_macro_attr(
+            cx,
+            sp,
+            self.span,
+            self.node_id,
+            self.name,
+            self.transparency,
+            args,
+            body,
+            &self.rules,
+        )
+    }
+}
+
 struct DummyExpander(ErrorGuaranteed);
 
 impl TTMacroExpander for DummyExpander {
@@ -197,7 +234,7 @@ pub(super) trait Tracker<'matcher> {
 
     /// This is called after an arm has been parsed, either successfully or unsuccessfully. When
     /// this is called, `before_match_loc` was called at least once (with a `MatcherLoc::Eof`).
-    fn after_arm(&mut self, _result: &NamedParseResult<Self::Failure>) {}
+    fn after_arm(&mut self, _in_body: bool, _result: &NamedParseResult<Self::Failure>) {}
 
     /// For tracing.
     fn description() -> &'static str;
@@ -245,14 +282,17 @@ fn expand_macro<'cx>(
 
     match try_success_result {
         Ok((rule_index, rule, named_matches)) => {
-            let mbe::TokenTree::Delimited(rhs_span, _, ref rhs) = rule.rhs else {
+            let MacroRule::Func { rhs, .. } = rule else {
+                panic!("try_match_macro returned non-func rule");
+            };
+            let mbe::TokenTree::Delimited(rhs_span, _, rhs) = rhs else {
                 cx.dcx().span_bug(sp, "malformed macro rhs");
             };
-            let arm_span = rule.rhs.span();
+            let arm_span = rhs_span.entire();
 
             // rhs has holes ( `$id` and `$(...)` that need filled)
             let id = cx.current_expansion.id;
-            let tts = match transcribe(psess, &named_matches, rhs, rhs_span, transparency, id) {
+            let tts = match transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id) {
                 Ok(tts) => tts,
                 Err(err) => {
                     let guar = err.emit();
@@ -280,13 +320,76 @@ fn expand_macro<'cx>(
         Err(CanRetry::Yes) => {
             // Retry and emit a better error.
             let (span, guar) =
-                diagnostics::failed_to_match_macro(cx.psess(), sp, def_span, name, arg, rules);
+                failed_to_match_macro(cx.psess(), sp, def_span, name, None, &arg, rules);
             cx.macro_error_and_trace_macros_diag();
             DummyResult::any(span, guar)
         }
     }
 }
 
+/// Expands the rules based macro defined by `rules` for a given attribute `args` and `body`.
+#[instrument(skip(cx, transparency, args, body, rules))]
+fn expand_macro_attr(
+    cx: &mut ExtCtxt<'_>,
+    sp: Span,
+    def_span: Span,
+    node_id: NodeId,
+    name: Ident,
+    transparency: Transparency,
+    args: TokenStream,
+    body: TokenStream,
+    rules: &[MacroRule],
+) -> Result<TokenStream, ErrorGuaranteed> {
+    let psess = &cx.sess.psess;
+    // Macros defined in the current crate have a real node id,
+    // whereas macros from an external crate have a dummy id.
+    let is_local = node_id != DUMMY_NODE_ID;
+
+    if cx.trace_macros() {
+        let msg = format!(
+            "expanding `$[{name}({})] {}`",
+            pprust::tts_to_string(&args),
+            pprust::tts_to_string(&body),
+        );
+        trace_macros_note(&mut cx.expansions, sp, msg);
+    }
+
+    // Track nothing for the best performance.
+    match try_match_macro_attr(psess, name, &args, &body, rules, &mut NoopTracker) {
+        Ok((i, rule, named_matches)) => {
+            let MacroRule::Attr { rhs, .. } = rule else {
+                panic!("try_macro_match_attr returned non-attr rule");
+            };
+            let mbe::TokenTree::Delimited(rhs_span, _, rhs) = rhs else {
+                cx.dcx().span_bug(sp, "malformed macro rhs");
+            };
+
+            let id = cx.current_expansion.id;
+            let tts = transcribe(psess, &named_matches, rhs, *rhs_span, transparency, id)
+                .map_err(|e| e.emit())?;
+
+            if cx.trace_macros() {
+                let msg = format!("to `{}`", pprust::tts_to_string(&tts));
+                trace_macros_note(&mut cx.expansions, sp, msg);
+            }
+
+            if is_local {
+                cx.resolver.record_macro_rule_usage(node_id, i);
+            }
+
+            Ok(tts)
+        }
+        Err(CanRetry::No(guar)) => Err(guar),
+        Err(CanRetry::Yes) => {
+            // Retry and emit a better error.
+            let (_, guar) =
+                failed_to_match_macro(cx.psess(), sp, def_span, name, Some(&args), &body, rules);
+            cx.trace_macros_diag();
+            Err(guar)
+        }
+    }
+}
+
 pub(super) enum CanRetry {
     Yes,
     /// We are not allowed to retry macro expansion as a fatal error has been emitted already.
@@ -327,6 +430,7 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
     // Try each arm's matchers.
     let mut tt_parser = TtParser::new(name);
     for (i, rule) in rules.iter().enumerate() {
+        let MacroRule::Func { lhs, .. } = rule else { continue };
         let _tracing_span = trace_span!("Matching arm", %i);
 
         // Take a snapshot of the state of pre-expansion gating at this point.
@@ -335,9 +439,9 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
         // are not recorded. On the first `Success(..)`ful matcher, the spans are merged.
         let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
 
-        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), &rule.lhs, track);
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&parser), lhs, track);
 
-        track.after_arm(&result);
+        track.after_arm(true, &result);
 
         match result {
             Success(named_matches) => {
@@ -372,6 +476,60 @@ pub(super) fn try_match_macro<'matcher, T: Tracker<'matcher>>(
     Err(CanRetry::Yes)
 }
 
+/// Try expanding the macro attribute. Returns the index of the successful arm and its
+/// named_matches if it was successful, and nothing if it failed. On failure, it's the caller's job
+/// to use `track` accordingly to record all errors correctly.
+#[instrument(level = "debug", skip(psess, attr_args, attr_body, rules, track), fields(tracking = %T::description()))]
+pub(super) fn try_match_macro_attr<'matcher, T: Tracker<'matcher>>(
+    psess: &ParseSess,
+    name: Ident,
+    attr_args: &TokenStream,
+    attr_body: &TokenStream,
+    rules: &'matcher [MacroRule],
+    track: &mut T,
+) -> Result<(usize, &'matcher MacroRule, NamedMatches), CanRetry> {
+    // This uses the same strategy as `try_match_macro`
+    let args_parser = parser_from_cx(psess, attr_args.clone(), T::recovery());
+    let body_parser = parser_from_cx(psess, attr_body.clone(), T::recovery());
+    let mut tt_parser = TtParser::new(name);
+    for (i, rule) in rules.iter().enumerate() {
+        let MacroRule::Attr { args, body, .. } = rule else { continue };
+
+        let mut gated_spans_snapshot = mem::take(&mut *psess.gated_spans.spans.borrow_mut());
+
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&args_parser), args, track);
+        track.after_arm(false, &result);
+
+        let mut named_matches = match result {
+            Success(named_matches) => named_matches,
+            Failure(_) => {
+                mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut());
+                continue;
+            }
+            Error(_, _) => return Err(CanRetry::Yes),
+            ErrorReported(guar) => return Err(CanRetry::No(guar)),
+        };
+
+        let result = tt_parser.parse_tt(&mut Cow::Borrowed(&body_parser), body, track);
+        track.after_arm(true, &result);
+
+        match result {
+            Success(body_named_matches) => {
+                psess.gated_spans.merge(gated_spans_snapshot);
+                named_matches.extend(body_named_matches);
+                return Ok((i, rule, named_matches));
+            }
+            Failure(_) => {
+                mem::swap(&mut gated_spans_snapshot, &mut psess.gated_spans.spans.borrow_mut())
+            }
+            Error(_, _) => return Err(CanRetry::Yes),
+            ErrorReported(guar) => return Err(CanRetry::No(guar)),
+        }
+    }
+
+    Err(CanRetry::Yes)
+}
+
 /// Converts a macro item into a syntax extension.
 pub fn compile_declarative_macro(
     sess: &Session,
@@ -382,13 +540,13 @@ pub fn compile_declarative_macro(
     span: Span,
     node_id: NodeId,
     edition: Edition,
-) -> (SyntaxExtension, usize) {
-    let mk_syn_ext = |expander| {
-        let kind = SyntaxExtensionKind::LegacyBang(expander);
+) -> (SyntaxExtension, Option<Arc<SyntaxExtension>>, usize) {
+    let mk_syn_ext = |kind| {
         let is_local = is_defined_in_current_crate(node_id);
         SyntaxExtension::new(sess, kind, span, Vec::new(), edition, ident.name, attrs, is_local)
     };
-    let dummy_syn_ext = |guar| (mk_syn_ext(Arc::new(DummyExpander(guar))), 0);
+    let mk_bang_ext = |expander| mk_syn_ext(SyntaxExtensionKind::LegacyBang(expander));
+    let dummy_syn_ext = |guar| (mk_bang_ext(Arc::new(DummyExpander(guar))), None, 0);
 
     let macro_rules = macro_def.macro_rules;
     let exp_sep = if macro_rules { exp!(Semi) } else { exp!(Comma) };
@@ -401,9 +559,30 @@ pub fn compile_declarative_macro(
     let mut guar = None;
     let mut check_emission = |ret: Result<(), ErrorGuaranteed>| guar = guar.or(ret.err());
 
+    let mut has_attr_rules = false;
     let mut rules = Vec::new();
 
     while p.token != token::Eof {
+        let args = if p.eat_keyword_noexpect(sym::attr) {
+            has_attr_rules = true;
+            if !features.macro_attr() {
+                feature_err(sess, sym::macro_attr, span, "`macro_rules!` attributes are unstable")
+                    .emit();
+            }
+            if let Some(guar) = check_no_eof(sess, &p, "expected macro attr args") {
+                return dummy_syn_ext(guar);
+            }
+            let args = p.parse_token_tree();
+            check_args_parens(sess, &args);
+            let args = parse_one_tt(args, RulePart::Pattern, sess, node_id, features, edition);
+            check_emission(check_lhs(sess, node_id, &args));
+            if let Some(guar) = check_no_eof(sess, &p, "expected macro attr body") {
+                return dummy_syn_ext(guar);
+            }
+            Some(args)
+        } else {
+            None
+        };
         let lhs_tt = p.parse_token_tree();
         let lhs_tt = parse_one_tt(lhs_tt, RulePart::Pattern, sess, node_id, features, edition);
         check_emission(check_lhs(sess, node_id, &lhs_tt));
@@ -416,7 +595,7 @@ pub fn compile_declarative_macro(
         let rhs_tt = p.parse_token_tree();
         let rhs_tt = parse_one_tt(rhs_tt, RulePart::Body, sess, node_id, features, edition);
         check_emission(check_rhs(sess, &rhs_tt));
-        check_emission(macro_check::check_meta_variables(&sess.psess, node_id, &lhs_tt, &rhs_tt));
+        check_emission(check_meta_variables(&sess.psess, node_id, args.as_ref(), &lhs_tt, &rhs_tt));
         let lhs_span = lhs_tt.span();
         // Convert the lhs into `MatcherLoc` form, which is better for doing the
         // actual matching.
@@ -425,7 +604,17 @@ pub fn compile_declarative_macro(
         } else {
             return dummy_syn_ext(guar.unwrap());
         };
-        rules.push(MacroRule { lhs, lhs_span, rhs: rhs_tt });
+        if let Some(args) = args {
+            let args_span = args.span();
+            let mbe::TokenTree::Delimited(.., delimited) = args else {
+                return dummy_syn_ext(guar.unwrap());
+            };
+            let args = mbe::macro_parser::compute_locs(&delimited.tts);
+            let body_span = lhs_span;
+            rules.push(MacroRule::Attr { args, args_span, body: lhs, body_span, rhs: rhs_tt });
+        } else {
+            rules.push(MacroRule::Func { lhs, lhs_span, rhs: rhs_tt });
+        }
         if p.token == token::Eof {
             break;
         }
@@ -451,9 +640,12 @@ pub fn compile_declarative_macro(
     // Return the number of rules for unused rule linting, if this is a local macro.
     let nrules = if is_defined_in_current_crate(node_id) { rules.len() } else { 0 };
 
-    let expander =
-        Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
-    (mk_syn_ext(expander), nrules)
+    let exp = Arc::new(MacroRulesMacroExpander { name: ident, span, node_id, transparency, rules });
+    let opt_attr_ext = has_attr_rules.then(|| {
+        let exp = Arc::clone(&exp);
+        Arc::new(mk_syn_ext(SyntaxExtensionKind::Attr(exp)))
+    });
+    (mk_bang_ext(exp), opt_attr_ext, nrules)
 }
 
 fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<ErrorGuaranteed> {
@@ -469,6 +661,18 @@ fn check_no_eof(sess: &Session, p: &Parser<'_>, msg: &'static str) -> Option<Err
     None
 }
 
+fn check_args_parens(sess: &Session, args: &tokenstream::TokenTree) {
+    // This does not handle the non-delimited case; that gets handled separately by `check_lhs`.
+    if let tokenstream::TokenTree::Delimited(dspan, _, delim, _) = args
+        && *delim != Delimiter::Parenthesis
+    {
+        sess.dcx().emit_err(errors::MacroArgsBadDelim {
+            span: dspan.entire(),
+            sugg: errors::MacroArgsBadDelimSugg { open: dspan.open, close: dspan.close },
+        });
+    }
+}
+
 fn check_lhs(sess: &Session, node_id: NodeId, lhs: &mbe::TokenTree) -> Result<(), ErrorGuaranteed> {
     let e1 = check_lhs_nt_follows(sess, node_id, lhs);
     let e2 = check_lhs_no_empty_seq(sess, slice::from_ref(lhs));
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index ca71bcebfdd..ae1f57c1ef6 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -554,6 +554,8 @@ declare_features! (
     (unstable, link_arg_attribute, "1.76.0", Some(99427)),
     /// Allows fused `loop`/`match` for direct intraprocedural jumps.
     (incomplete, loop_match, "1.90.0", Some(132306)),
+    /// Allow `macro_rules!` attribute rules
+    (unstable, macro_attr, "CURRENT_RUSTC_VERSION", Some(83527)),
     /// Give access to additional metadata about declarative macro meta-variables.
     (unstable, macro_metavar_expr, "1.61.0", Some(83527)),
     /// Provides a way to concatenate identifiers using metavariable expressions.
diff --git a/compiler/rustc_hir_analysis/src/check/intrinsic.rs b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
index 6e5fe3823ab..4441dd6ebd6 100644
--- a/compiler/rustc_hir_analysis/src/check/intrinsic.rs
+++ b/compiler/rustc_hir_analysis/src/check/intrinsic.rs
@@ -652,16 +652,16 @@ pub(crate) fn check_intrinsic_type(
         sym::atomic_store => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], tcx.types.unit),
 
         sym::atomic_xchg
-        | sym::atomic_xadd
-        | sym::atomic_xsub
-        | sym::atomic_and
-        | sym::atomic_nand
-        | sym::atomic_or
-        | sym::atomic_xor
         | sym::atomic_max
         | sym::atomic_min
         | sym::atomic_umax
         | sym::atomic_umin => (1, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(0)], param(0)),
+        sym::atomic_xadd
+        | sym::atomic_xsub
+        | sym::atomic_and
+        | sym::atomic_nand
+        | sym::atomic_or
+        | sym::atomic_xor => (2, 1, vec![Ty::new_mut_ptr(tcx, param(0)), param(1)], param(0)),
         sym::atomic_fence | sym::atomic_singlethreadfence => (0, 1, Vec::new(), tcx.types.unit),
 
         other => {
diff --git a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
index 7e2bfa9f920..1675aecd2b8 100644
--- a/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
+++ b/compiler/rustc_hir_analysis/src/hir_ty_lowering/mod.rs
@@ -1135,9 +1135,10 @@ impl<'tcx> dyn HirTyLowerer<'tcx> + '_ {
                         );
                     }
                 } else {
+                    let trait_ =
+                        tcx.short_string(bound.print_only_trait_path(), err.long_ty_path());
                     err.note(format!(
-                        "associated {assoc_kind_str} `{assoc_ident}` could derive from `{}`",
-                        bound.print_only_trait_path(),
+                        "associated {assoc_kind_str} `{assoc_ident}` could derive from `{trait_}`",
                     ));
                 }
             }
diff --git a/compiler/rustc_hir_typeck/messages.ftl b/compiler/rustc_hir_typeck/messages.ftl
index bac4d70103c..1ed0756fdd6 100644
--- a/compiler/rustc_hir_typeck/messages.ftl
+++ b/compiler/rustc_hir_typeck/messages.ftl
@@ -159,7 +159,7 @@ hir_typeck_lossy_provenance_ptr2int =
     .suggestion = use `.addr()` to obtain the address of a pointer
     .help = if you can't comply with strict provenance and need to expose the pointer provenance you can use `.expose_provenance()` instead
 
-hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty_str}`
+hir_typeck_missing_parentheses_in_range = can't call method `{$method_name}` on type `{$ty}`
 
 hir_typeck_naked_asm_outside_naked_fn =
     the `naked_asm!` macro can only be used in functions marked with `#[unsafe(naked)]`
@@ -184,7 +184,7 @@ hir_typeck_never_type_fallback_flowing_into_unsafe_path = never type fallback af
 hir_typeck_never_type_fallback_flowing_into_unsafe_union_field = never type fallback affects this union access
     .help = specify the type explicitly
 
-hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty_str}`{$trait_missing_method ->
+hir_typeck_no_associated_item = no {$item_kind} named `{$item_ident}` found for {$ty_prefix} `{$ty}`{$trait_missing_method ->
     [true] {""}
     *[other] {" "}in the current scope
 }
diff --git a/compiler/rustc_hir_typeck/src/errors.rs b/compiler/rustc_hir_typeck/src/errors.rs
index a8bb6956f10..d15d092b7d3 100644
--- a/compiler/rustc_hir_typeck/src/errors.rs
+++ b/compiler/rustc_hir_typeck/src/errors.rs
@@ -200,11 +200,11 @@ pub(crate) enum ExplicitDestructorCallSugg {
 
 #[derive(Diagnostic)]
 #[diag(hir_typeck_missing_parentheses_in_range, code = E0689)]
-pub(crate) struct MissingParenthesesInRange {
+pub(crate) struct MissingParenthesesInRange<'tcx> {
     #[primary_span]
     #[label(hir_typeck_missing_parentheses_in_range)]
     pub span: Span,
-    pub ty_str: String,
+    pub ty: Ty<'tcx>,
     pub method_name: String,
     #[subdiagnostic]
     pub add_missing_parentheses: Option<AddMissingParenthesesInRange>,
@@ -828,13 +828,13 @@ pub(crate) struct UnlabeledCfInWhileCondition<'a> {
 
 #[derive(Diagnostic)]
 #[diag(hir_typeck_no_associated_item, code = E0599)]
-pub(crate) struct NoAssociatedItem {
+pub(crate) struct NoAssociatedItem<'tcx> {
     #[primary_span]
     pub span: Span,
     pub item_kind: &'static str,
     pub item_ident: Ident,
     pub ty_prefix: Cow<'static, str>,
-    pub ty_str: String,
+    pub ty: Ty<'tcx>,
     pub trait_missing_method: bool,
 }
 
diff --git a/compiler/rustc_hir_typeck/src/expr.rs b/compiler/rustc_hir_typeck/src/expr.rs
index 454ec7ddcaf..0498a938366 100644
--- a/compiler/rustc_hir_typeck/src/expr.rs
+++ b/compiler/rustc_hir_typeck/src/expr.rs
@@ -2745,6 +2745,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 let available_field_names = self.available_field_names(variant, expr, skip_fields);
                 if let Some(field_name) =
                     find_best_match_for_name(&available_field_names, field.ident.name, None)
+                    && !(field.ident.name.as_str().parse::<usize>().is_ok()
+                        && field_name.as_str().parse::<usize>().is_ok())
                 {
                     err.span_label(field.ident.span, "unknown field");
                     err.span_suggestion_verbose(
@@ -3321,18 +3323,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         } else {
             (base_ty, "")
         };
-        for (found_fields, args) in
+        for found_fields in
             self.get_field_candidates_considering_privacy_for_diag(span, ty, mod_id, expr.hir_id)
         {
-            let field_names = found_fields.iter().map(|field| field.name).collect::<Vec<_>>();
+            let field_names = found_fields.iter().map(|field| field.0.name).collect::<Vec<_>>();
             let mut candidate_fields: Vec<_> = found_fields
                 .into_iter()
                 .filter_map(|candidate_field| {
                     self.check_for_nested_field_satisfying_condition_for_diag(
                         span,
-                        &|candidate_field, _| candidate_field.ident(self.tcx()) == field,
+                        &|candidate_field, _| candidate_field == field,
                         candidate_field,
-                        args,
                         vec![],
                         mod_id,
                         expr.hir_id,
@@ -3361,6 +3362,8 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 );
             } else if let Some(field_name) =
                 find_best_match_for_name(&field_names, field.name, None)
+                && !(field.name.as_str().parse::<usize>().is_ok()
+                    && field_name.as_str().parse::<usize>().is_ok())
             {
                 err.span_suggestion_verbose(
                     field.span,
@@ -3396,7 +3399,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         base_ty: Ty<'tcx>,
         mod_id: DefId,
         hir_id: HirId,
-    ) -> Vec<(Vec<&'tcx ty::FieldDef>, GenericArgsRef<'tcx>)> {
+    ) -> Vec<Vec<(Ident, Ty<'tcx>)>> {
         debug!("get_field_candidates(span: {:?}, base_t: {:?}", span, base_ty);
 
         let mut autoderef = self.autoderef(span, base_ty).silence_errors();
@@ -3422,7 +3425,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         if fields.iter().all(|field| !field.vis.is_accessible_from(mod_id, tcx)) {
                             return None;
                         }
-                        return Some((
+                        return Some(
                             fields
                                 .iter()
                                 .filter(move |field| {
@@ -3431,9 +3434,25 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 })
                                 // For compile-time reasons put a limit on number of fields we search
                                 .take(100)
+                                .map(|field_def| {
+                                    (
+                                        field_def.ident(self.tcx).normalize_to_macros_2_0(),
+                                        field_def.ty(self.tcx, args),
+                                    )
+                                })
+                                .collect::<Vec<_>>(),
+                        );
+                    }
+                    ty::Tuple(types) => {
+                        return Some(
+                            types
+                                .iter()
+                                .enumerate()
+                                // For compile-time reasons put a limit on number of fields we search
+                                .take(100)
+                                .map(|(i, ty)| (Ident::from_str(&i.to_string()), ty))
                                 .collect::<Vec<_>>(),
-                            *args,
-                        ));
+                        );
                     }
                     _ => None,
                 }
@@ -3443,56 +3462,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
     /// This method is called after we have encountered a missing field error to recursively
     /// search for the field
+    #[instrument(skip(self, matches, mod_id, hir_id), level = "debug")]
     pub(crate) fn check_for_nested_field_satisfying_condition_for_diag(
         &self,
         span: Span,
-        matches: &impl Fn(&ty::FieldDef, Ty<'tcx>) -> bool,
-        candidate_field: &ty::FieldDef,
-        subst: GenericArgsRef<'tcx>,
+        matches: &impl Fn(Ident, Ty<'tcx>) -> bool,
+        (candidate_name, candidate_ty): (Ident, Ty<'tcx>),
         mut field_path: Vec<Ident>,
         mod_id: DefId,
         hir_id: HirId,
     ) -> Option<Vec<Ident>> {
-        debug!(
-            "check_for_nested_field_satisfying(span: {:?}, candidate_field: {:?}, field_path: {:?}",
-            span, candidate_field, field_path
-        );
-
         if field_path.len() > 3 {
             // For compile-time reasons and to avoid infinite recursion we only check for fields
             // up to a depth of three
-            None
-        } else {
-            field_path.push(candidate_field.ident(self.tcx).normalize_to_macros_2_0());
-            let field_ty = candidate_field.ty(self.tcx, subst);
-            if matches(candidate_field, field_ty) {
-                return Some(field_path);
-            } else {
-                for (nested_fields, subst) in self
-                    .get_field_candidates_considering_privacy_for_diag(
-                        span, field_ty, mod_id, hir_id,
-                    )
-                {
-                    // recursively search fields of `candidate_field` if it's a ty::Adt
-                    for field in nested_fields {
-                        if let Some(field_path) = self
-                            .check_for_nested_field_satisfying_condition_for_diag(
-                                span,
-                                matches,
-                                field,
-                                subst,
-                                field_path.clone(),
-                                mod_id,
-                                hir_id,
-                            )
-                        {
-                            return Some(field_path);
-                        }
-                    }
+            return None;
+        }
+        field_path.push(candidate_name);
+        if matches(candidate_name, candidate_ty) {
+            return Some(field_path);
+        }
+        for nested_fields in self.get_field_candidates_considering_privacy_for_diag(
+            span,
+            candidate_ty,
+            mod_id,
+            hir_id,
+        ) {
+            // recursively search fields of `candidate_field` if it's a ty::Adt
+            for field in nested_fields {
+                if let Some(field_path) = self.check_for_nested_field_satisfying_condition_for_diag(
+                    span,
+                    matches,
+                    field,
+                    field_path.clone(),
+                    mod_id,
+                    hir_id,
+                ) {
+                    return Some(field_path);
                 }
             }
-            None
         }
+        None
     }
 
     fn check_expr_index(
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 0c0cc752b01..f7430f7af4e 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -376,16 +376,20 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    fn suggest_missing_writer(&self, rcvr_ty: Ty<'tcx>, rcvr_expr: &hir::Expr<'tcx>) -> Diag<'_> {
-        let mut file = None;
+    fn suggest_missing_writer(
+        &self,
+        rcvr_ty: Ty<'tcx>,
+        rcvr_expr: &hir::Expr<'tcx>,
+        mut long_ty_path: Option<PathBuf>,
+    ) -> Diag<'_> {
         let mut err = struct_span_code_err!(
             self.dcx(),
             rcvr_expr.span,
             E0599,
             "cannot write into `{}`",
-            self.tcx.short_string(rcvr_ty, &mut file),
+            self.tcx.short_string(rcvr_ty, &mut long_ty_path),
         );
-        *err.long_ty_path() = file;
+        *err.long_ty_path() = long_ty_path;
         err.span_note(
             rcvr_expr.span,
             "must implement `io::Write`, `fmt::Write`, or have a `write_fmt` method",
@@ -403,7 +407,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         &self,
         self_source: SelfSource<'tcx>,
         method_name: Ident,
-        ty_str_reported: &str,
+        ty: Ty<'tcx>,
         err: &mut Diag<'_>,
     ) {
         #[derive(Debug)]
@@ -478,7 +482,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 }
 
                 // If the shadowed binding has an itializer expression,
-                // use the initializer expression'ty to try to find the method again.
+                // use the initializer expression's ty to try to find the method again.
                 // For example like:  `let mut x = Vec::new();`,
                 // `Vec::new()` is the itializer expression.
                 if let Some(self_ty) = self.fcx.node_ty_opt(binding.init_hir_id)
@@ -566,17 +570,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     let mut span = MultiSpan::from_span(sugg_let.span);
                     span.push_span_label(sugg_let.span,
                             format!("`{rcvr_name}` of type `{self_ty}` that has method `{method_name}` defined earlier here"));
+
+                    let ty = self.tcx.short_string(ty, err.long_ty_path());
                     span.push_span_label(
                         self.tcx.hir_span(recv_id),
-                        format!(
-                            "earlier `{rcvr_name}` shadowed here with type `{ty_str_reported}`"
-                        ),
+                        format!("earlier `{rcvr_name}` shadowed here with type `{ty}`"),
                     );
                     err.span_note(
                         span,
                         format!(
                             "there's an earlier shadowed binding `{rcvr_name}` of type `{self_ty}` \
-                                    that has method `{method_name}` available"
+                             that has method `{method_name}` available"
                         ),
                     );
                 }
@@ -602,15 +606,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx;
         let rcvr_ty = self.resolve_vars_if_possible(rcvr_ty);
         let mut ty_file = None;
-        let (ty_str, short_ty_str) =
-            if trait_missing_method && let ty::Dynamic(predicates, _, _) = rcvr_ty.kind() {
-                (predicates.to_string(), with_forced_trimmed_paths!(predicates.to_string()))
-            } else {
-                (
-                    tcx.short_string(rcvr_ty, &mut ty_file),
-                    with_forced_trimmed_paths!(rcvr_ty.to_string()),
-                )
-            };
         let is_method = mode == Mode::MethodCall;
         let unsatisfied_predicates = &no_match_data.unsatisfied_predicates;
         let similar_candidate = no_match_data.similar_candidate;
@@ -629,15 +624,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // We could pass the file for long types into these two, but it isn't strictly necessary
         // given how targeted they are.
-        if let Err(guar) = self.report_failed_method_call_on_range_end(
-            tcx,
-            rcvr_ty,
-            source,
-            span,
-            item_ident,
-            &short_ty_str,
-            &mut ty_file,
-        ) {
+        if let Err(guar) =
+            self.report_failed_method_call_on_range_end(tcx, rcvr_ty, source, span, item_ident)
+        {
             return guar;
         }
         if let Err(guar) = self.report_failed_method_call_on_numerical_infer_var(
@@ -647,44 +636,42 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             span,
             item_kind,
             item_ident,
-            &short_ty_str,
             &mut ty_file,
         ) {
             return guar;
         }
         span = item_ident.span;
 
-        // Don't show generic arguments when the method can't be found in any implementation (#81576).
-        let mut ty_str_reported = ty_str.clone();
-        if let ty::Adt(_, generics) = rcvr_ty.kind() {
-            if generics.len() > 0 {
-                let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
-                let candidate_found = autoderef.any(|(ty, _)| {
-                    if let ty::Adt(adt_def, _) = ty.kind() {
-                        self.tcx
-                            .inherent_impls(adt_def.did())
-                            .into_iter()
-                            .any(|def_id| self.associated_value(*def_id, item_ident).is_some())
-                    } else {
-                        false
-                    }
-                });
-                let has_deref = autoderef.step_count() > 0;
-                if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
-                    if let Some((path_string, _)) = ty_str.split_once('<') {
-                        ty_str_reported = path_string.to_string();
-                    }
-                }
-            }
-        }
-
         let is_write = sugg_span.ctxt().outer_expn_data().macro_def_id.is_some_and(|def_id| {
             tcx.is_diagnostic_item(sym::write_macro, def_id)
                 || tcx.is_diagnostic_item(sym::writeln_macro, def_id)
         }) && item_ident.name == sym::write_fmt;
         let mut err = if is_write && let SelfSource::MethodCall(rcvr_expr) = source {
-            self.suggest_missing_writer(rcvr_ty, rcvr_expr)
+            self.suggest_missing_writer(rcvr_ty, rcvr_expr, ty_file)
         } else {
+            // Don't show expanded generic arguments when the method can't be found in any
+            // implementation (#81576).
+            let mut ty = rcvr_ty;
+            if let ty::Adt(def, generics) = rcvr_ty.kind() {
+                if generics.len() > 0 {
+                    let mut autoderef = self.autoderef(span, rcvr_ty).silence_errors();
+                    let candidate_found = autoderef.any(|(ty, _)| {
+                        if let ty::Adt(adt_def, _) = ty.kind() {
+                            self.tcx
+                                .inherent_impls(adt_def.did())
+                                .into_iter()
+                                .any(|def_id| self.associated_value(*def_id, item_ident).is_some())
+                        } else {
+                            false
+                        }
+                    });
+                    let has_deref = autoderef.step_count() > 0;
+                    if !candidate_found && !has_deref && unsatisfied_predicates.is_empty() {
+                        ty = self.tcx.at(span).type_of(def.did()).instantiate_identity();
+                    }
+                }
+            }
+
             let mut err = self.dcx().create_err(NoAssociatedItem {
                 span,
                 item_kind,
@@ -695,16 +682,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 } else {
                     rcvr_ty.prefix_string(self.tcx)
                 },
-                ty_str: ty_str_reported.clone(),
+                ty,
                 trait_missing_method,
             });
 
             if is_method {
                 self.suggest_use_shadowed_binding_with_method(
-                    source,
-                    item_ident,
-                    &ty_str_reported,
-                    &mut err,
+                    source, item_ident, rcvr_ty, &mut err,
                 );
             }
 
@@ -734,6 +718,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
             err
         };
+
         if tcx.sess.source_map().is_multiline(sugg_span) {
             err.span_label(sugg_span.with_hi(span.lo()), "");
         }
@@ -750,6 +735,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
 
         if tcx.ty_is_opaque_future(rcvr_ty) && item_ident.name == sym::poll {
+            let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
             err.help(format!(
                 "method `poll` found on `Pin<&mut {ty_str}>`, \
                 see documentation for `std::pin::Pin`"
@@ -1339,7 +1325,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             }
                             let OnUnimplementedNote { message, label, notes, .. } = self
                                 .err_ctxt()
-                                .on_unimplemented_note(trait_ref, &obligation, &mut ty_file);
+                                .on_unimplemented_note(trait_ref, &obligation, err.long_ty_path());
                             (message, label, notes)
                         })
                         .unwrap()
@@ -1347,6 +1333,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     (None, None, Vec::new())
                 };
                 let primary_message = primary_message.unwrap_or_else(|| {
+                    let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
                     format!(
                         "the {item_kind} `{item_ident}` exists for {actual_prefix} `{ty_str}`, \
                          but its trait bounds were not satisfied"
@@ -1409,6 +1396,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let mut find_candidate_for_method = false;
 
         let mut label_span_not_found = |err: &mut Diag<'_>| {
+            let ty_str = self.tcx.short_string(rcvr_ty, err.long_ty_path());
             if unsatisfied_predicates.is_empty() {
                 err.span_label(span, format!("{item_kind} not found in `{ty_str}`"));
                 let is_string_or_ref_str = match rcvr_ty.kind() {
@@ -2520,8 +2508,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         source: SelfSource<'tcx>,
         span: Span,
         item_name: Ident,
-        ty_str: &str,
-        long_ty_path: &mut Option<PathBuf>,
     ) -> Result<(), ErrorGuaranteed> {
         if let SelfSource::MethodCall(expr) = source {
             for (_, parent) in tcx.hir_parent_iter(expr.hir_id).take(5) {
@@ -2583,18 +2569,16 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     );
                     if pick.is_ok() {
                         let range_span = parent_expr.span.with_hi(expr.span.hi());
-                        let mut err = self.dcx().create_err(errors::MissingParenthesesInRange {
+                        return Err(self.dcx().emit_err(errors::MissingParenthesesInRange {
                             span,
-                            ty_str: ty_str.to_string(),
+                            ty: actual,
                             method_name: item_name.as_str().to_string(),
                             add_missing_parentheses: Some(errors::AddMissingParenthesesInRange {
                                 func_name: item_name.name.as_str().to_string(),
                                 left: range_span.shrink_to_lo(),
                                 right: range_span.shrink_to_hi(),
                             }),
-                        });
-                        *err.long_ty_path() = long_ty_path.take();
-                        return Err(err.emit());
+                        }));
                     }
                 }
             }
@@ -2610,7 +2594,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         span: Span,
         item_kind: &str,
         item_name: Ident,
-        ty_str: &str,
         long_ty_path: &mut Option<PathBuf>,
     ) -> Result<(), ErrorGuaranteed> {
         let found_candidate = all_traits(self.tcx)
@@ -2643,14 +2626,12 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             && !actual.has_concrete_skeleton()
             && let SelfSource::MethodCall(expr) = source
         {
+            let ty_str = self.tcx.short_string(actual, long_ty_path);
             let mut err = struct_span_code_err!(
                 self.dcx(),
                 span,
                 E0689,
-                "can't call {} `{}` on ambiguous numeric type `{}`",
-                item_kind,
-                item_name,
-                ty_str
+                "can't call {item_kind} `{item_name}` on ambiguous numeric type `{ty_str}`"
             );
             *err.long_ty_path() = long_ty_path.take();
             let concrete_type = if actual.is_integral() { "i32" } else { "f32" };
@@ -2792,7 +2773,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     ) {
         if let SelfSource::MethodCall(expr) = source {
             let mod_id = self.tcx.parent_module(expr.hir_id).to_def_id();
-            for (fields, args) in self.get_field_candidates_considering_privacy_for_diag(
+            for fields in self.get_field_candidates_considering_privacy_for_diag(
                 span,
                 actual,
                 mod_id,
@@ -2831,7 +2812,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                 })
                             },
                             candidate_field,
-                            args,
                             vec![],
                             mod_id,
                             expr.hir_id,
@@ -3671,7 +3651,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         )
                     {
                         debug!("try_alt_rcvr: pick candidate {:?}", pick);
-                        let did = Some(pick.item.container_id(self.tcx));
+                        let did = pick.item.trait_container(self.tcx);
                         // We don't want to suggest a container type when the missing
                         // method is `.clone()` or `.deref()` otherwise we'd suggest
                         // `Arc::new(foo).clone()`, which is far from what the user wants.
@@ -3720,8 +3700,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     && !alt_rcvr_sugg
                     // `T: !Unpin`
                     && !unpin
-                    // The method isn't `as_ref`, as it would provide a wrong suggestion for `Pin`.
-                    && sym::as_ref != item_name.name
                     // Either `Pin::as_ref` or `Pin::as_mut`.
                     && let Some(pin_call) = pin_call
                     // Search for `item_name` as a method accessible on `Pin<T>`.
@@ -3735,6 +3713,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // We skip some common traits that we don't want to consider because autoderefs
                     // would take care of them.
                     && !skippable.contains(&Some(pick.item.container_id(self.tcx)))
+                    // Do not suggest pinning when the method is directly on `Pin`.
+                    && pick.item.impl_container(self.tcx).map_or(true, |did| {
+                        match self.tcx.type_of(did).skip_binder().kind() {
+                            ty::Adt(def, _) => Some(def.did()) != self.tcx.lang_items().pin_type(),
+                            _ => true,
+                        }
+                    })
                     // We don't want to go through derefs.
                     && pick.autoderefs == 0
                     // Check that the method of the same name that was found on the new `Pin<T>`
diff --git a/compiler/rustc_metadata/src/native_libs.rs b/compiler/rustc_metadata/src/native_libs.rs
index 8855766ca98..958e314efab 100644
--- a/compiler/rustc_metadata/src/native_libs.rs
+++ b/compiler/rustc_metadata/src/native_libs.rs
@@ -83,7 +83,7 @@ pub fn walk_native_lib_search_dirs<R>(
     // Mac Catalyst uses the macOS SDK, but to link to iOS-specific frameworks
     // we must have the support library stubs in the library search path (#121430).
     if let Some(sdk_root) = apple_sdk_root
-        && sess.target.llvm_target.contains("macabi")
+        && sess.target.env == "macabi"
     {
         f(&sdk_root.join("System/iOSSupport/usr/lib"), false)?;
         f(&sdk_root.join("System/iOSSupport/System/Library/Frameworks"), true)?;
diff --git a/compiler/rustc_middle/src/ty/generic_args.rs b/compiler/rustc_middle/src/ty/generic_args.rs
index b02abb5ab43..648709e88e6 100644
--- a/compiler/rustc_middle/src/ty/generic_args.rs
+++ b/compiler/rustc_middle/src/ty/generic_args.rs
@@ -527,21 +527,28 @@ impl<'tcx> GenericArgs<'tcx> {
     #[inline]
     #[track_caller]
     pub fn type_at(&self, i: usize) -> Ty<'tcx> {
-        self[i].as_type().unwrap_or_else(|| bug!("expected type for param #{} in {:?}", i, self))
+        self[i].as_type().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected type for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
     #[track_caller]
     pub fn region_at(&self, i: usize) -> ty::Region<'tcx> {
-        self[i]
-            .as_region()
-            .unwrap_or_else(|| bug!("expected region for param #{} in {:?}", i, self))
+        self[i].as_region().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected region for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
     #[track_caller]
     pub fn const_at(&self, i: usize) -> ty::Const<'tcx> {
-        self[i].as_const().unwrap_or_else(|| bug!("expected const for param #{} in {:?}", i, self))
+        self[i].as_const().unwrap_or_else(
+            #[track_caller]
+            || bug!("expected const for param #{} in {:?}", i, self),
+        )
     }
 
     #[inline]
diff --git a/compiler/rustc_middle/src/ty/print/pretty.rs b/compiler/rustc_middle/src/ty/print/pretty.rs
index b381d62be47..67244e767cb 100644
--- a/compiler/rustc_middle/src/ty/print/pretty.rs
+++ b/compiler/rustc_middle/src/ty/print/pretty.rs
@@ -2987,7 +2987,7 @@ impl<'tcx> ty::Binder<'tcx, ty::TraitRef<'tcx>> {
     }
 }
 
-#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift)]
+#[derive(Copy, Clone, TypeFoldable, TypeVisitable, Lift, Hash)]
 pub struct TraitPredPrintModifiersAndPath<'tcx>(ty::TraitPredicate<'tcx>);
 
 impl<'tcx> fmt::Debug for TraitPredPrintModifiersAndPath<'tcx> {
diff --git a/compiler/rustc_pattern_analysis/src/constructor.rs b/compiler/rustc_pattern_analysis/src/constructor.rs
index 9a9e0db964c..12f653a1337 100644
--- a/compiler/rustc_pattern_analysis/src/constructor.rs
+++ b/compiler/rustc_pattern_analysis/src/constructor.rs
@@ -1130,16 +1130,16 @@ impl<Cx: PatCx> ConstructorSet<Cx> {
                         seen_false = true;
                     }
                 }
-                if seen_false {
-                    present.push(Bool(false));
-                } else {
-                    missing.push(Bool(false));
-                }
                 if seen_true {
                     present.push(Bool(true));
                 } else {
                     missing.push(Bool(true));
                 }
+                if seen_false {
+                    present.push(Bool(false));
+                } else {
+                    missing.push(Bool(false));
+                }
             }
             ConstructorSet::Integers { range_1, range_2 } => {
                 let seen_ranges: Vec<_> =
diff --git a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
index 14ca0d057f0..4ad64f81560 100644
--- a/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
+++ b/compiler/rustc_pattern_analysis/tests/exhaustiveness.rs
@@ -176,6 +176,9 @@ fn test_witnesses() {
         ),
         vec!["Enum::Variant1(_)", "Enum::Variant2(_)", "_"],
     );
+
+    // Assert we put `true` before `false`.
+    assert_witnesses(AllOfThem, Ty::Bool, Vec::new(), vec!["true", "false"]);
 }
 
 #[test]
diff --git a/compiler/rustc_resolve/messages.ftl b/compiler/rustc_resolve/messages.ftl
index 39e9a9cc58a..ceef558c0cf 100644
--- a/compiler/rustc_resolve/messages.ftl
+++ b/compiler/rustc_resolve/messages.ftl
@@ -243,7 +243,7 @@ resolve_lowercase_self =
     .suggestion = try using `Self`
 
 resolve_macro_cannot_use_as_attr =
-    `{$ident}` exists, but a declarative macro cannot be used as an attribute macro
+    `{$ident}` exists, but has no `attr` rules
 
 resolve_macro_cannot_use_as_derive =
      `{$ident}` exists, but a declarative macro cannot be used as a derive macro
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 80e57a4fa3d..092bb6fc4f9 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -631,9 +631,21 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 };
 
                 match result {
-                    Ok((binding, flags))
-                        if sub_namespace_match(binding.macro_kind(), macro_kind) =>
-                    {
+                    Ok((binding, flags)) => {
+                        let binding_macro_kind = binding.macro_kind();
+                        // If we're looking for an attribute, that might be supported by a
+                        // `macro_rules!` macro.
+                        // FIXME: Replace this with tracking multiple macro kinds for one Def.
+                        if !(sub_namespace_match(binding_macro_kind, macro_kind)
+                            || (binding_macro_kind == Some(MacroKind::Bang)
+                                && macro_kind == Some(MacroKind::Attr)
+                                && this
+                                    .get_macro(binding.res())
+                                    .is_some_and(|macro_data| macro_data.attr_ext.is_some())))
+                        {
+                            return None;
+                        }
+
                         if finalize.is_none() || matches!(scope_set, ScopeSet::Late(..)) {
                             return Some(Ok(binding));
                         }
@@ -710,7 +722,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             innermost_result = Some((binding, flags));
                         }
                     }
-                    Ok(..) | Err(Determinacy::Determined) => {}
+                    Err(Determinacy::Determined) => {}
                     Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,
                 }
 
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index e5df23a86cb..23f44ff1658 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -1029,13 +1029,14 @@ struct DeriveData {
 
 struct MacroData {
     ext: Arc<SyntaxExtension>,
+    attr_ext: Option<Arc<SyntaxExtension>>,
     nrules: usize,
     macro_rules: bool,
 }
 
 impl MacroData {
     fn new(ext: Arc<SyntaxExtension>) -> MacroData {
-        MacroData { ext, nrules: 0, macro_rules: false }
+        MacroData { ext, attr_ext: None, nrules: 0, macro_rules: false }
     }
 }
 
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index dae3c9dfad5..9173d0d3ea5 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -842,7 +842,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 }
                 _ => None,
             },
-            None => self.get_macro(res).map(|macro_data| Arc::clone(&macro_data.ext)),
+            None => self.get_macro(res).map(|macro_data| match kind {
+                Some(MacroKind::Attr) if let Some(ref ext) = macro_data.attr_ext => Arc::clone(ext),
+                _ => Arc::clone(&macro_data.ext),
+            }),
         };
         Ok((ext, res))
     }
@@ -1178,7 +1181,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         node_id: NodeId,
         edition: Edition,
     ) -> MacroData {
-        let (mut ext, mut nrules) = compile_declarative_macro(
+        let (mut ext, mut attr_ext, mut nrules) = compile_declarative_macro(
             self.tcx.sess,
             self.tcx.features(),
             macro_def,
@@ -1195,13 +1198,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 // The macro is a built-in, replace its expander function
                 // while still taking everything else from the source code.
                 ext.kind = builtin_ext_kind.clone();
+                attr_ext = None;
                 nrules = 0;
             } else {
                 self.dcx().emit_err(errors::CannotFindBuiltinMacroWithName { span, ident });
             }
         }
 
-        MacroData { ext: Arc::new(ext), nrules, macro_rules: macro_def.macro_rules }
+        MacroData { ext: Arc::new(ext), attr_ext, nrules, macro_rules: macro_def.macro_rules }
     }
 
     fn path_accessible(
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index 36197950221..5462ed38dd3 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -1311,6 +1311,7 @@ symbols! {
         lt,
         m68k_target_feature,
         macro_at_most_once_rep,
+        macro_attr,
         macro_attributes_in_derive_output,
         macro_concat,
         macro_escape,
diff --git a/compiler/rustc_target/src/spec/base/apple/mod.rs b/compiler/rustc_target/src/spec/base/apple/mod.rs
index aa6d1ec7009..da9f96ce37d 100644
--- a/compiler/rustc_target/src/spec/base/apple/mod.rs
+++ b/compiler/rustc_target/src/spec/base/apple/mod.rs
@@ -51,14 +51,14 @@ impl Arch {
         })
     }
 
-    fn target_cpu(self, abi: TargetAbi) -> &'static str {
+    fn target_cpu(self, env: TargetEnv) -> &'static str {
         match self {
             Armv7k => "cortex-a8",
             Armv7s => "swift", // iOS 10 is only supported on iPhone 5 or higher.
-            Arm64 => match abi {
-                TargetAbi::Normal => "apple-a7",
-                TargetAbi::Simulator => "apple-a12",
-                TargetAbi::MacCatalyst => "apple-a12",
+            Arm64 => match env {
+                TargetEnv::Normal => "apple-a7",
+                TargetEnv::Simulator => "apple-a12",
+                TargetEnv::MacCatalyst => "apple-a12",
             },
             Arm64e => "apple-a12",
             Arm64_32 => "apple-s4",
@@ -83,14 +83,14 @@ impl Arch {
 }
 
 #[derive(Copy, Clone, PartialEq)]
-pub(crate) enum TargetAbi {
+pub(crate) enum TargetEnv {
     Normal,
     Simulator,
     MacCatalyst,
 }
 
-impl TargetAbi {
-    fn target_abi(self) -> &'static str {
+impl TargetEnv {
+    fn target_env(self) -> &'static str {
         match self {
             Self::Normal => "",
             Self::MacCatalyst => "macabi",
@@ -104,13 +104,20 @@ impl TargetAbi {
 pub(crate) fn base(
     os: &'static str,
     arch: Arch,
-    abi: TargetAbi,
+    env: TargetEnv,
 ) -> (TargetOptions, StaticCow<str>, StaticCow<str>) {
     let mut opts = TargetOptions {
-        abi: abi.target_abi().into(),
         llvm_floatabi: Some(FloatAbi::Hard),
         os: os.into(),
-        cpu: arch.target_cpu(abi).into(),
+        env: env.target_env().into(),
+        // NOTE: We originally set `cfg(target_abi = "macabi")` / `cfg(target_abi = "sim")`,
+        // before it was discovered that those are actually environments:
+        // https://github.com/rust-lang/rust/issues/133331
+        //
+        // But let's continue setting them for backwards compatibility.
+        // FIXME(madsmtm): Warn about using these in the future.
+        abi: env.target_env().into(),
+        cpu: arch.target_cpu(env).into(),
         link_env_remove: link_env_remove(os),
         vendor: "apple".into(),
         linker_flavor: LinkerFlavor::Darwin(Cc::Yes, Lld::No),
@@ -168,14 +175,14 @@ pub(crate) fn base(
         // All Apple x86-32 targets have SSE2.
         opts.rustc_abi = Some(RustcAbi::X86Sse2);
     }
-    (opts, unversioned_llvm_target(os, arch, abi), arch.target_arch())
+    (opts, unversioned_llvm_target(os, arch, env), arch.target_arch())
 }
 
 /// Generate part of the LLVM target triple.
 ///
 /// See `rustc_codegen_ssa::back::versioned_llvm_target` for the full triple passed to LLVM and
 /// Clang.
-fn unversioned_llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<str> {
+fn unversioned_llvm_target(os: &str, arch: Arch, env: TargetEnv) -> StaticCow<str> {
     let arch = arch.target_name();
     // Convert to the "canonical" OS name used by LLVM:
     // https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L236-L282
@@ -187,10 +194,10 @@ fn unversioned_llvm_target(os: &str, arch: Arch, abi: TargetAbi) -> StaticCow<st
         "visionos" => "xros",
         _ => unreachable!("tried to get LLVM target OS for non-Apple platform"),
     };
-    let environment = match abi {
-        TargetAbi::Normal => "",
-        TargetAbi::MacCatalyst => "-macabi",
-        TargetAbi::Simulator => "-simulator",
+    let environment = match env {
+        TargetEnv::Normal => "",
+        TargetEnv::MacCatalyst => "-macabi",
+        TargetEnv::Simulator => "-simulator",
     };
     format!("{arch}-apple-{os}{environment}").into()
 }
@@ -309,7 +316,7 @@ impl OSVersion {
     /// This matches what LLVM does, see in part:
     /// <https://github.com/llvm/llvm-project/blob/llvmorg-18.1.8/llvm/lib/TargetParser/Triple.cpp#L1900-L1932>
     pub fn minimum_deployment_target(target: &Target) -> Self {
-        let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.abi) {
+        let (major, minor, patch) = match (&*target.os, &*target.arch, &*target.env) {
             ("macos", "aarch64", _) => (11, 0, 0),
             ("ios", "aarch64", "macabi") => (14, 0, 0),
             ("ios", "aarch64", "sim") => (14, 0, 0),
diff --git a/compiler/rustc_target/src/spec/base/apple/tests.rs b/compiler/rustc_target/src/spec/base/apple/tests.rs
index 391f3470104..bca86ce33c3 100644
--- a/compiler/rustc_target/src/spec/base/apple/tests.rs
+++ b/compiler/rustc_target/src/spec/base/apple/tests.rs
@@ -6,7 +6,7 @@ use crate::spec::targets::{
 };
 
 #[test]
-fn simulator_targets_set_abi() {
+fn simulator_targets_set_env() {
     let all_sim_targets = [
         x86_64_apple_ios::target(),
         x86_64_apple_tvos::target(),
@@ -18,7 +18,9 @@ fn simulator_targets_set_abi() {
     ];
 
     for target in &all_sim_targets {
-        assert_eq!(target.abi, "sim")
+        assert_eq!(target.env, "sim");
+        // Ensure backwards compat
+        assert_eq!(target.abi, "sim");
     }
 }
 
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
index 4dd39877715..e1960472555 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
index 769a7b6c391..3b522c34522 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
index 4bb2f73e4f9..4d6a3103ee3 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_macabi.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::MacCatalyst);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::MacCatalyst);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
index 7d04034e759..d366ed26482 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_ios_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
index ec92a40e255..7aef6f96e1c 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
index 74fbe5a89ca..f0d17db873b 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_tvos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
index dc595fbe7b6..22ce52e637f 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
index 06ff1bfb2f0..21739ba9fdb 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_visionos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("visionos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
index 23596271107..2e88f95f1dd 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
index bad9f6c1485..272dc682dc0 100644
--- a/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/aarch64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
index 4c3a2f43743..564ac2cd708 100644
--- a/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64_32_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Arm64_32, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
index 326f2b16d59..86e178a9572 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
index 01c6f0b888d..dae3f77d7ae 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
index cad3650bda1..a99fc5dc68c 100644
--- a/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/arm64e_apple_tvos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("tvos", Arch::Arm64e, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
index 8103d132cea..df58559848a 100644
--- a/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7k_apple_watchos.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("watchos", Arch::Armv7k, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
index ba9edd71461..63259043b73 100644
--- a/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/armv7s_apple_ios.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("ios", Arch::Armv7s, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
index 29865fcd4c4..a919be765a2 100644
--- a/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/i386_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // i386-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::I386, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
index d1339c57b00..96c477d5236 100644
--- a/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/i686_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::I686, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
index eba595ba7dd..53e2cb469ee 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetAbi::Normal);
+    let (opts, llvm_target, arch) = base("macos", Arch::X86_64, TargetEnv::Normal);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
index df45f430ecb..d74a688fa0f 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-ios is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
index ee0c2bf31cd..193e26f94c9 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_ios_macabi.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetAbi::MacCatalyst);
+    let (opts, llvm_target, arch) = base("ios", Arch::X86_64, TargetEnv::MacCatalyst);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
index 80ca80013f0..e69bd17a049 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_tvos.rs
@@ -1,10 +1,10 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
     // x86_64-apple-tvos is a simulator target, even though it isn't declared
     // that way in the target name like the other ones...
-    let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("tvos", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
index c503baedb8b..9490ca6aa36 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64_apple_watchos_sim.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetAbi::Simulator);
+    let (opts, llvm_target, arch) = base("watchos", Arch::X86_64, TargetEnv::Simulator);
     Target {
         llvm_target,
         metadata: TargetMetadata {
diff --git a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
index e64556c4132..67b5a160a89 100644
--- a/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
+++ b/compiler/rustc_target/src/spec/targets/x86_64h_apple_darwin.rs
@@ -1,8 +1,8 @@
-use crate::spec::base::apple::{Arch, TargetAbi, base};
+use crate::spec::base::apple::{Arch, TargetEnv, base};
 use crate::spec::{SanitizerSet, Target, TargetMetadata, TargetOptions};
 
 pub(crate) fn target() -> Target {
-    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetAbi::Normal);
+    let (mut opts, llvm_target, arch) = base("macos", Arch::X86_64h, TargetEnv::Normal);
     opts.max_atomic_width = Some(128);
     opts.supported_sanitizers =
         SanitizerSet::ADDRESS | SanitizerSet::CFI | SanitizerSet::LEAK | SanitizerSet::THREAD;
diff --git a/compiler/rustc_trait_selection/messages.ftl b/compiler/rustc_trait_selection/messages.ftl
index 8232da4df43..fcb25025087 100644
--- a/compiler/rustc_trait_selection/messages.ftl
+++ b/compiler/rustc_trait_selection/messages.ftl
@@ -171,8 +171,6 @@ trait_selection_fps_remove_ref = consider removing the reference
 trait_selection_fps_use_ref = consider using a reference
 trait_selection_fulfill_req_lifetime = the type `{$ty}` does not fulfill the required lifetime
 
-trait_selection_full_type_written = the full type name has been written to '{$path}'
-
 trait_selection_ignored_diagnostic_option = `{$option_name}` is ignored due to previous definition of `{$option_name}`
     .other_label = `{$option_name}` is first declared here
     .label = `{$option_name}` is already declared here
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index ed8229154a9..1c890821b1d 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -1930,7 +1930,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         &self,
         trace: &TypeTrace<'tcx>,
         terr: TypeError<'tcx>,
-        path: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Vec<TypeErrorAdditionalDiags> {
         let mut suggestions = Vec::new();
         let span = trace.cause.span;
@@ -2009,7 +2009,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         })
         | ObligationCauseCode::BlockTailExpression(.., source)) = code
             && let hir::MatchSource::TryDesugar(_) = source
-            && let Some((expected_ty, found_ty)) = self.values_str(trace.values, &trace.cause, path)
+            && let Some((expected_ty, found_ty)) =
+                self.values_str(trace.values, &trace.cause, long_ty_path)
         {
             suggestions.push(TypeErrorAdditionalDiags::TryCannotConvert {
                 found: found_ty.content(),
@@ -2139,11 +2140,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         &self,
         values: ValuePairs<'tcx>,
         cause: &ObligationCause<'tcx>,
-        file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(DiagStyledString, DiagStyledString)> {
         match values {
             ValuePairs::Regions(exp_found) => self.expected_found_str(exp_found),
-            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, file),
+            ValuePairs::Terms(exp_found) => self.expected_found_str_term(exp_found, long_ty_path),
             ValuePairs::Aliases(exp_found) => self.expected_found_str(exp_found),
             ValuePairs::ExistentialTraitRef(exp_found) => self.expected_found_str(exp_found),
             ValuePairs::ExistentialProjection(exp_found) => self.expected_found_str(exp_found),
@@ -2183,7 +2184,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
     fn expected_found_str_term(
         &self,
         exp_found: ty::error::ExpectedFound<ty::Term<'tcx>>,
-        path: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(DiagStyledString, DiagStyledString)> {
         let exp_found = self.resolve_vars_if_possible(exp_found);
         if exp_found.references_error() {
@@ -2200,11 +2201,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let exp_s = exp.content();
                 let fnd_s = fnd.content();
                 if exp_s.len() > len {
-                    let exp_s = self.tcx.short_string(expected, path);
+                    let exp_s = self.tcx.short_string(expected, long_ty_path);
                     exp = DiagStyledString::highlighted(exp_s);
                 }
                 if fnd_s.len() > len {
-                    let fnd_s = self.tcx.short_string(found, path);
+                    let fnd_s = self.tcx.short_string(found, long_ty_path);
                     fnd = DiagStyledString::highlighted(fnd_s);
                 }
                 (exp, fnd)
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
index 966f117a1bf..ec2287ed516 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/need_type_info.rs
@@ -436,8 +436,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -447,8 +445,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -458,8 +454,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label,
-                was_written: false,
-                path: Default::default(),
             }),
         }
     }
@@ -496,7 +490,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             return self.bad_inference_failure_err(failure_span, arg_data, error_code);
         };
 
-        let (source_kind, name, path) = kind.ty_localized_msg(self);
+        let (source_kind, name, long_ty_path) = kind.ty_localized_msg(self);
         let failure_span = if should_label_span && !failure_span.overlaps(span) {
             Some(failure_span)
         } else {
@@ -628,7 +622,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
             }
         }
-        match error_code {
+        let mut err = match error_code {
             TypeAnnotationNeeded::E0282 => self.dcx().create_err(AnnotationRequired {
                 span,
                 source_kind,
@@ -637,8 +631,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0283 => self.dcx().create_err(AmbiguousImpl {
                 span,
@@ -648,8 +640,6 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
             TypeAnnotationNeeded::E0284 => self.dcx().create_err(AmbiguousReturn {
                 span,
@@ -659,10 +649,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 infer_subdiags,
                 multi_suggestions,
                 bad_label: None,
-                was_written: path.is_some(),
-                path: path.unwrap_or_default(),
             }),
-        }
+        };
+        *err.long_ty_path() = long_ty_path;
+        err
     }
 }
 
@@ -726,22 +716,24 @@ impl<'tcx> InferSource<'tcx> {
 
 impl<'tcx> InferSourceKind<'tcx> {
     fn ty_localized_msg(&self, infcx: &InferCtxt<'tcx>) -> (&'static str, String, Option<PathBuf>) {
-        let mut path = None;
+        let mut long_ty_path = None;
         match *self {
             InferSourceKind::LetBinding { ty, .. }
             | InferSourceKind::ClosureArg { ty, .. }
             | InferSourceKind::ClosureReturn { ty, .. } => {
                 if ty.is_closure() {
-                    ("closure", closure_as_fn_str(infcx, ty), path)
+                    ("closure", closure_as_fn_str(infcx, ty), long_ty_path)
                 } else if !ty.is_ty_or_numeric_infer() {
-                    ("normal", infcx.tcx.short_string(ty, &mut path), path)
+                    ("normal", infcx.tcx.short_string(ty, &mut long_ty_path), long_ty_path)
                 } else {
-                    ("other", String::new(), path)
+                    ("other", String::new(), long_ty_path)
                 }
             }
             // FIXME: We should be able to add some additional info here.
             InferSourceKind::GenericArg { .. }
-            | InferSourceKind::FullyQualifiedMethodCall { .. } => ("other", String::new(), path),
+            | InferSourceKind::FullyQualifiedMethodCall { .. } => {
+                ("other", String::new(), long_ty_path)
+            }
         }
     }
 }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
index cdf1402252a..af912227ce4 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/ambiguity.rs
@@ -169,7 +169,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
         let predicate = self.resolve_vars_if_possible(obligation.predicate);
         let span = obligation.cause.span;
-        let mut file = None;
+        let mut long_ty_path = None;
 
         debug!(?predicate, obligation.cause.code = ?obligation.cause.code());
 
@@ -211,19 +211,18 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.tcx.as_lang_item(trait_pred.def_id()),
                     Some(LangItem::Sized | LangItem::MetaSized)
                 ) {
-                    match self.tainted_by_errors() {
-                        None => {
-                            let err = self.emit_inference_failure_err(
+                    return match self.tainted_by_errors() {
+                        None => self
+                            .emit_inference_failure_err(
                                 obligation.cause.body_id,
                                 span,
                                 trait_pred.self_ty().skip_binder().into(),
                                 TypeAnnotationNeeded::E0282,
                                 false,
-                            );
-                            return err.emit();
-                        }
-                        Some(e) => return e,
-                    }
+                            )
+                            .emit(),
+                        Some(e) => e,
+                    };
                 }
 
                 // Typically, this ambiguity should only happen if
@@ -260,8 +259,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         span,
                         E0283,
                         "type annotations needed: cannot satisfy `{}`",
-                        self.tcx.short_string(predicate, &mut file),
+                        self.tcx.short_string(predicate, &mut long_ty_path),
                     )
+                    .with_long_ty_path(long_ty_path)
                 };
 
                 let mut ambiguities = compute_applicable_impls_for_diagnostics(
@@ -307,7 +307,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         err.cancel();
                         return e;
                     }
-                    let pred = self.tcx.short_string(predicate, &mut file);
+                    let pred = self.tcx.short_string(predicate, &mut err.long_ty_path());
                     err.note(format!("cannot satisfy `{pred}`"));
                     let impl_candidates =
                         self.find_similar_impl_candidates(predicate.as_trait_clause().unwrap());
@@ -512,6 +512,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     true,
                 )
             }
+
             ty::PredicateKind::Clause(ty::ClauseKind::Projection(data)) => {
                 if let Err(e) = predicate.error_reported() {
                     return e;
@@ -536,7 +537,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     .filter_map(ty::GenericArg::as_term)
                     .chain([data.term])
                     .find(|g| g.has_non_region_infer());
-                let predicate = self.tcx.short_string(predicate, &mut file);
+                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                 if let Some(term) = term {
                     self.emit_inference_failure_err(
                         obligation.cause.body_id,
@@ -546,6 +547,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         true,
                     )
                     .with_note(format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 } else {
                     // If we can't find a generic parameter, just print a generic error
                     struct_span_code_err!(
@@ -555,6 +557,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         "type annotations needed: cannot satisfy `{predicate}`",
                     )
                     .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 }
             }
 
@@ -568,17 +571,16 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 let term =
                     data.walk().filter_map(ty::GenericArg::as_term).find(|term| term.is_infer());
                 if let Some(term) = term {
-                    let err = self.emit_inference_failure_err(
+                    self.emit_inference_failure_err(
                         obligation.cause.body_id,
                         span,
                         term,
                         TypeAnnotationNeeded::E0284,
                         true,
-                    );
-                    err
+                    )
                 } else {
                     // If we can't find a generic parameter, just print a generic error
-                    let predicate = self.tcx.short_string(predicate, &mut file);
+                    let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                     struct_span_code_err!(
                         self.dcx(),
                         span,
@@ -586,6 +588,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         "type annotations needed: cannot satisfy `{predicate}`",
                     )
                     .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                    .with_long_ty_path(long_ty_path)
                 }
             }
 
@@ -597,13 +600,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     TypeAnnotationNeeded::E0284,
                     true,
                 ),
+
             ty::PredicateKind::NormalizesTo(ty::NormalizesTo { alias, term })
                 if term.is_infer() =>
             {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
-                let alias = self.tcx.short_string(alias, &mut file);
+                let alias = self.tcx.short_string(alias, &mut long_ty_path);
                 struct_span_code_err!(
                     self.dcx(),
                     span,
@@ -611,37 +615,34 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "type annotations needed: cannot normalize `{alias}`",
                 )
                 .with_span_label(span, format!("cannot normalize `{alias}`"))
+                .with_long_ty_path(long_ty_path)
             }
+
             ty::PredicateKind::Clause(ty::ClauseKind::UnstableFeature(sym)) => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
 
-                let mut err;
-
                 if self.tcx.features().staged_api() {
-                    err = self.dcx().struct_span_err(
+                    self.dcx().struct_span_err(
                         span,
                         format!("unstable feature `{sym}` is used without being enabled."),
-                    );
-
-                    err.help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"));
+                    ).with_help(format!("The feature can be enabled by marking the current item with `#[unstable_feature_bound({sym})]`"))
                 } else {
-                    err = feature_err_unstable_feature_bound(
+                    feature_err_unstable_feature_bound(
                         &self.tcx.sess,
                         sym,
                         span,
                         format!("use of unstable library feature `{sym}`"),
-                    );
+                    )
                 }
-                err
             }
 
             _ => {
                 if let Some(e) = self.tainted_by_errors() {
                     return e;
                 }
-                let predicate = self.tcx.short_string(predicate, &mut file);
+                let predicate = self.tcx.short_string(predicate, &mut long_ty_path);
                 struct_span_code_err!(
                     self.dcx(),
                     span,
@@ -649,9 +650,9 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "type annotations needed: cannot satisfy `{predicate}`",
                 )
                 .with_span_label(span, format!("cannot satisfy `{predicate}`"))
+                .with_long_ty_path(long_ty_path)
             }
         };
-        *err.long_ty_path() = file;
         self.note_obligation_cause(&mut err, obligation);
         err.emit()
     }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
index a9e346a5cdb..62859329de3 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/fulfillment_errors.rs
@@ -208,16 +208,19 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                                      performs a conversion on the error value \
                                                      using the `From` trait";
                         let (message, notes, append_const_msg) = if is_try_conversion {
+                            let ty = self.tcx.short_string(
+                                main_trait_predicate.skip_binder().self_ty(),
+                                &mut long_ty_file,
+                            );
                             // We have a `-> Result<_, E1>` and `gives_E2()?`.
                             (
-                                Some(format!(
-                                    "`?` couldn't convert the error to `{}`",
-                                    main_trait_predicate.skip_binder().self_ty(),
-                                )),
+                                Some(format!("`?` couldn't convert the error to `{ty}`")),
                                 vec![question_mark_message.to_owned()],
                                 Some(AppendConstMessage::Default),
                             )
                         } else if is_question_mark {
+                            let main_trait_predicate =
+                                self.tcx.short_string(main_trait_predicate, &mut long_ty_file);
                             // Similar to the case above, but in this case the conversion is for a
                             // trait object: `-> Result<_, Box<dyn Error>` and `gives_E()?` when
                             // `E: Error` isn't met.
@@ -233,7 +236,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             (message, notes, append_const_msg)
                         };
 
-                        let err_msg = self.get_standard_error_message(
+                        let default_err_msg = || self.get_standard_error_message(
                             main_trait_predicate,
                             message,
                             None,
@@ -258,7 +261,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                     );
                                 }
                                 GetSafeTransmuteErrorAndReason::Default => {
-                                    (err_msg, None)
+                                    (default_err_msg(), None)
                                 }
                                 GetSafeTransmuteErrorAndReason::Error {
                                     err_msg,
@@ -266,7 +269,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 } => (err_msg, safe_transmute_explanation),
                             }
                         } else {
-                            (err_msg, None)
+                            (default_err_msg(), None)
                         };
 
                         let mut err = struct_span_code_err!(self.dcx(), span, E0277, "{}", err_msg);
@@ -279,15 +282,21 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                         if let Some(ret_span) = self.return_type_span(&obligation) {
                             if is_try_conversion {
+                                let ty = self.tcx.short_string(
+                                    main_trait_predicate.skip_binder().self_ty(),
+                                    err.long_ty_path(),
+                                );
                                 err.span_label(
                                     ret_span,
-                                    format!(
-                                        "expected `{}` because of this",
-                                        main_trait_predicate.skip_binder().self_ty()
-                                    ),
+                                    format!("expected `{ty}` because of this"),
                                 );
                             } else if is_question_mark {
-                                err.span_label(ret_span, format!("required `{main_trait_predicate}` because of this"));
+                                let main_trait_predicate =
+                                    self.tcx.short_string(main_trait_predicate, err.long_ty_path());
+                                err.span_label(
+                                    ret_span,
+                                    format!("required `{main_trait_predicate}` because of this"),
+                                );
                             }
                         }
 
@@ -303,6 +312,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             &obligation,
                             leaf_trait_predicate,
                             pre_message,
+                            err.long_ty_path(),
                         );
 
                         self.check_for_binding_assigned_block_without_tail_expression(
@@ -414,11 +424,12 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                 } else {
                                     vec![(span.shrink_to_hi(), format!(" as {}", cand.self_ty()))]
                                 };
+                                let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
+                                let ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
                                 err.multipart_suggestion(
                                     format!(
-                                        "the trait `{}` is implemented for fn pointer `{}`, try casting using `as`",
-                                        cand.print_trait_sugared(),
-                                        cand.self_ty(),
+                                        "the trait `{trait_}` is implemented for fn pointer \
+                                         `{ty}`, try casting using `as`",
                                     ),
                                     suggestion,
                                     Applicability::MaybeIncorrect,
@@ -522,7 +533,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                                     <https://github.com/rust-lang/rust/issues/48950> \
                                     for more information)",
                                 );
-                                err.help("did you intend to use the type `()` here instead?");
+                                err.help("you might have intended to use the type `()` here instead");
                             }
                         }
 
@@ -722,10 +733,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             }
 
             SelectionError::ConstArgHasWrongType { ct, ct_ty, expected_ty } => {
+                let expected_ty_str = self.tcx.short_string(expected_ty, &mut long_ty_file);
+                let ct_str = self.tcx.short_string(ct, &mut long_ty_file);
                 let mut diag = self.dcx().struct_span_err(
                     span,
-                    format!("the constant `{ct}` is not of type `{expected_ty}`"),
+                    format!("the constant `{ct_str}` is not of type `{expected_ty_str}`"),
                 );
+                diag.long_ty_path = long_ty_file;
 
                 self.note_type_err(
                     &mut diag,
@@ -1118,9 +1132,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .must_apply_modulo_regions()
             {
                 if !suggested {
+                    let err_ty = self.tcx.short_string(err_ty, err.long_ty_path());
                     err.span_label(span, format!("this has type `Result<_, {err_ty}>`"));
                 }
             } else {
+                let err_ty = self.tcx.short_string(err_ty, err.long_ty_path());
                 err.span_label(
                     span,
                     format!(
@@ -1156,12 +1172,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
             }
             (ty::Adt(def, _), None) if def.did().is_local() => {
+                let trait_path = self.tcx.short_string(
+                    trait_pred.skip_binder().trait_ref.print_only_trait_path(),
+                    err.long_ty_path(),
+                );
                 err.span_note(
                     self.tcx.def_span(def.did()),
-                    format!(
-                        "`{self_ty}` needs to implement `{}`",
-                        trait_pred.skip_binder().trait_ref.print_only_trait_path(),
-                    ),
+                    format!("`{self_ty}` needs to implement `{trait_path}`"),
                 );
             }
             (ty::Adt(def, _), Some(ty)) if def.did().is_local() => {
@@ -1195,13 +1212,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
             bug!()
         };
 
+        let mut file = None;
+        let ty_str = self.tcx.short_string(ty, &mut file);
         let mut diag = match ty.kind() {
             ty::Float(_) => {
                 struct_span_code_err!(
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` is forbidden as the type of a const generic parameter",
+                    "`{ty_str}` is forbidden as the type of a const generic parameter",
                 )
             }
             ty::FnPtr(..) => {
@@ -1226,7 +1245,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
+                    "`{ty_str}` must implement `ConstParamTy` to be used as the type of a const generic parameter",
                 );
                 // Only suggest derive if this isn't a derived obligation,
                 // and the struct is local.
@@ -1258,21 +1277,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     self.dcx(),
                     span,
                     E0741,
-                    "`{ty}` can't be used as a const parameter type",
+                    "`{ty_str}` can't be used as a const parameter type",
                 )
             }
         };
+        diag.long_ty_path = file;
 
         let mut code = obligation.cause.code();
         let mut pred = obligation.predicate.as_trait_clause();
         while let Some((next_code, next_pred)) = code.parent_with_predicate() {
             if let Some(pred) = pred {
                 self.enter_forall(pred, |pred| {
-                    diag.note(format!(
-                        "`{}` must implement `{}`, but it does not",
-                        pred.self_ty(),
-                        pred.print_modifiers_and_trait_path()
-                    ));
+                    let ty = self.tcx.short_string(pred.self_ty(), diag.long_ty_path());
+                    let trait_path = self
+                        .tcx
+                        .short_string(pred.print_modifiers_and_trait_path(), diag.long_ty_path());
+                    diag.note(format!("`{ty}` must implement `{trait_path}`, but it does not"));
                 })
             }
             code = next_code;
@@ -1584,7 +1604,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         projection_term: ty::AliasTerm<'tcx>,
         normalized_ty: ty::Term<'tcx>,
         expected_ty: ty::Term<'tcx>,
-        file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> Option<(String, Span, Option<Span>)> {
         let trait_def_id = projection_term.trait_def_id(self.tcx);
         let self_ty = projection_term.self_ty();
@@ -1624,17 +1644,25 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 };
                 let item = match self_ty.kind() {
                     ty::FnDef(def, _) => self.tcx.item_name(*def).to_string(),
-                    _ => self.tcx.short_string(self_ty, file),
+                    _ => self.tcx.short_string(self_ty, long_ty_path),
                 };
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{item}` to return `{expected_ty}`, but it returns `{normalized_ty}`",
                 ), span, closure_span))
             } else if self.tcx.is_lang_item(trait_def_id, LangItem::Future) {
+                let self_ty = self.tcx.short_string(self_ty, long_ty_path);
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{self_ty}` to be a future that resolves to `{expected_ty}`, but it \
                      resolves to `{normalized_ty}`"
                 ), span, None))
             } else if Some(trait_def_id) == self.tcx.get_diagnostic_item(sym::Iterator) {
+                let self_ty = self.tcx.short_string(self_ty, long_ty_path);
+                let expected_ty = self.tcx.short_string(expected_ty, long_ty_path);
+                let normalized_ty = self.tcx.short_string(normalized_ty, long_ty_path);
                 Some((format!(
                     "expected `{self_ty}` to be an iterator that yields `{expected_ty}`, but it \
                      yields `{normalized_ty}`"
@@ -2097,12 +2125,15 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
 
                     if let [TypeError::Sorts(exp_found)] = &terrs[..] {
                         let exp_found = self.resolve_vars_if_possible(*exp_found);
+                        let expected =
+                            self.tcx.short_string(exp_found.expected, err.long_ty_path());
+                        let found = self.tcx.short_string(exp_found.found, err.long_ty_path());
                         err.highlighted_help(vec![
                             StringPart::normal("for that trait implementation, "),
                             StringPart::normal("expected `"),
-                            StringPart::highlighted(exp_found.expected.to_string()),
+                            StringPart::highlighted(expected),
                             StringPart::normal("`, found `"),
-                            StringPart::highlighted(exp_found.found.to_string()),
+                            StringPart::highlighted(found),
                             StringPart::normal("`"),
                         ]);
                         self.suggest_function_pointers_impl(None, &exp_found, err);
@@ -2135,11 +2166,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         (ty::FnPtr(..), _) => (" implemented for fn pointer `", ""),
                         _ => (" implemented for `", ""),
                     };
+                let trait_ = self.tcx.short_string(cand.print_trait_sugared(), err.long_ty_path());
+                let self_ty = self.tcx.short_string(cand.self_ty(), err.long_ty_path());
                 err.highlighted_help(vec![
-                    StringPart::normal(format!("the trait `{}` ", cand.print_trait_sugared())),
+                    StringPart::normal(format!("the trait `{trait_}` ",)),
                     StringPart::highlighted("is"),
                     StringPart::normal(desc),
-                    StringPart::highlighted(cand.self_ty().to_string()),
+                    StringPart::highlighted(self_ty),
                     StringPart::normal("`"),
                     StringPart::normal(mention_castable),
                 ]);
@@ -2159,9 +2192,13 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 .into_iter()
                 .map(|c| {
                     if all_traits_equal {
-                        format!("\n  {}", c.self_ty())
+                        format!("\n  {}", self.tcx.short_string(c.self_ty(), err.long_ty_path()))
                     } else {
-                        format!("\n  `{}` implements `{}`", c.self_ty(), c.print_only_trait_path())
+                        format!(
+                            "\n  `{}` implements `{}`",
+                            self.tcx.short_string(c.self_ty(), err.long_ty_path()),
+                            self.tcx.short_string(c.print_only_trait_path(), err.long_ty_path()),
+                        )
                     }
                 })
                 .collect();
@@ -2477,7 +2514,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
         predicate_constness: Option<ty::BoundConstness>,
         append_const_msg: Option<AppendConstMessage>,
         post_message: String,
-        long_ty_file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> String {
         message
             .and_then(|cannot_do_this| {
@@ -2503,7 +2540,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     "the trait bound `{}` is not satisfied{post_message}",
                     self.tcx.short_string(
                         trait_predicate.print_with_bound_constness(predicate_constness),
-                        long_ty_file,
+                        long_ty_path,
                     ),
                 )
             })
@@ -2608,8 +2645,8 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             dst_min_align,
                         } => {
                             format!(
-                                "the minimum alignment of `{src}` ({src_min_align}) should \
-                        be greater than that of `{dst}` ({dst_min_align})"
+                                "the minimum alignment of `{src}` ({src_min_align}) should be \
+                                 greater than that of `{dst}` ({dst_min_align})"
                             )
                         }
                         rustc_transmute::Reason::DstIsMoreUnique => {
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
index 5765dfd891d..bb5c6469f34 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/on_unimplemented.rs
@@ -99,7 +99,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
         &self,
         trait_pred: ty::PolyTraitPredicate<'tcx>,
         obligation: &PredicateObligation<'tcx>,
-        long_ty_file: &mut Option<PathBuf>,
+        long_ty_path: &mut Option<PathBuf>,
     ) -> OnUnimplementedNote {
         if trait_pred.polarity() != ty::PredicatePolarity::Positive {
             return OnUnimplementedNote::default();
@@ -281,7 +281,7 @@ impl<'tcx> TypeErrCtxt<'_, 'tcx> {
                     GenericParamDefKind::Type { .. } | GenericParamDefKind::Const { .. } => {
                         if let Some(ty) = trait_pred.trait_ref.args[param.index as usize].as_type()
                         {
-                            self.tcx.short_string(ty, long_ty_file)
+                            self.tcx.short_string(ty, long_ty_path)
                         } else {
                             trait_pred.trait_ref.args[param.index as usize].to_string()
                         }
diff --git a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
index 718cff6d135..374e1f67930 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/traits/suggestions.rs
@@ -3,6 +3,7 @@
 use std::assert_matches::debug_assert_matches;
 use std::borrow::Cow;
 use std::iter;
+use std::path::PathBuf;
 
 use itertools::{EitherOrBoth, Itertools};
 use rustc_abi::ExternAbi;
@@ -1369,6 +1370,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 );
                 let self_ty_str =
                     self.tcx.short_string(old_pred.self_ty().skip_binder(), err.long_ty_path());
+                let trait_path = self
+                    .tcx
+                    .short_string(old_pred.print_modifiers_and_trait_path(), err.long_ty_path());
+
                 if has_custom_message {
                     err.note(msg);
                 } else {
@@ -1376,10 +1381,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 err.span_label(
                     span,
-                    format!(
-                        "the trait `{}` is not implemented for `{self_ty_str}`",
-                        old_pred.print_modifiers_and_trait_path()
-                    ),
+                    format!("the trait `{trait_path}` is not implemented for `{self_ty_str}`"),
                 );
             };
 
@@ -3333,17 +3335,22 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                     tcx.async_fn_trait_kind_from_def_id(data.parent_trait_pred.def_id()).is_some();
 
                 if !is_upvar_tys_infer_tuple && !is_builtin_async_fn_trait {
-                    let ty_str = tcx.short_string(ty, err.long_ty_path());
-                    let msg = format!("required because it appears within the type `{ty_str}`");
+                    let mut msg = || {
+                        let ty_str = tcx.short_string(ty, err.long_ty_path());
+                        format!("required because it appears within the type `{ty_str}`")
+                    };
                     match ty.kind() {
-                        ty::Adt(def, _) => match tcx.opt_item_ident(def.did()) {
-                            Some(ident) => {
-                                err.span_note(ident.span, msg);
-                            }
-                            None => {
-                                err.note(msg);
+                        ty::Adt(def, _) => {
+                            let msg = msg();
+                            match tcx.opt_item_ident(def.did()) {
+                                Some(ident) => {
+                                    err.span_note(ident.span, msg);
+                                }
+                                None => {
+                                    err.note(msg);
+                                }
                             }
-                        },
+                        }
                         ty::Alias(ty::Opaque, ty::AliasTy { def_id, .. }) => {
                             // If the previous type is async fn, this is the future generated by the body of an async function.
                             // Avoid printing it twice (it was already printed in the `ty::Coroutine` arm below).
@@ -3363,6 +3370,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             {
                                 // See comment above; skip printing twice.
                             } else {
+                                let msg = msg();
                                 err.span_note(tcx.def_span(def_id), msg);
                             }
                         }
@@ -3392,6 +3400,7 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                             err.note("`str` is considered to contain a `[u8]` slice for auto trait purposes");
                         }
                         _ => {
+                            let msg = msg();
                             err.note(msg);
                         }
                     };
@@ -3441,7 +3450,10 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 }
                 let self_ty_str =
                     tcx.short_string(parent_trait_pred.skip_binder().self_ty(), err.long_ty_path());
-                let trait_name = parent_trait_pred.print_modifiers_and_trait_path().to_string();
+                let trait_name = tcx.short_string(
+                    parent_trait_pred.print_modifiers_and_trait_path(),
+                    err.long_ty_path(),
+                );
                 let msg = format!("required for `{self_ty_str}` to implement `{trait_name}`");
                 let mut is_auto_trait = false;
                 match tcx.hir_get_if_local(data.impl_or_alias_def_id) {
@@ -3539,10 +3551,11 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                         parent_trait_pred.skip_binder().self_ty(),
                         err.long_ty_path(),
                     );
-                    err.note(format!(
-                        "required for `{self_ty}` to implement `{}`",
-                        parent_trait_pred.print_modifiers_and_trait_path()
-                    ));
+                    let trait_path = tcx.short_string(
+                        parent_trait_pred.print_modifiers_and_trait_path(),
+                        err.long_ty_path(),
+                    );
+                    err.note(format!("required for `{self_ty}` to implement `{trait_path}`"));
                 }
                 // #74711: avoid a stack overflow
                 ensure_sufficient_stack(|| {
@@ -3558,15 +3571,20 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
                 });
             }
             ObligationCauseCode::ImplDerivedHost(ref data) => {
-                let self_ty =
-                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty());
-                let msg = format!(
-                    "required for `{self_ty}` to implement `{} {}`",
-                    data.derived.parent_host_pred.skip_binder().constness,
+                let self_ty = tcx.short_string(
+                    self.resolve_vars_if_possible(data.derived.parent_host_pred.self_ty()),
+                    err.long_ty_path(),
+                );
+                let trait_path = tcx.short_string(
                     data.derived
                         .parent_host_pred
                         .map_bound(|pred| pred.trait_ref)
                         .print_only_trait_path(),
+                    err.long_ty_path(),
+                );
+                let msg = format!(
+                    "required for `{self_ty}` to implement `{} {trait_path}`",
+                    data.derived.parent_host_pred.skip_binder().constness,
                 );
                 match tcx.hir_get_if_local(data.impl_def_id) {
                     Some(Node::Item(hir::Item {
@@ -5351,6 +5369,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
     obligation: &PredicateObligation<'tcx>,
     trait_predicate: ty::PolyTraitPredicate<'tcx>,
     pre_message: String,
+    long_ty_path: &mut Option<PathBuf>,
 ) -> String {
     if let ObligationCauseCode::MainFunctionType = obligation.cause.code() {
         "consider using `()`, or a `Result`".to_owned()
@@ -5369,7 +5388,7 @@ pub(super) fn get_explanation_based_on_obligation<'tcx>(
             format!(
                 "{pre_message}the trait `{}` is not implemented for{desc} `{}`",
                 trait_predicate.print_modifiers_and_trait_path(),
-                tcx.short_string(trait_predicate.self_ty().skip_binder(), &mut None),
+                tcx.short_string(trait_predicate.self_ty().skip_binder(), long_ty_path),
             )
         } else {
             // "the trait bound `T: !Send` is not satisfied" reads better than "`!Send` is
diff --git a/compiler/rustc_trait_selection/src/errors.rs b/compiler/rustc_trait_selection/src/errors.rs
index 7901d52dffb..af241099c01 100644
--- a/compiler/rustc_trait_selection/src/errors.rs
+++ b/compiler/rustc_trait_selection/src/errors.rs
@@ -1,5 +1,3 @@
-use std::path::PathBuf;
-
 use rustc_ast::Path;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_errors::codes::*;
@@ -224,9 +222,6 @@ pub struct AnnotationRequired<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0283
@@ -245,9 +240,6 @@ pub struct AmbiguousImpl<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Copy of `AnnotationRequired` for E0284
@@ -266,9 +258,6 @@ pub struct AmbiguousReturn<'a> {
     pub infer_subdiags: Vec<SourceKindSubdiag<'a>>,
     #[subdiagnostic]
     pub multi_suggestions: Vec<SourceKindMultiSuggestion<'a>>,
-    #[note(trait_selection_full_type_written)]
-    pub was_written: bool,
-    pub path: PathBuf,
 }
 
 // Used when a better one isn't available
diff --git a/compiler/rustc_type_ir/src/binder.rs b/compiler/rustc_type_ir/src/binder.rs
index 189afa32852..10d48526fd2 100644
--- a/compiler/rustc_type_ir/src/binder.rs
+++ b/compiler/rustc_type_ir/src/binder.rs
@@ -15,13 +15,12 @@ use crate::lift::Lift;
 use crate::visit::{Flags, TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::{self as ty, Interner};
 
-/// Binder is a binder for higher-ranked lifetimes or types. It is part of the
+/// `Binder` is a binder for higher-ranked lifetimes or types. It is part of the
 /// compiler's representation for things like `for<'a> Fn(&'a isize)`
-/// (which would be represented by the type `PolyTraitRef ==
-/// Binder<I, TraitRef>`). Note that when we instantiate,
-/// erase, or otherwise "discharge" these bound vars, we change the
-/// type from `Binder<I, T>` to just `T` (see
-/// e.g., `liberate_late_bound_regions`).
+/// (which would be represented by the type `PolyTraitRef == Binder<I, TraitRef>`).
+///
+/// See <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
+/// for more details.
 ///
 /// `Decodable` and `Encodable` are implemented for `Binder<T>` using the `impl_binder_encode_decode!` macro.
 #[derive_where(Clone; I: Interner, T: Clone)]
@@ -154,22 +153,19 @@ impl<I: Interner, T: TypeVisitable<I>> TypeSuperVisitable<I> for Binder<I, T> {
 }
 
 impl<I: Interner, T> Binder<I, T> {
-    /// Skips the binder and returns the "bound" value. This is a
-    /// risky thing to do because it's easy to get confused about
-    /// De Bruijn indices and the like. It is usually better to
-    /// discharge the binder using `no_bound_vars` or
-    /// `instantiate_bound_regions` or something like
-    /// that. `skip_binder` is only valid when you are either
-    /// extracting data that has nothing to do with bound vars, you
-    /// are doing some sort of test that does not involve bound
-    /// regions, or you are being very careful about your depth
-    /// accounting.
+    /// Returns the value contained inside of this `for<'a>`. Accessing generic args
+    /// in the returned value is generally incorrect.
+    ///
+    /// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/instantiating_binders.html>
+    /// before using this function. It is usually better to discharge the binder using
+    /// `no_bound_vars` or `instantiate_bound_regions` or something like that.
     ///
-    /// Some examples where `skip_binder` is reasonable:
+    /// `skip_binder` is only valid when you are either extracting data that does not reference
+    /// any generic arguments, e.g. a `DefId`, or when you're making sure you only pass the
+    /// value to things which can handle escaping bound vars.
     ///
-    /// - extracting the `DefId` from a PolyTraitRef;
-    /// - comparing the self type of a PolyTraitRef to see if it is equal to
-    ///   a type parameter `X`, since the type `X` does not reference any regions
+    /// See existing uses of `.skip_binder()` in `rustc_trait_selection::traits::select`
+    /// or `rustc_next_trait_solver` for examples.
     pub fn skip_binder(self) -> T {
         self.value
     }
@@ -355,12 +351,11 @@ impl<I: Interner> TypeVisitor<I> for ValidateBoundVars<I> {
     }
 }
 
-/// Similar to [`super::Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
+/// Similar to [`Binder`] except that it tracks early bound generics, i.e. `struct Foo<T>(T)`
 /// needs `T` instantiated immediately. This type primarily exists to avoid forgetting to call
 /// `instantiate`.
 ///
-/// If you don't have anything to `instantiate`, you may be looking for
-/// [`instantiate_identity`](EarlyBinder::instantiate_identity) or [`skip_binder`](EarlyBinder::skip_binder).
+/// See <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html> for more details.
 #[derive_where(Clone; I: Interner, T: Clone)]
 #[derive_where(Copy; I: Interner, T: Copy)]
 #[derive_where(PartialEq; I: Interner, T: PartialEq)]
@@ -423,17 +418,22 @@ impl<I: Interner, T> EarlyBinder<I, T> {
         EarlyBinder { value, _tcx: PhantomData }
     }
 
-    /// Skips the binder and returns the "bound" value.
-    /// This can be used to extract data that does not depend on generic parameters
-    /// (e.g., getting the `DefId` of the inner value or getting the number of
-    /// arguments of an `FnSig`). Otherwise, consider using
-    /// [`instantiate_identity`](EarlyBinder::instantiate_identity).
+    /// Skips the binder and returns the "bound" value. Accessing generic args
+    /// in the returned value is generally incorrect.
+    ///
+    /// Please read <https://rustc-dev-guide.rust-lang.org/ty_module/early_binder.html>
+    /// before using this function.
+    ///
+    /// Only use this to extract data that does not depend on generic parameters, e.g.
+    /// to get the `DefId` of the inner value or the number of arguments ofan `FnSig`,
+    /// or while making sure to only pass the value to functions which are explicitly
+    /// set up to handle these uninstantiated generic parameters.
     ///
     /// To skip the binder on `x: &EarlyBinder<I, T>` to obtain `&T`, leverage
     /// [`EarlyBinder::as_ref`](EarlyBinder::as_ref): `x.as_ref().skip_binder()`.
     ///
-    /// See also [`Binder::skip_binder`](super::Binder::skip_binder), which is
-    /// the analogous operation on [`super::Binder`].
+    /// See also [`Binder::skip_binder`](Binder::skip_binder), which is
+    /// the analogous operation on [`Binder`].
     pub fn skip_binder(self) -> T {
         self.value
     }
diff --git a/library/core/src/intrinsics/mod.rs b/library/core/src/intrinsics/mod.rs
index 05b0522c202..7228ad0ed6d 100644
--- a/library/core/src/intrinsics/mod.rs
+++ b/library/core/src/intrinsics/mod.rs
@@ -150,69 +150,63 @@ pub unsafe fn atomic_xchg<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src:
 
 /// Adds to the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_add` method. For example, [`AtomicIsize::fetch_add`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xadd<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xadd<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Subtract from the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_sub` method. For example, [`AtomicIsize::fetch_sub`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xsub<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xsub<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise and with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_and` method. For example, [`AtomicBool::fetch_and`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_and<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_and<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise nand with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`AtomicBool`] type via the `fetch_nand` method. For example, [`AtomicBool::fetch_nand`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_nand<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_nand<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise or with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_or` method. For example, [`AtomicBool::fetch_or`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_or<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_or<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Bitwise xor with the current value, returning the previous value.
 /// `T` must be an integer or pointer type.
-/// If `T` is a pointer type, the provenance of `src` is ignored: both the return value and the new
-/// value stored at `*dst` will have the provenance of the old value stored there.
+/// `U` must be the same as `T` if that is an integer type, or `usize` if `T` is a pointer type.
 ///
 /// The stabilized version of this intrinsic is available on the
 /// [`atomic`] types via the `fetch_xor` method. For example, [`AtomicBool::fetch_xor`].
 #[rustc_intrinsic]
 #[rustc_nounwind]
-pub unsafe fn atomic_xor<T: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+pub unsafe fn atomic_xor<T: Copy, U: Copy, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 /// Maximum with the current value using a signed comparison.
 /// `T` must be a signed integer type.
diff --git a/library/core/src/sync/atomic.rs b/library/core/src/sync/atomic.rs
index 70c02ead358..44a6895f90a 100644
--- a/library/core/src/sync/atomic.rs
+++ b/library/core/src/sync/atomic.rs
@@ -2293,7 +2293,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_byte_add(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_add(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_add(self.p.get(), val, order).cast() }
     }
 
     /// Offsets the pointer's address by subtracting `val` *bytes*, returning the
@@ -2318,9 +2318,10 @@ impl<T> AtomicPtr<T> {
     /// #![feature(strict_provenance_atomic_ptr)]
     /// use core::sync::atomic::{AtomicPtr, Ordering};
     ///
-    /// let atom = AtomicPtr::<i64>::new(core::ptr::without_provenance_mut(1));
-    /// assert_eq!(atom.fetch_byte_sub(1, Ordering::Relaxed).addr(), 1);
-    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), 0);
+    /// let mut arr = [0i64, 1];
+    /// let atom = AtomicPtr::<i64>::new(&raw mut arr[1]);
+    /// assert_eq!(atom.fetch_byte_sub(8, Ordering::Relaxed).addr(), (&raw const arr[1]).addr());
+    /// assert_eq!(atom.load(Ordering::Relaxed).addr(), (&raw const arr[0]).addr());
     /// ```
     #[inline]
     #[cfg(target_has_atomic = "ptr")]
@@ -2328,7 +2329,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_byte_sub(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_sub(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_sub(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "or" operation on the address of the current pointer,
@@ -2379,7 +2380,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_or(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_or(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_or(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "and" operation on the address of the current
@@ -2429,7 +2430,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_and(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_and(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_and(self.p.get(), val, order).cast() }
     }
 
     /// Performs a bitwise "xor" operation on the address of the current
@@ -2477,7 +2478,7 @@ impl<T> AtomicPtr<T> {
     #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
     pub fn fetch_xor(&self, val: usize, order: Ordering) -> *mut T {
         // SAFETY: data races are prevented by atomic intrinsics.
-        unsafe { atomic_xor(self.p.get(), core::ptr::without_provenance_mut(val), order).cast() }
+        unsafe { atomic_xor(self.p.get(), val, order).cast() }
     }
 
     /// Returns a mutable pointer to the underlying pointer.
@@ -3981,15 +3982,15 @@ unsafe fn atomic_swap<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_add<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_add`.
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_xadd::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_xadd::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xadd::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xadd::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_xadd::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_xadd::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_xadd::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xadd::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xadd::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_xadd::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -3998,15 +3999,15 @@ unsafe fn atomic_add<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_sub<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_sub<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_sub`.
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_xsub::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_xsub::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xsub::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xsub::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_xsub::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_xsub::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_xsub::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xsub::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xsub::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_xsub::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4147,15 +4148,15 @@ unsafe fn atomic_compare_exchange_weak<T: Copy>(
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_and<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_and`
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_and::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_and::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_and::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_and::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_and::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_and::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_and::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_and::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_and::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_and::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4163,15 +4164,15 @@ unsafe fn atomic_and<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_nand<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_nand`
     unsafe {
         match order {
-            Relaxed => intrinsics::atomic_nand::<T, { AO::Relaxed }>(dst, val),
-            Acquire => intrinsics::atomic_nand::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_nand::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_nand::<T, { AO::AcqRel }>(dst, val),
-            SeqCst => intrinsics::atomic_nand::<T, { AO::SeqCst }>(dst, val),
+            Relaxed => intrinsics::atomic_nand::<T, U, { AO::Relaxed }>(dst, val),
+            Acquire => intrinsics::atomic_nand::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_nand::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_nand::<T, U, { AO::AcqRel }>(dst, val),
+            SeqCst => intrinsics::atomic_nand::<T, U, { AO::SeqCst }>(dst, val),
         }
     }
 }
@@ -4179,15 +4180,15 @@ unsafe fn atomic_nand<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_or<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_or`
     unsafe {
         match order {
-            SeqCst => intrinsics::atomic_or::<T, { AO::SeqCst }>(dst, val),
-            Acquire => intrinsics::atomic_or::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_or::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_or::<T, { AO::AcqRel }>(dst, val),
-            Relaxed => intrinsics::atomic_or::<T, { AO::Relaxed }>(dst, val),
+            SeqCst => intrinsics::atomic_or::<T, U, { AO::SeqCst }>(dst, val),
+            Acquire => intrinsics::atomic_or::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_or::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_or::<T, U, { AO::AcqRel }>(dst, val),
+            Relaxed => intrinsics::atomic_or::<T, U, { AO::Relaxed }>(dst, val),
         }
     }
 }
@@ -4195,15 +4196,15 @@ unsafe fn atomic_or<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
 #[inline]
 #[cfg(target_has_atomic)]
 #[cfg_attr(miri, track_caller)] // even without panics, this helps for Miri backtraces
-unsafe fn atomic_xor<T: Copy>(dst: *mut T, val: T, order: Ordering) -> T {
+unsafe fn atomic_xor<T: Copy, U: Copy>(dst: *mut T, val: U, order: Ordering) -> T {
     // SAFETY: the caller must uphold the safety contract for `atomic_xor`
     unsafe {
         match order {
-            SeqCst => intrinsics::atomic_xor::<T, { AO::SeqCst }>(dst, val),
-            Acquire => intrinsics::atomic_xor::<T, { AO::Acquire }>(dst, val),
-            Release => intrinsics::atomic_xor::<T, { AO::Release }>(dst, val),
-            AcqRel => intrinsics::atomic_xor::<T, { AO::AcqRel }>(dst, val),
-            Relaxed => intrinsics::atomic_xor::<T, { AO::Relaxed }>(dst, val),
+            SeqCst => intrinsics::atomic_xor::<T, U, { AO::SeqCst }>(dst, val),
+            Acquire => intrinsics::atomic_xor::<T, U, { AO::Acquire }>(dst, val),
+            Release => intrinsics::atomic_xor::<T, U, { AO::Release }>(dst, val),
+            AcqRel => intrinsics::atomic_xor::<T, U, { AO::AcqRel }>(dst, val),
+            Relaxed => intrinsics::atomic_xor::<T, U, { AO::Relaxed }>(dst, val),
         }
     }
 }
diff --git a/src/doc/rustc/src/platform-support/apple-ios-macabi.md b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
index d4b71dbd4f4..c6f68f7a1e8 100644
--- a/src/doc/rustc/src/platform-support/apple-ios-macabi.md
+++ b/src/doc/rustc/src/platform-support/apple-ios-macabi.md
@@ -56,6 +56,17 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios-macabi your-code.rs
 ```
 
+The target can be differentiated from the iOS targets with the
+`target_env = "macabi"` cfg (or `target_abi = "macabi"` before Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(target_env = "macabi") {
+    // Do something only on Mac Catalyst.
+}
+```
+
+This is similar to the `TARGET_OS_MACCATALYST` define in C code.
+
 ## Testing
 
 Mac Catalyst binaries can be run directly on macOS 10.15 Catalina or newer.
diff --git a/src/doc/rustc/src/platform-support/apple-ios.md b/src/doc/rustc/src/platform-support/apple-ios.md
index 64325554ab6..586afa65226 100644
--- a/src/doc/rustc/src/platform-support/apple-ios.md
+++ b/src/doc/rustc/src/platform-support/apple-ios.md
@@ -66,6 +66,20 @@ Rust programs can be built for these targets by specifying `--target`, if
 $ rustc --target aarch64-apple-ios your-code.rs
 ```
 
+The simulator variants can be differentiated from the variants running
+on-device with the `target_env = "sim"` cfg (or `target_abi = "sim"` before
+Rust CURRENT_RUSTC_VERSION).
+
+```rust
+if cfg!(all(target_vendor = "apple", target_env = "sim")) {
+    // Do something on the iOS/tvOS/visionOS/watchOS Simulator.
+} {
+    // Everything else, like Windows and non-Simulator iOS.
+}
+```
+
+This is similar to the `TARGET_OS_SIMULATOR` define in C code.
+
 ## Testing
 
 There is no support for running the Rust or standard library testsuite at the
diff --git a/src/tools/compiletest/src/directives/tests.rs b/src/tools/compiletest/src/directives/tests.rs
index 30d8537b51a..33a02eb29fd 100644
--- a/src/tools/compiletest/src/directives/tests.rs
+++ b/src/tools/compiletest/src/directives/tests.rs
@@ -637,6 +637,7 @@ fn matches_env() {
         ("x86_64-unknown-linux-gnu", "gnu"),
         ("x86_64-fortanix-unknown-sgx", "sgx"),
         ("arm-unknown-linux-musleabi", "musl"),
+        ("aarch64-apple-ios-macabi", "macabi"),
     ];
     for (target, env) in envs {
         let config: Config = cfg().target(target).build();
@@ -647,11 +648,7 @@ fn matches_env() {
 
 #[test]
 fn matches_abi() {
-    let abis = [
-        ("aarch64-apple-ios-macabi", "macabi"),
-        ("x86_64-unknown-linux-gnux32", "x32"),
-        ("arm-unknown-linux-gnueabi", "eabi"),
-    ];
+    let abis = [("x86_64-unknown-linux-gnux32", "x32"), ("arm-unknown-linux-gnueabi", "eabi")];
     for (target, abi) in abis {
         let config: Config = cfg().target(target).build();
         assert!(config.matches_abi(abi), "{target} {abi}");
diff --git a/src/tools/miri/src/intrinsics/atomic.rs b/src/tools/miri/src/intrinsics/atomic.rs
index bcc3e9ec885..e6341252927 100644
--- a/src/tools/miri/src/intrinsics/atomic.rs
+++ b/src/tools/miri/src/intrinsics/atomic.rs
@@ -105,27 +105,27 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             "or" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitOr, false), rw_ord(ord))?;
             }
             "xor" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitXor, false), rw_ord(ord))?;
             }
             "and" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, false), rw_ord(ord))?;
             }
             "nand" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::BitAnd, true), rw_ord(ord))?;
             }
             "xadd" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Add, false), rw_ord(ord))?;
             }
             "xsub" => {
-                let ord = get_ord_at(1);
+                let ord = get_ord_at(2);
                 this.atomic_rmw_op(args, dest, AtomicOp::MirOp(BinOp::Sub, false), rw_ord(ord))?;
             }
             "min" => {
@@ -231,15 +231,14 @@ trait EvalContextPrivExt<'tcx>: MiriInterpCxExt<'tcx> {
         let place = this.deref_pointer(place)?;
         let rhs = this.read_immediate(rhs)?;
 
-        if !place.layout.ty.is_integral() && !place.layout.ty.is_raw_ptr() {
+        if !(place.layout.ty.is_integral() || place.layout.ty.is_raw_ptr())
+            || !(rhs.layout.ty.is_integral() || rhs.layout.ty.is_raw_ptr())
+        {
             span_bug!(
                 this.cur_span(),
                 "atomic arithmetic operations only work on integer and raw pointer types",
             );
         }
-        if rhs.layout.ty != place.layout.ty {
-            span_bug!(this.cur_span(), "atomic arithmetic operation type mismatch");
-        }
 
         let old = match atomic_op {
             AtomicOp::Min =>
diff --git a/src/tools/miri/src/operator.rs b/src/tools/miri/src/operator.rs
index 73d671121f6..3c3f2c28535 100644
--- a/src/tools/miri/src/operator.rs
+++ b/src/tools/miri/src/operator.rs
@@ -50,17 +50,13 @@ pub trait EvalContextExt<'tcx>: crate::MiriInterpCxExt<'tcx> {
             }
 
             // Some more operations are possible with atomics.
-            // The return value always has the provenance of the *left* operand.
+            // The RHS must be `usize`.
             Add | Sub | BitOr | BitAnd | BitXor => {
                 assert!(left.layout.ty.is_raw_ptr());
-                assert!(right.layout.ty.is_raw_ptr());
+                assert_eq!(right.layout.ty, this.tcx.types.usize);
                 let ptr = left.to_scalar().to_pointer(this)?;
                 // We do the actual operation with usize-typed scalars.
                 let left = ImmTy::from_uint(ptr.addr().bytes(), this.machine.layouts.usize);
-                let right = ImmTy::from_uint(
-                    right.to_scalar().to_target_usize(this)?,
-                    this.machine.layouts.usize,
-                );
                 let result = this.binary_op(bin_op, &left, &right)?;
                 // Construct a new pointer with the provenance of `ptr` (the LHS).
                 let result_ptr = Pointer::new(
diff --git a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
index 29c56ca81f7..a2a4be30eca 100644
--- a/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
+++ b/src/tools/miri/tests/fail/alloc/alloc_error_handler_custom.stderr
@@ -11,7 +11,7 @@ note: inside `_::__rg_oom`
   --> tests/fail/alloc/alloc_error_handler_custom.rs:LL:CC
    |
 LL | #[alloc_error_handler]
-   | ---------------------- in this procedural macro expansion
+   | ---------------------- in this attribute macro expansion
 LL | fn alloc_error_handler(layout: Layout) -> ! {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    = note: inside `alloc::alloc::handle_alloc_error::rt_error` at RUSTLIB/alloc/src/alloc.rs:LL:CC
diff --git a/tests/codegen-llvm/atomicptr.rs b/tests/codegen-llvm/atomicptr.rs
index 4819af40ca2..ce6c4aa0d2b 100644
--- a/tests/codegen-llvm/atomicptr.rs
+++ b/tests/codegen-llvm/atomicptr.rs
@@ -1,5 +1,5 @@
 // LLVM does not support some atomic RMW operations on pointers, so inside codegen we lower those
-// to integer atomics, surrounded by casts to and from integer type.
+// to integer atomics, followed by an inttoptr cast.
 // This test ensures that we do the round-trip correctly for AtomicPtr::fetch_byte_add, and also
 // ensures that we do not have such a round-trip for AtomicPtr::swap, because LLVM supports pointer
 // arguments to `atomicrmw xchg`.
@@ -20,8 +20,8 @@ pub fn helper(_: usize) {}
 // CHECK-LABEL: @atomicptr_fetch_byte_add
 #[no_mangle]
 pub fn atomicptr_fetch_byte_add(a: &AtomicPtr<u8>, v: usize) -> *mut u8 {
-    // CHECK: %[[INTPTR:.*]] = ptrtoint ptr %{{.*}} to [[USIZE]]
-    // CHECK-NEXT: %[[RET:.*]] = atomicrmw add ptr %{{.*}}, [[USIZE]] %[[INTPTR]]
+    // CHECK: llvm.lifetime.start
+    // CHECK-NEXT: %[[RET:.*]] = atomicrmw add ptr %{{.*}}, [[USIZE]] %v
     // CHECK-NEXT: inttoptr [[USIZE]] %[[RET]] to ptr
     a.fetch_byte_add(v, Relaxed)
 }
diff --git a/tests/run-make/atomic-lock-free/atomic_lock_free.rs b/tests/run-make/atomic-lock-free/atomic_lock_free.rs
index f5c3b360ee8..92ffd111ce8 100644
--- a/tests/run-make/atomic-lock-free/atomic_lock_free.rs
+++ b/tests/run-make/atomic-lock-free/atomic_lock_free.rs
@@ -14,7 +14,7 @@ pub enum AtomicOrdering {
 }
 
 #[rustc_intrinsic]
-unsafe fn atomic_xadd<T, const ORD: AtomicOrdering>(dst: *mut T, src: T) -> T;
+unsafe fn atomic_xadd<T, U, const ORD: AtomicOrdering>(dst: *mut T, src: U) -> T;
 
 #[lang = "pointee_sized"]
 pub trait PointeeSized {}
@@ -35,51 +35,62 @@ impl<T: ?Sized> Copy for *mut T {}
 impl ConstParamTy for AtomicOrdering {}
 
 #[cfg(target_has_atomic = "8")]
+#[unsafe(no_mangle)] // let's make sure we actually generate a symbol to check
 pub unsafe fn atomic_u8(x: *mut u8) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u8);
 }
 #[cfg(target_has_atomic = "8")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i8(x: *mut i8) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i8);
 }
 #[cfg(target_has_atomic = "16")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u16(x: *mut u16) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u16);
 }
 #[cfg(target_has_atomic = "16")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i16(x: *mut i16) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i16);
 }
 #[cfg(target_has_atomic = "32")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u32(x: *mut u32) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u32);
 }
 #[cfg(target_has_atomic = "32")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i32(x: *mut i32) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i32);
 }
 #[cfg(target_has_atomic = "64")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u64(x: *mut u64) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u64);
 }
 #[cfg(target_has_atomic = "64")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i64(x: *mut i64) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i64);
 }
 #[cfg(target_has_atomic = "128")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_u128(x: *mut u128) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1u128);
 }
 #[cfg(target_has_atomic = "128")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_i128(x: *mut i128) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1i128);
 }
 #[cfg(target_has_atomic = "ptr")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_usize(x: *mut usize) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1usize);
 }
 #[cfg(target_has_atomic = "ptr")]
+#[unsafe(no_mangle)]
 pub unsafe fn atomic_isize(x: *mut isize) {
-    atomic_xadd::<_, { AtomicOrdering::SeqCst }>(x, 1);
+    atomic_xadd::<_, _, { AtomicOrdering::SeqCst }>(x, 1isize);
 }
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
index 15314fac37b..aad45c422e2 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-1.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
@@ -23,7 +23,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-1.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: &Layout,
 LL | || ) -> ()
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
index 2ab42638411..581d1947419 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: Layout,
 LL | || ) {
@@ -31,7 +31,7 @@ error[E0308]: mismatched types
   --> $DIR/alloc-error-handler-bad-signature-2.rs:10:1
    |
 LL |    #[alloc_error_handler]
-   |    ---------------------- in this procedural macro expansion
+   |    ---------------------- in this attribute macro expansion
 LL | // fn oom(
 LL | ||     info: Layout,
 LL | || ) {
diff --git a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
index 3a410174f54..91147df71eb 100644
--- a/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
+++ b/tests/ui/alloc-error/alloc-error-handler-bad-signature-3.stderr
@@ -2,7 +2,7 @@ error[E0061]: this function takes 0 arguments but 1 argument was supplied
   --> $DIR/alloc-error-handler-bad-signature-3.rs:10:1
    |
 LL |   #[alloc_error_handler]
-   |   ---------------------- in this procedural macro expansion
+   |   ---------------------- in this attribute macro expansion
 LL |   fn oom() -> ! {
    |  _-^^^^^^^^^^^^
 LL | |     loop {}
diff --git a/tests/ui/allocator/not-an-allocator.stderr b/tests/ui/allocator/not-an-allocator.stderr
index 079bf9334eb..f33a698ed78 100644
--- a/tests/ui/allocator/not-an-allocator.stderr
+++ b/tests/ui/allocator/not-an-allocator.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -12,7 +12,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -23,7 +23,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
@@ -34,7 +34,7 @@ error[E0277]: the trait bound `usize: GlobalAlloc` is not satisfied
   --> $DIR/not-an-allocator.rs:2:11
    |
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static A: usize = 0;
    |           ^^^^^ the trait `GlobalAlloc` is not implemented for `usize`
    |
diff --git a/tests/ui/allocator/two-allocators.stderr b/tests/ui/allocator/two-allocators.stderr
index 5308232a20b..1a9a5910eec 100644
--- a/tests/ui/allocator/two-allocators.stderr
+++ b/tests/ui/allocator/two-allocators.stderr
@@ -4,7 +4,7 @@ error: cannot define multiple global allocators
 LL | static A: System = System;
    | -------------------------- previous global allocator defined here
 LL | #[global_allocator]
-   | ------------------- in this procedural macro expansion
+   | ------------------- in this attribute macro expansion
 LL | static B: System = System;
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^ cannot define a new global allocator
 
diff --git a/tests/ui/attributes/rustc_confusables_std_cases.stderr b/tests/ui/attributes/rustc_confusables_std_cases.stderr
index f2d9ebe2c0e..771c0c6dfe9 100644
--- a/tests/ui/attributes/rustc_confusables_std_cases.stderr
+++ b/tests/ui/attributes/rustc_confusables_std_cases.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `push` found for struct `BTreeSet` in the current scope
+error[E0599]: no method named `push` found for struct `BTreeSet<T, A>` in the current scope
   --> $DIR/rustc_confusables_std_cases.rs:6:7
    |
 LL |     x.push(1);
@@ -22,7 +22,7 @@ LL -     x.push_back(1);
 LL +     x.push(1);
    |
 
-error[E0599]: no method named `push` found for struct `VecDeque` in the current scope
+error[E0599]: no method named `push` found for struct `VecDeque<T, A>` in the current scope
   --> $DIR/rustc_confusables_std_cases.rs:12:7
    |
 LL |     x.push(1);
@@ -35,7 +35,7 @@ LL |     let mut x = Vec::new();
    |         ^^^^^ `x` of type `Vec<_>` that has method `push` defined earlier here
 ...
 LL |     let mut x = VecDeque::new();
-   |         ----- earlier `x` shadowed here with type `VecDeque`
+   |         ----- earlier `x` shadowed here with type `VecDeque<_>`
 help: you might have meant to use `push_back`
    |
 LL |     x.push_back(1);
diff --git a/tests/ui/check-cfg/well-known-values.stderr b/tests/ui/check-cfg/well-known-values.stderr
index b2186f85b8a..18e038a442e 100644
--- a/tests/ui/check-cfg/well-known-values.stderr
+++ b/tests/ui/check-cfg/well-known-values.stderr
@@ -156,7 +156,7 @@ warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
 LL |     target_env = "_UNEXPECTED_VALUE",
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
-   = note: expected values for `target_env` are: ``, `gnu`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `uclibc`, and `v5`
+   = note: expected values for `target_env` are: ``, `gnu`, `macabi`, `msvc`, `musl`, `newlib`, `nto70`, `nto71`, `nto71_iosock`, `nto80`, `ohos`, `p1`, `p2`, `relibc`, `sgx`, `sim`, `uclibc`, and `v5`
    = note: see <https://doc.rust-lang.org/nightly/rustc/check-cfg.html> for more information about checking conditional configuration
 
 warning: unexpected `cfg` condition value: `_UNEXPECTED_VALUE`
diff --git a/tests/ui/codegen/overflow-during-mono.rs b/tests/ui/codegen/overflow-during-mono.rs
index a9045840173..3aafe05ba05 100644
--- a/tests/ui/codegen/overflow-during-mono.rs
+++ b/tests/ui/codegen/overflow-during-mono.rs
@@ -1,5 +1,6 @@
-//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
+//~ ERROR overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:14:41: 14:44}: FnMut(&'a _)`
 //@ build-fail
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 
 #![recursion_limit = "32"]
 
diff --git a/tests/ui/codegen/overflow-during-mono.stderr b/tests/ui/codegen/overflow-during-mono.stderr
index 74d98fde285..1559de757e7 100644
--- a/tests/ui/codegen/overflow-during-mono.stderr
+++ b/tests/ui/codegen/overflow-during-mono.stderr
@@ -1,10 +1,12 @@
-error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}: FnMut(&'a _)`
+error[E0275]: overflow evaluating the requirement `for<'a> {closure@$DIR/overflow-during-mono.rs:14:41: 14:44}: FnMut(&'a _)`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "64"]` attribute to your crate (`overflow_during_mono`)
-   = note: required for `Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
+   = note: required for `Filter<IntoIter<i32, 11>, {closure@overflow-during-mono.rs:14:41}>` to implement `Iterator`
    = note: 31 redundant requirements hidden
-   = note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `Iterator`
-   = note: required for `Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<Filter<std::array::IntoIter<i32, 11>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>, {closure@$DIR/overflow-during-mono.rs:13:41: 13:44}>` to implement `IntoIterator`
+   = note: required for `Filter<Filter<Filter<Filter<Filter<..., ...>, ...>, ...>, ...>, ...>` to implement `Iterator`
+   = note: required for `Filter<Filter<Filter<Filter<Filter<..., ...>, ...>, ...>, ...>, ...>` to implement `IntoIterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/overflow-during-mono.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/coherence/coherence-tuple-conflict.stderr b/tests/ui/coherence/coherence-tuple-conflict.stderr
index 95f9a1a8841..8ce65f79aca 100644
--- a/tests/ui/coherence/coherence-tuple-conflict.stderr
+++ b/tests/ui/coherence/coherence-tuple-conflict.stderr
@@ -12,6 +12,8 @@ error[E0609]: no field `dummy` on type `&(A, B)`
    |
 LL |     fn get(&self) -> usize { self.dummy }
    |                                   ^^^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/confuse-field-and-method/issue-18343.stderr b/tests/ui/confuse-field-and-method/issue-18343.stderr
index e50c971d837..9517617fe34 100644
--- a/tests/ui/confuse-field-and-method/issue-18343.stderr
+++ b/tests/ui/confuse-field-and-method/issue-18343.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-18343.rs:7:7
    |
 LL | struct Obj<F> where F: FnMut() -> u32 {
diff --git a/tests/ui/confuse-field-and-method/issue-2392.stderr b/tests/ui/confuse-field-and-method/issue-2392.stderr
index 77930de44a7..e1ad24df80f 100644
--- a/tests/ui/confuse-field-and-method/issue-2392.stderr
+++ b/tests/ui/confuse-field-and-method/issue-2392.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:36:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -12,7 +12,7 @@ help: to call the closure stored in `closure`, surround the field access with pa
 LL |     (o_closure.closure)();
    |     +                 +
 
-error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:38:15
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -23,7 +23,7 @@ LL |     o_closure.not_closure();
    |               |
    |               field, not a method
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:42:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -65,7 +65,7 @@ help: to call the trait object stored in `boxed_closure`, surround the field acc
 LL |     (boxed_closure.boxed_closure)();
    |     +                           +
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:53:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -79,7 +79,7 @@ help: to call the function stored in `closure`, surround the field access with p
 LL |     (w.wrap.closure)();
    |     +              +
 
-error[E0599]: no method named `not_closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `not_closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:55:12
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
@@ -90,7 +90,7 @@ LL |     w.wrap.not_closure();
    |            |
    |            field, not a method
 
-error[E0599]: no method named `closure` found for struct `Obj` in the current scope
+error[E0599]: no method named `closure` found for struct `Obj<F>` in the current scope
   --> $DIR/issue-2392.rs:58:24
    |
 LL | struct Obj<F> where F: FnOnce() -> u32 {
diff --git a/tests/ui/consts/issue-19244-1.stderr b/tests/ui/consts/issue-19244-1.stderr
index 9c1336402e6..98a33817b4c 100644
--- a/tests/ui/consts/issue-19244-1.stderr
+++ b/tests/ui/consts/issue-19244-1.stderr
@@ -3,6 +3,8 @@ error[E0609]: no field `1` on type `(usize,)`
    |
 LL |     let a: [isize; TUP.1];
    |                        ^ unknown field
+   |
+   = note: available field is: `0`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/custom_test_frameworks/mismatch.stderr b/tests/ui/custom_test_frameworks/mismatch.stderr
index c7798635fbf..7cdfaa9e804 100644
--- a/tests/ui/custom_test_frameworks/mismatch.stderr
+++ b/tests/ui/custom_test_frameworks/mismatch.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `TestDescAndFn: Testable` is not satisfied
   --> $DIR/mismatch.rs:9:1
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn wrong_kind(){}
    | ^^^^^^^^^^^^^^^^^ the trait `Testable` is not implemented for `TestDescAndFn`
    |
diff --git a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
index 61e2a8f64dd..b0bfc720658 100644
--- a/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
+++ b/tests/ui/delegation/correct_body_owner_parent_found_in_diagnostics.stderr
@@ -43,7 +43,7 @@ help: consider introducing lifetime `'a` here
 LL | impl<'a> Trait for Z {
    |     ++++
 
-error[E0599]: no function or associated item named `new` found for struct `InvariantRef` in the current scope
+error[E0599]: no function or associated item named `new` found for struct `InvariantRef<'a, T>` in the current scope
   --> $DIR/correct_body_owner_parent_found_in_diagnostics.rs:9:41
    |
 LL | pub struct InvariantRef<'a, T: ?Sized>(&'a T, PhantomData<&'a mut &'a T>);
diff --git a/tests/ui/diagnostic-width/long-E0609.stderr b/tests/ui/diagnostic-width/long-E0609.stderr
index 36ef8545746..70092ea34bc 100644
--- a/tests/ui/diagnostic-width/long-E0609.stderr
+++ b/tests/ui/diagnostic-width/long-E0609.stderr
@@ -4,6 +4,7 @@ error[E0609]: no field `field` on type `(..., ..., ..., ...)`
 LL |     x.field;
    |       ^^^^^ unknown field
    |
+   = note: available fields are: `0`, `1`, `2`, `3`
    = note: the full name for the type has been written to '$TEST_BUILD_DIR/long-E0609.long-type-$LONG_TYPE_HASH.txt'
    = note: consider using `--verbose` to print the full type name to the console
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
index 17b76b6c832..2bb82a2ebf2 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.rs
@@ -1,5 +1,6 @@
 // Issue 22443: Reject code using non-regular types that would
 // otherwise cause dropck to loop infinitely.
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 
 use std::marker::PhantomData;
 
diff --git a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
index 9360f4a98e9..330a40d925b 100644
--- a/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
+++ b/tests/ui/dropck/dropck_no_diverge_on_nonregular_1.stderr
@@ -1,10 +1,12 @@
 error[E0320]: overflow while adding drop-check rules for `FingerTree<i32>`
-  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:24:9
+  --> $DIR/dropck_no_diverge_on_nonregular_1.rs:25:9
    |
 LL |     let ft =
    |         ^^
    |
-   = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<Node<i32>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
+   = note: overflowed on `FingerTree<Node<Node<Node<Node<Node<Node<Node<Node<Node<...>>>>>>>>>>`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/dropck_no_diverge_on_nonregular_1.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
index 2daf00f7804..f0d4de364fb 100644
--- a/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
+++ b/tests/ui/editions/never-type-fallback-breaking.e2024.stderr
@@ -5,7 +5,7 @@ LL |         true => Default::default(),
    |                 ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 
 error[E0277]: the trait bound `!: Default` is not satisfied
   --> $DIR/never-type-fallback-breaking.rs:37:5
@@ -14,7 +14,7 @@ LL |     deserialize()?;
    |     ^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `deserialize`
   --> $DIR/never-type-fallback-breaking.rs:33:23
    |
@@ -51,7 +51,7 @@ LL |     takes_apit(|| Default::default())?;
    |                   ^^^^^^^^^^^^^^^^^^ the trait `Default` is not implemented for `!`
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 
 error[E0277]: the trait bound `!: Default` is not satisfied
   --> $DIR/never-type-fallback-breaking.rs:76:17
@@ -62,7 +62,7 @@ LL |     takes_apit2(mk()?);
    |     required by a bound introduced by this call
    |
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `takes_apit2`
   --> $DIR/never-type-fallback-breaking.rs:71:25
    |
diff --git a/tests/ui/error-codes/E0275.rs b/tests/ui/error-codes/E0275.rs
index 28a9676f03e..98d4a3c01b9 100644
--- a/tests/ui/error-codes/E0275.rs
+++ b/tests/ui/error-codes/E0275.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 trait Foo {}
 
 struct Bar<T>(T);
diff --git a/tests/ui/error-codes/E0275.stderr b/tests/ui/error-codes/E0275.stderr
index 3b31c87320a..755404c1e16 100644
--- a/tests/ui/error-codes/E0275.stderr
+++ b/tests/ui/error-codes/E0275.stderr
@@ -1,17 +1,19 @@
 error[E0275]: overflow evaluating the requirement `Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>: Foo`
-  --> $DIR/E0275.rs:5:33
+  --> $DIR/E0275.rs:6:33
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |                                 ^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`E0275`)
-note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<T>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `Foo`
-  --> $DIR/E0275.rs:5:9
+note: required for `Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<Bar<...>>>>>>>>>>>>>` to implement `Foo`
+  --> $DIR/E0275.rs:6:9
    |
 LL | impl<T> Foo for T where Bar<T>: Foo {}
    |         ^^^     ^               --- unsatisfied trait bound introduced here
    = note: 126 redundant requirements hidden
    = note: required for `Bar<T>` to implement `Foo`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/E0275.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/error-codes/ex-E0612.stderr b/tests/ui/error-codes/ex-E0612.stderr
index 54451d3d452..e6062f6061d 100644
--- a/tests/ui/error-codes/ex-E0612.stderr
+++ b/tests/ui/error-codes/ex-E0612.stderr
@@ -4,11 +4,7 @@ error[E0609]: no field `1` on type `Foo`
 LL |    y.1;
    |      ^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -    y.1;
-LL +    y.0;
-   |
+   = note: available field is: `0`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-macro-attr.rs b/tests/ui/feature-gates/feature-gate-macro-attr.rs
new file mode 100644
index 00000000000..8419d851147
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-attr.rs
@@ -0,0 +1,4 @@
+#![crate_type = "lib"]
+
+macro_rules! myattr { attr() {} => {} }
+//~^ ERROR `macro_rules!` attributes are unstable
diff --git a/tests/ui/feature-gates/feature-gate-macro-attr.stderr b/tests/ui/feature-gates/feature-gate-macro-attr.stderr
new file mode 100644
index 00000000000..b58418527c5
--- /dev/null
+++ b/tests/ui/feature-gates/feature-gate-macro-attr.stderr
@@ -0,0 +1,13 @@
+error[E0658]: `macro_rules!` attributes are unstable
+  --> $DIR/feature-gate-macro-attr.rs:3:1
+   |
+LL | macro_rules! myattr { attr() {} => {} }
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #83527 <https://github.com/rust-lang/rust/issues/83527> for more information
+   = help: add `#![feature(macro_attr)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
index d8a1f3fa69e..d2793afdd06 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.rs
@@ -6,6 +6,8 @@
 // This tests double-checks that we do not allow such behavior to leak
 // through again.
 
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
+
 pub trait Stream {
     type Item;
     fn next(self) -> Option<Self::Item>;
diff --git a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
index 23b979e2ef0..91e65b2b073 100644
--- a/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/hrtb-doesnt-borrow-self-2.stderr
@@ -1,5 +1,5 @@
-error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>`, but its trait bounds were not satisfied
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:110:24
+error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@...}>`, but its trait bounds were not satisfied
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:112:24
    |
 LL | pub struct Filter<S, F> {
    | ----------------------- method `countx` not found for this struct because it doesn't satisfy `_: StreamExt`
@@ -8,19 +8,21 @@ LL |     let count = filter.countx();
    |                        ^^^^^^ method cannot be called due to unsatisfied trait bounds
    |
 note: the following trait bounds were not satisfied:
-      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:109:30: 109:37}>: Stream`
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:96:50
+      `&'a mut &Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut &mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+      `&'a mut Filter<Map<Repeat, for<'a> fn(&'a u64) -> &'a u64 {identity::<u64>}>, {closure@$DIR/hrtb-doesnt-borrow-self-2.rs:111:30: 111:37}>: Stream`
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:98:50
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `StreamExt` defines an item `countx`, perhaps you need to implement it
-  --> $DIR/hrtb-doesnt-borrow-self-2.rs:64:1
+  --> $DIR/hrtb-doesnt-borrow-self-2.rs:66:1
    |
 LL | pub trait StreamExt
    | ^^^^^^^^^^^^^^^^^^^
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/hrtb-doesnt-borrow-self-2.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
index 09450089ada..ead81bf3374 100644
--- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
+++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::cell::Cell;
 use std::rc::Rc;
 
diff --git a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
index 52fa28145d6..ba76d9ba2b8 100644
--- a/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
+++ b/tests/ui/impl-trait/auto-trait-leakage/auto-trait-leak2.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:20:10
+  --> $DIR/auto-trait-leak2.rs:21:10
    |
 LL | fn before() -> impl Fn(i32) {
    |                ------------ within this `impl Fn(i32)`
@@ -11,23 +11,23 @@ LL |     send(before());
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
-  --> $DIR/auto-trait-leak2.rs:10:5
+  --> $DIR/auto-trait-leak2.rs:11:5
    |
 LL |     move |x| p.set(x)
    |     ^^^^^^^^
 note: required because it appears within the type `impl Fn(i32)`
-  --> $DIR/auto-trait-leak2.rs:5:16
+  --> $DIR/auto-trait-leak2.rs:6:16
    |
 LL | fn before() -> impl Fn(i32) {
    |                ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:13:12
+  --> $DIR/auto-trait-leak2.rs:14:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
 
 error[E0277]: `Rc<Cell<i32>>` cannot be sent between threads safely
-  --> $DIR/auto-trait-leak2.rs:25:10
+  --> $DIR/auto-trait-leak2.rs:26:10
    |
 LL |     send(after());
    |     ---- ^^^^^^^ `Rc<Cell<i32>>` cannot be sent between threads safely
@@ -39,17 +39,17 @@ LL | fn after() -> impl Fn(i32) {
    |
    = help: within `impl Fn(i32)`, the trait `Send` is not implemented for `Rc<Cell<i32>>`
 note: required because it's used within this closure
-  --> $DIR/auto-trait-leak2.rs:38:5
+  --> $DIR/auto-trait-leak2.rs:39:5
    |
 LL |     move |x| p.set(x)
    |     ^^^^^^^^
 note: required because it appears within the type `impl Fn(i32)`
-  --> $DIR/auto-trait-leak2.rs:33:15
+  --> $DIR/auto-trait-leak2.rs:34:15
    |
 LL | fn after() -> impl Fn(i32) {
    |               ^^^^^^^^^^^^
 note: required by a bound in `send`
-  --> $DIR/auto-trait-leak2.rs:13:12
+  --> $DIR/auto-trait-leak2.rs:14:12
    |
 LL | fn send<T: Send>(_: T) {}
    |            ^^^^ required by this bound in `send`
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
index 4fd15eea9e0..f1353f1805d 100644
--- a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 type A = (i32, i32, i32, i32);
 type B = (A, A, A, A);
 type C = (B, B, B, B);
diff --git a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
index 65fe2ffcb7f..5c4a1a75829 100644
--- a/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
+++ b/tests/ui/inference/really-long-type-in-let-binding-without-sufficient-type-info.stderr
@@ -1,9 +1,11 @@
-error[E0282]: type annotations needed for `Result<_, ((((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))), (((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32)), ((i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32), (i32, i32, i32, i32))))>`
-  --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:7:9
+error[E0282]: type annotations needed for `Result<_, (((..., ..., ..., ...), ..., ..., ...), ..., ..., ...)>`
+  --> $DIR/really-long-type-in-let-binding-without-sufficient-type-info.rs:8:9
    |
 LL |     let y = Err(x);
    |         ^   ------ type must be known at this point
    |
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/really-long-type-in-let-binding-without-sufficient-type-info.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 help: consider giving `y` an explicit type, where the type for type parameter `T` is specified
    |
 LL |     let y: Result<T, _> = Err(x);
diff --git a/tests/ui/interior-mutability/interior-mutability.rs b/tests/ui/interior-mutability/interior-mutability.rs
index c704acc22af..7e4fe76852d 100644
--- a/tests/ui/interior-mutability/interior-mutability.rs
+++ b/tests/ui/interior-mutability/interior-mutability.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::cell::Cell;
 use std::panic::catch_unwind;
 fn main() {
diff --git a/tests/ui/interior-mutability/interior-mutability.stderr b/tests/ui/interior-mutability/interior-mutability.stderr
index cfc64445bf3..5a959d14c8a 100644
--- a/tests/ui/interior-mutability/interior-mutability.stderr
+++ b/tests/ui/interior-mutability/interior-mutability.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the type `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
-  --> $DIR/interior-mutability.rs:5:18
+  --> $DIR/interior-mutability.rs:6:18
    |
 LL |     catch_unwind(|| { x.set(23); });
    |     ------------ ^^^^^^^^^^^^^^^^^ `UnsafeCell<i32>` may contain interior mutability and a reference may not be safely transferrable across a catch_unwind boundary
@@ -11,7 +11,7 @@ note: required because it appears within the type `Cell<i32>`
   --> $SRC_DIR/core/src/cell.rs:LL:COL
    = note: required for `&Cell<i32>` to implement `UnwindSafe`
 note: required because it's used within this closure
-  --> $DIR/interior-mutability.rs:5:18
+  --> $DIR/interior-mutability.rs:6:18
    |
 LL |     catch_unwind(|| { x.set(23); });
    |                  ^^
diff --git a/tests/ui/intrinsics/intrinsic-atomics.rs b/tests/ui/intrinsics/intrinsic-atomics.rs
index 2275aafff83..c19948137db 100644
--- a/tests/ui/intrinsics/intrinsic-atomics.rs
+++ b/tests/ui/intrinsics/intrinsic-atomics.rs
@@ -33,14 +33,14 @@ pub fn main() {
         assert_eq!(rusti::atomic_xchg::<_, { Release }>(&mut *x, 0), 1);
         assert_eq!(*x, 0);
 
-        assert_eq!(rusti::atomic_xadd::<_, { SeqCst }>(&mut *x, 1), 0);
-        assert_eq!(rusti::atomic_xadd::<_, { Acquire }>(&mut *x, 1), 1);
-        assert_eq!(rusti::atomic_xadd::<_, { Release }>(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xadd::<_, _, { SeqCst }>(&mut *x, 1), 0);
+        assert_eq!(rusti::atomic_xadd::<_, _, { Acquire }>(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xadd::<_, _, { Release }>(&mut *x, 1), 2);
         assert_eq!(*x, 3);
 
-        assert_eq!(rusti::atomic_xsub::<_, { SeqCst }>(&mut *x, 1), 3);
-        assert_eq!(rusti::atomic_xsub::<_, { Acquire }>(&mut *x, 1), 2);
-        assert_eq!(rusti::atomic_xsub::<_, { Release }>(&mut *x, 1), 1);
+        assert_eq!(rusti::atomic_xsub::<_, _, { SeqCst }>(&mut *x, 1), 3);
+        assert_eq!(rusti::atomic_xsub::<_, _, { Acquire }>(&mut *x, 1), 2);
+        assert_eq!(rusti::atomic_xsub::<_, _, { Release }>(&mut *x, 1), 1);
         assert_eq!(*x, 0);
 
         loop {
diff --git a/tests/ui/intrinsics/non-integer-atomic.rs b/tests/ui/intrinsics/non-integer-atomic.rs
index 853c163710f..30f713f1241 100644
--- a/tests/ui/intrinsics/non-integer-atomic.rs
+++ b/tests/ui/intrinsics/non-integer-atomic.rs
@@ -13,80 +13,80 @@ pub type Quux = [u8; 100];
 
 pub unsafe fn test_bool_load(p: &mut bool, v: bool) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_store(p: &mut bool, v: bool) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_xchg(p: &mut bool, v: bool) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_bool_cxchg(p: &mut bool, v: bool) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool`
 }
 
 pub unsafe fn test_Foo_load(p: &mut Foo, v: Foo) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_store(p: &mut Foo, v: Foo) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_xchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Foo_cxchg(p: &mut Foo, v: Foo) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo`
 }
 
 pub unsafe fn test_Bar_load(p: &mut Bar, v: Bar) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_store(p: &mut Bar, v: Bar) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_xchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Bar_cxchg(p: &mut Bar, v: Bar) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR expected basic integer type, found `&dyn Fn()`
+    //~^ ERROR expected basic integer or pointer type, found `&dyn Fn()`
 }
 
 pub unsafe fn test_Quux_load(p: &mut Quux, v: Quux) {
     intrinsics::atomic_load::<_, { SeqCst }>(p);
-    //~^ ERROR `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_load` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_store(p: &mut Quux, v: Quux) {
     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_xchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
-    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
 
 pub unsafe fn test_Quux_cxchg(p: &mut Quux, v: Quux) {
     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
-    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+    //~^ ERROR `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
 }
diff --git a/tests/ui/intrinsics/non-integer-atomic.stderr b/tests/ui/intrinsics/non-integer-atomic.stderr
index e539d99b8ae..b96ee7ba846 100644
--- a/tests/ui/intrinsics/non-integer-atomic.stderr
+++ b/tests/ui/intrinsics/non-integer-atomic.stderr
@@ -1,94 +1,94 @@
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:15:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:20:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:25:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `bool`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `bool`
   --> $DIR/non-integer-atomic.rs:30:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:35:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:40:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:45:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `Foo`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `Foo`
   --> $DIR/non-integer-atomic.rs:50:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:55:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:60:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:65:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `&dyn Fn()`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `&dyn Fn()`
   --> $DIR/non-integer-atomic.rs:70:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_load` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:75:5
    |
 LL |     intrinsics::atomic_load::<_, { SeqCst }>(p);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_store` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:80:5
    |
 LL |     intrinsics::atomic_store::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_xchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:85:5
    |
 LL |     intrinsics::atomic_xchg::<_, { SeqCst }>(p, v);
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer type, found `[u8; 100]`
+error[E0511]: invalid monomorphization of `atomic_cxchg` intrinsic: expected basic integer or pointer type, found `[u8; 100]`
   --> $DIR/non-integer-atomic.rs:90:5
    |
 LL |     intrinsics::atomic_cxchg::<_, { SeqCst }, { SeqCst }>(p, v, v);
diff --git a/tests/ui/issues/issue-41880.stderr b/tests/ui/issues/issue-41880.stderr
index 1936c0aebd4..2f1ebee7ca5 100644
--- a/tests/ui/issues/issue-41880.stderr
+++ b/tests/ui/issues/issue-41880.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `iter` found for struct `Iterate` in the current scope
+error[E0599]: no method named `iter` found for struct `Iterate<T, F>` in the current scope
   --> $DIR/issue-41880.rs:27:24
    |
 LL | pub struct Iterate<T, F> {
diff --git a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
index e5b913b208d..77f8bef83a4 100644
--- a/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
+++ b/tests/ui/macros/macro-rules-as-derive-or-attr-issue-132928.stderr
@@ -11,7 +11,7 @@ error: cannot find attribute `sample` in this scope
   --> $DIR/macro-rules-as-derive-or-attr-issue-132928.rs:5:3
    |
 LL | macro_rules! sample { () => {} }
-   |              ------ `sample` exists, but a declarative macro cannot be used as an attribute macro
+   |              ------ `sample` exists, but has no `attr` rules
 LL |
 LL | #[sample]
    |   ^^^^^^
diff --git a/tests/ui/macros/macro-rules-attr-error.rs b/tests/ui/macros/macro-rules-attr-error.rs
new file mode 100644
index 00000000000..1c8bb251e20
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-error.rs
@@ -0,0 +1,15 @@
+#![feature(macro_attr)]
+
+macro_rules! local_attr {
+    attr() { $($body:tt)* } => {
+        compile_error!(concat!("local_attr: ", stringify!($($body)*)));
+    };
+    //~^^ ERROR: local_attr
+}
+
+fn main() {
+    #[local_attr]
+    struct S;
+
+    local_attr!(arg); //~ ERROR: macro has no rules for function-like invocation
+}
diff --git a/tests/ui/macros/macro-rules-attr-error.stderr b/tests/ui/macros/macro-rules-attr-error.stderr
new file mode 100644
index 00000000000..177b7009384
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-error.stderr
@@ -0,0 +1,22 @@
+error: local_attr: struct S;
+  --> $DIR/macro-rules-attr-error.rs:5:9
+   |
+LL |         compile_error!(concat!("local_attr: ", stringify!($($body)*)));
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+...
+LL |     #[local_attr]
+   |     ------------- in this attribute macro expansion
+   |
+   = note: this error originates in the attribute macro `local_attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: macro has no rules for function-like invocation `local_attr!`
+  --> $DIR/macro-rules-attr-error.rs:14:5
+   |
+LL | macro_rules! local_attr {
+   | ----------------------- this macro has no rules for function-like invocation
+...
+LL |     local_attr!(arg);
+   |     ^^^^^^^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/macros/macro-rules-attr-infinite-recursion.rs b/tests/ui/macros/macro-rules-attr-infinite-recursion.rs
new file mode 100644
index 00000000000..dc54c32cad3
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-infinite-recursion.rs
@@ -0,0 +1,12 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr {
+    attr() { $($body:tt)* } => {
+        #[attr] $($body)*
+    };
+    //~^^ ERROR: recursion limit reached
+}
+
+#[attr]
+struct S;
diff --git a/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr
new file mode 100644
index 00000000000..7d9a94338f5
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-infinite-recursion.stderr
@@ -0,0 +1,14 @@
+error: recursion limit reached while expanding `#[attr]`
+  --> $DIR/macro-rules-attr-infinite-recursion.rs:6:9
+   |
+LL |         #[attr] $($body)*
+   |         ^^^^^^^
+...
+LL | #[attr]
+   | ------- in this attribute macro expansion
+   |
+   = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`macro_rules_attr_infinite_recursion`)
+   = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/macros/macro-rules-attr-nested.rs b/tests/ui/macros/macro-rules-attr-nested.rs
new file mode 100644
index 00000000000..af5c30f00dd
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-nested.rs
@@ -0,0 +1,24 @@
+//@ run-pass
+//@ check-run-results
+#![feature(macro_attr)]
+
+macro_rules! nest {
+    attr() { struct $name:ident; } => {
+        println!("nest");
+        #[nest(1)]
+        struct $name;
+    };
+    attr(1) { struct $name:ident; } => {
+        println!("nest(1)");
+        #[nest(2)]
+        struct $name;
+    };
+    attr(2) { struct $name:ident; } => {
+        println!("nest(2)");
+    };
+}
+
+fn main() {
+    #[nest]
+    struct S;
+}
diff --git a/tests/ui/macros/macro-rules-attr-nested.run.stdout b/tests/ui/macros/macro-rules-attr-nested.run.stdout
new file mode 100644
index 00000000000..46017f9ae08
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr-nested.run.stdout
@@ -0,0 +1,3 @@
+nest
+nest(1)
+nest(2)
diff --git a/tests/ui/macros/macro-rules-attr.rs b/tests/ui/macros/macro-rules-attr.rs
new file mode 100644
index 00000000000..1d6f09b53e1
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.rs
@@ -0,0 +1,90 @@
+//@ run-pass
+//@ check-run-results
+#![feature(macro_attr)]
+#![warn(unused)]
+
+#[macro_export]
+macro_rules! exported_attr {
+    attr($($args:tt)*) { $($body:tt)* } => {
+        println!(
+            "exported_attr: args={:?}, body={:?}",
+            stringify!($($args)*),
+            stringify!($($body)*),
+        );
+    };
+    { $($args:tt)* } => {
+        println!("exported_attr!({:?})", stringify!($($args)*));
+    };
+    attr() {} => {
+        unused_rule();
+    };
+    attr() {} => {
+        compile_error!();
+    };
+    {} => {
+        unused_rule();
+    };
+    {} => {
+        compile_error!();
+    };
+}
+
+macro_rules! local_attr {
+    attr($($args:tt)*) { $($body:tt)* } => {
+        println!(
+            "local_attr: args={:?}, body={:?}",
+            stringify!($($args)*),
+            stringify!($($body)*),
+        );
+    };
+    { $($args:tt)* } => {
+        println!("local_attr!({:?})", stringify!($($args)*));
+    };
+    attr() {} => { //~ WARN: never used
+        unused_rule();
+    };
+    attr() {} => {
+        compile_error!();
+    };
+    {} => { //~ WARN: never used
+        unused_rule();
+    };
+    {} => {
+        compile_error!();
+    };
+}
+
+fn main() {
+    #[crate::exported_attr]
+    struct S;
+    #[::exported_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[self::exported_attr(1)]
+    #[self::exported_attr(2)]
+    struct Twice;
+
+    crate::exported_attr!();
+    crate::exported_attr!(invoked, arguments);
+
+    #[exported_attr]
+    struct S;
+    #[exported_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[exported_attr(1)]
+    #[exported_attr(2)]
+    struct Twice;
+
+    exported_attr!();
+    exported_attr!(invoked, arguments);
+
+    #[local_attr]
+    struct S;
+    #[local_attr(arguments, key = "value")]
+    fn func(_arg: u32) {}
+    #[local_attr(1)]
+    #[local_attr(2)]
+    struct Twice;
+
+    local_attr!();
+    local_attr!(invoked, arguments);
+}
diff --git a/tests/ui/macros/macro-rules-attr.run.stdout b/tests/ui/macros/macro-rules-attr.run.stdout
new file mode 100644
index 00000000000..77aa94d54f8
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.run.stdout
@@ -0,0 +1,15 @@
+exported_attr: args="", body="struct S;"
+exported_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+exported_attr: args="1", body="#[self::exported_attr(2)] struct Twice;"
+exported_attr!("")
+exported_attr!("invoked, arguments")
+exported_attr: args="", body="struct S;"
+exported_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+exported_attr: args="1", body="#[exported_attr(2)] struct Twice;"
+exported_attr!("")
+exported_attr!("invoked, arguments")
+local_attr: args="", body="struct S;"
+local_attr: args="arguments, key = \"value\"", body="fn func(_arg: u32) {}"
+local_attr: args="1", body="#[local_attr(2)] struct Twice;"
+local_attr!("")
+local_attr!("invoked, arguments")
diff --git a/tests/ui/macros/macro-rules-attr.stderr b/tests/ui/macros/macro-rules-attr.stderr
new file mode 100644
index 00000000000..567664cd73d
--- /dev/null
+++ b/tests/ui/macros/macro-rules-attr.stderr
@@ -0,0 +1,21 @@
+warning: rule #3 of macro `local_attr` is never used
+  --> $DIR/macro-rules-attr.rs:43:9
+   |
+LL |     attr() {} => {
+   |         ^^ ^^
+   |
+note: the lint level is defined here
+  --> $DIR/macro-rules-attr.rs:4:9
+   |
+LL | #![warn(unused)]
+   |         ^^^^^^
+   = note: `#[warn(unused_macro_rules)]` implied by `#[warn(unused)]`
+
+warning: rule #5 of macro `local_attr` is never used
+  --> $DIR/macro-rules-attr.rs:49:5
+   |
+LL |     {} => {
+   |     ^^
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/methods/call_method_unknown_referent.rs b/tests/ui/methods/call_method_unknown_referent.rs
index b01e2d80f7f..b26ecc74175 100644
--- a/tests/ui/methods/call_method_unknown_referent.rs
+++ b/tests/ui/methods/call_method_unknown_referent.rs
@@ -44,5 +44,5 @@ fn main() {
     // our resolution logic needs to be able to call methods such as foo()
     // on the outer type even if the inner type is ambiguous.
     let _c = (ptr as SmartPtr<_>).read();
-    //~^ ERROR no method named `read` found for struct `SmartPtr`
+    //~^ ERROR no method named `read` found for struct `SmartPtr<T>`
 }
diff --git a/tests/ui/methods/call_method_unknown_referent.stderr b/tests/ui/methods/call_method_unknown_referent.stderr
index 748b02b52b5..5d6974a00c6 100644
--- a/tests/ui/methods/call_method_unknown_referent.stderr
+++ b/tests/ui/methods/call_method_unknown_referent.stderr
@@ -10,7 +10,7 @@ error[E0282]: type annotations needed
 LL |     let _b = (rc as std::rc::Rc<_>).read();
    |                                     ^^^^ cannot infer type
 
-error[E0599]: no method named `read` found for struct `SmartPtr` in the current scope
+error[E0599]: no method named `read` found for struct `SmartPtr<T>` in the current scope
   --> $DIR/call_method_unknown_referent.rs:46:35
    |
 LL | struct SmartPtr<T>(T);
diff --git a/tests/ui/methods/inherent-bound-in-probe.rs b/tests/ui/methods/inherent-bound-in-probe.rs
index 4add93e808d..39b4ba983e4 100644
--- a/tests/ui/methods/inherent-bound-in-probe.rs
+++ b/tests/ui/methods/inherent-bound-in-probe.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 // Fixes #110131
 //
 // The issue is that we were constructing an `ImplDerived` cause code for the
diff --git a/tests/ui/methods/inherent-bound-in-probe.stderr b/tests/ui/methods/inherent-bound-in-probe.stderr
index 77aed390c9a..b7751ca4714 100644
--- a/tests/ui/methods/inherent-bound-in-probe.stderr
+++ b/tests/ui/methods/inherent-bound-in-probe.stderr
@@ -1,5 +1,5 @@
 error[E0277]: `Helper<'a, T>` is not an iterator
-  --> $DIR/inherent-bound-in-probe.rs:38:21
+  --> $DIR/inherent-bound-in-probe.rs:39:21
    |
 LL |     type IntoIter = Helper<'a, T>;
    |                     ^^^^^^^^^^^^^ `Helper<'a, T>` is not an iterator
@@ -9,14 +9,14 @@ note: required by a bound in `std::iter::IntoIterator::IntoIter`
   --> $SRC_DIR/core/src/iter/traits/collect.rs:LL:COL
 
 error[E0275]: overflow evaluating the requirement `&_: IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:42:9
+  --> $DIR/inherent-bound-in-probe.rs:43:9
    |
 LL |         Helper::new(&self.0)
    |         ^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`inherent_bound_in_probe`)
 note: required for `&BitReaderWrapper<_>` to implement `IntoIterator`
-  --> $DIR/inherent-bound-in-probe.rs:32:13
+  --> $DIR/inherent-bound-in-probe.rs:33:13
    |
 LL | impl<'a, T> IntoIterator for &'a BitReaderWrapper<T>
    |             ^^^^^^^^^^^^     ^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,15 +24,17 @@ LL | where
 LL |     &'a T: IntoIterator<Item = &'a u8>,
    |                         ------------- unsatisfied trait bound introduced here
    = note: 126 redundant requirements hidden
-   = note: required for `&BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<_>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>` to implement `IntoIterator`
+   = note: required for `&BitReaderWrapper<BitReaderWrapper<BitReaderWrapper<...>>>` to implement `IntoIterator`
 note: required by a bound in `Helper`
-  --> $DIR/inherent-bound-in-probe.rs:16:12
+  --> $DIR/inherent-bound-in-probe.rs:17:12
    |
 LL | struct Helper<'a, T>
    |        ------ required by a bound in this struct
 LL | where
 LL |     &'a T: IntoIterator<Item = &'a u8>,
    |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^ required by this bound in `Helper`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/inherent-bound-in-probe.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/methods/method-not-found-generic-arg-elision.stderr b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
index 8429c3aebac..75fabc27b0f 100644
--- a/tests/ui/methods/method-not-found-generic-arg-elision.stderr
+++ b/tests/ui/methods/method-not-found-generic-arg-elision.stderr
@@ -10,7 +10,7 @@ LL |     let d = point_i32.distance();
    = note: the method was found for
            - `Point<f64>`
 
-error[E0599]: no method named `other` found for struct `Point` in the current scope
+error[E0599]: no method named `other` found for struct `Point<T>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:84:23
    |
 LL | struct Point<T> {
@@ -19,7 +19,7 @@ LL | struct Point<T> {
 LL |     let d = point_i32.other();
    |                       ^^^^^ method not found in `Point<i32>`
 
-error[E0599]: no method named `extend` found for struct `Map` in the current scope
+error[E0599]: no method named `extend` found for struct `Map<I, F>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:87:67
    |
 LL |     v.iter().map(Box::new(|x| x * x) as Box<dyn Fn(&i32) -> i32>).extend(std::iter::once(100));
@@ -41,7 +41,7 @@ LL |     wrapper.method();
            - `Wrapper<i8>`
            and 2 more types
 
-error[E0599]: no method named `other` found for struct `Wrapper` in the current scope
+error[E0599]: no method named `other` found for struct `Wrapper<T>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:92:13
    |
 LL | struct Wrapper<T>(T);
@@ -64,7 +64,7 @@ LL |     wrapper.method();
            - `Wrapper2<'a, i32, C>`
            - `Wrapper2<'a, i8, C>`
 
-error[E0599]: no method named `other` found for struct `Wrapper2` in the current scope
+error[E0599]: no method named `other` found for struct `Wrapper2<'a, T, C>` in the current scope
   --> $DIR/method-not-found-generic-arg-elision.rs:98:13
    |
 LL | struct Wrapper2<'a, T, const C: usize> {
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.rs b/tests/ui/methods/probe-error-on-infinite-deref.rs
index 85c1c0c09c1..196d026438b 100644
--- a/tests/ui/methods/probe-error-on-infinite-deref.rs
+++ b/tests/ui/methods/probe-error-on-infinite-deref.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 use std::ops::Deref;
 
 // Make sure that method probe error reporting doesn't get too tangled up
diff --git a/tests/ui/methods/probe-error-on-infinite-deref.stderr b/tests/ui/methods/probe-error-on-infinite-deref.stderr
index 57a9ca2eaa8..6148b001163 100644
--- a/tests/ui/methods/probe-error-on-infinite-deref.stderr
+++ b/tests/ui/methods/probe-error-on-infinite-deref.stderr
@@ -1,13 +1,15 @@
-error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<{integer}>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>`
-  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+error[E0055]: reached the recursion limit while auto-dereferencing `Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<Wrap<...>>>>>>>>>>>`
+  --> $DIR/probe-error-on-infinite-deref.rs:14:13
    |
 LL |     Wrap(1).lmao();
    |             ^^^^ deref recursion limit reached
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`probe_error_on_infinite_deref`)
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/probe-error-on-infinite-deref.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error[E0599]: no method named `lmao` found for struct `Wrap<{integer}>` in the current scope
-  --> $DIR/probe-error-on-infinite-deref.rs:13:13
+  --> $DIR/probe-error-on-infinite-deref.rs:14:13
    |
 LL | struct Wrap<T>(T);
    | -------------- method `lmao` not found for this struct
diff --git a/tests/ui/methods/untrimmed-path-type.stderr b/tests/ui/methods/untrimmed-path-type.stderr
index 1f3101ff4e7..ee07e2daa1e 100644
--- a/tests/ui/methods/untrimmed-path-type.stderr
+++ b/tests/ui/methods/untrimmed-path-type.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `unknown` found for enum `Result` in the current scope
+error[E0599]: no method named `unknown` found for enum `Result<T, E>` in the current scope
   --> $DIR/untrimmed-path-type.rs:5:11
    |
 LL |    meow().unknown();
diff --git a/tests/ui/never_type/defaulted-never-note.fallback.stderr b/tests/ui/never_type/defaulted-never-note.fallback.stderr
index fe9a924f64a..7526a399bf1 100644
--- a/tests/ui/never_type/defaulted-never-note.fallback.stderr
+++ b/tests/ui/never_type/defaulted-never-note.fallback.stderr
@@ -8,7 +8,7 @@ LL |     foo(_x);
    |
    = help: the trait `ImplementedForUnitButNotNever` is implemented for `()`
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `foo`
   --> $DIR/defaulted-never-note.rs:25:11
    |
diff --git a/tests/ui/never_type/defaulted-never-note.rs b/tests/ui/never_type/defaulted-never-note.rs
index badb5d4c51d..71f0d9fa5bb 100644
--- a/tests/ui/never_type/defaulted-never-note.rs
+++ b/tests/ui/never_type/defaulted-never-note.rs
@@ -35,7 +35,7 @@ fn smeg() {
     //[fallback]~| HELP trait `ImplementedForUnitButNotNever` is implemented for `()`
     //[fallback]~| NOTE this error might have been caused
     //[fallback]~| NOTE required by a bound introduced by this call
-    //[fallback]~| HELP did you intend
+    //[fallback]~| HELP you might have intended to use the type `()`
 }
 
 fn main() {
diff --git a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
index c5463814475..610c687194b 100644
--- a/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
+++ b/tests/ui/never_type/diverging-fallback-no-leak.fallback.stderr
@@ -10,7 +10,7 @@ LL |     unconstrained_arg(return);
              ()
              i32
    = note: this error might have been caused by changes to Rust's type-inference algorithm (see issue #48950 <https://github.com/rust-lang/rust/issues/48950> for more information)
-   = help: did you intend to use the type `()` here instead?
+   = help: you might have intended to use the type `()` here instead
 note: required by a bound in `unconstrained_arg`
   --> $DIR/diverging-fallback-no-leak.rs:12:25
    |
diff --git a/tests/ui/offset-of/offset-of-tuple-field.stderr b/tests/ui/offset-of/offset-of-tuple-field.stderr
index 4da0d851650..01622c5fa2d 100644
--- a/tests/ui/offset-of/offset-of-tuple-field.stderr
+++ b/tests/ui/offset-of/offset-of-tuple-field.stderr
@@ -15,60 +15,96 @@ error[E0609]: no field `_0` on type `(u8, u8)`
    |
 LL |     offset_of!((u8, u8), _0);
    |                          ^^
+   |
+help: a field with a similar name exists
+   |
+LL -     offset_of!((u8, u8), _0);
+LL +     offset_of!((u8, u8), 0);
+   |
 
 error[E0609]: no field `01` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:7:26
    |
 LL |     offset_of!((u8, u8), 01);
    |                          ^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e2` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:8:26
    |
 LL |     offset_of!((u8, u8), 1e2);
    |                          ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1_` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:9:26
    |
 LL |     offset_of!((u8, u8), 1_u8);
    |                          ^^^^
+   |
+help: a field with a similar name exists
+   |
+LL -     offset_of!((u8, u8), 1_u8);
+LL +     offset_of!((u8, u8), 1);
+   |
 
 error[E0609]: no field `1e2` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:12:35
    |
 LL |     builtin # offset_of((u8, u8), 1e2);
    |                                   ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `_0` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:13:35
    |
 LL |     builtin # offset_of((u8, u8), _0);
    |                                   ^^
+   |
+help: a field with a similar name exists
+   |
+LL -     builtin # offset_of((u8, u8), _0);
+LL +     builtin # offset_of((u8, u8), 0);
+   |
 
 error[E0609]: no field `01` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:14:35
    |
 LL |     builtin # offset_of((u8, u8), 01);
    |                                   ^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1_` on type `(u8, u8)`
   --> $DIR/offset-of-tuple-field.rs:15:35
    |
 LL |     builtin # offset_of((u8, u8), 1_u8);
    |                                   ^^^^
+   |
+help: a field with a similar name exists
+   |
+LL -     builtin # offset_of((u8, u8), 1_u8);
+LL +     builtin # offset_of((u8, u8), 1);
+   |
 
 error[E0609]: no field `2` on type `(u8, u16)`
   --> $DIR/offset-of-tuple-field.rs:18:47
    |
 LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.2);
    |                                               ^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e2` on type `(u8, u16)`
   --> $DIR/offset-of-tuple-field.rs:19:47
    |
 LL |     offset_of!(((u8, u16), (u32, u16, u8)), 0.1e2);
    |                                               ^^^
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0` on type `u8`
   --> $DIR/offset-of-tuple-field.rs:21:49
diff --git a/tests/ui/parser/float-field.stderr b/tests/ui/parser/float-field.stderr
index 0cc1b0767dc..078d16a4117 100644
--- a/tests/ui/parser/float-field.stderr
+++ b/tests/ui/parser/float-field.stderr
@@ -305,6 +305,8 @@ error[E0609]: no field `1e1` on type `(u8, u8)`
    |
 LL |     { s.1.1e1; }
    |           ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `0x1e1` on type `S`
   --> $DIR/float-field.rs:34:9
@@ -343,12 +345,16 @@ error[E0609]: no field `f32` on type `(u8, u8)`
    |
 LL |     { s.1.f32; }
    |           ^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `1e1` on type `(u8, u8)`
   --> $DIR/float-field.rs:71:9
    |
 LL |     { s.1.1e1f32; }
    |         ^^^^^^^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 57 previous errors
 
diff --git a/tests/ui/parser/macro/macro-attr-bad.rs b/tests/ui/parser/macro/macro-attr-bad.rs
new file mode 100644
index 00000000000..4313a4d04ab
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-bad.rs
@@ -0,0 +1,32 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr_incomplete_1 { attr }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_incomplete_2 { attr() }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_incomplete_3 { attr() {} }
+//~^ ERROR expected `=>`
+
+macro_rules! attr_incomplete_4 { attr() {} => }
+//~^ ERROR macro definition ended unexpectedly
+
+macro_rules! attr_noparens_1 { attr{} {} => {} }
+//~^ ERROR macro attribute argument matchers require parentheses
+
+macro_rules! attr_noparens_2 { attr[] {} => {} }
+//~^ ERROR macro attribute argument matchers require parentheses
+
+macro_rules! attr_noparens_3 { attr _ {} => {} }
+//~^ ERROR invalid macro matcher
+
+macro_rules! attr_dup_matcher_1 { attr() {$x:ident $x:ident} => {} }
+//~^ ERROR duplicate matcher binding
+
+macro_rules! attr_dup_matcher_2 { attr($x:ident $x:ident) {} => {} }
+//~^ ERROR duplicate matcher binding
+
+macro_rules! attr_dup_matcher_3 { attr($x:ident) {$x:ident} => {} }
+//~^ ERROR duplicate matcher binding
diff --git a/tests/ui/parser/macro/macro-attr-bad.stderr b/tests/ui/parser/macro/macro-attr-bad.stderr
new file mode 100644
index 00000000000..4d286b66649
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-bad.stderr
@@ -0,0 +1,80 @@
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:4:38
+   |
+LL | macro_rules! attr_incomplete_1 { attr }
+   |                                      ^ expected macro attr args
+
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:7:40
+   |
+LL | macro_rules! attr_incomplete_2 { attr() }
+   |                                        ^ expected macro attr body
+
+error: expected `=>`, found end of macro arguments
+  --> $DIR/macro-attr-bad.rs:10:43
+   |
+LL | macro_rules! attr_incomplete_3 { attr() {} }
+   |                                           ^ expected `=>`
+
+error: macro definition ended unexpectedly
+  --> $DIR/macro-attr-bad.rs:13:46
+   |
+LL | macro_rules! attr_incomplete_4 { attr() {} => }
+   |                                              ^ expected right-hand side of macro rule
+
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-bad.rs:16:36
+   |
+LL | macro_rules! attr_noparens_1 { attr{} {} => {} }
+   |                                    ^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL - macro_rules! attr_noparens_1 { attr{} {} => {} }
+LL + macro_rules! attr_noparens_1 { attr() {} => {} }
+   |
+
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-bad.rs:19:36
+   |
+LL | macro_rules! attr_noparens_2 { attr[] {} => {} }
+   |                                    ^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL - macro_rules! attr_noparens_2 { attr[] {} => {} }
+LL + macro_rules! attr_noparens_2 { attr() {} => {} }
+   |
+
+error: invalid macro matcher; matchers must be contained in balanced delimiters
+  --> $DIR/macro-attr-bad.rs:22:37
+   |
+LL | macro_rules! attr_noparens_3 { attr _ {} => {} }
+   |                                     ^
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:25:52
+   |
+LL | macro_rules! attr_dup_matcher_1 { attr() {$x:ident $x:ident} => {} }
+   |                                           -------- ^^^^^^^^ duplicate binding
+   |                                           |
+   |                                           previous binding
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:28:49
+   |
+LL | macro_rules! attr_dup_matcher_2 { attr($x:ident $x:ident) {} => {} }
+   |                                        -------- ^^^^^^^^ duplicate binding
+   |                                        |
+   |                                        previous binding
+
+error: duplicate matcher binding
+  --> $DIR/macro-attr-bad.rs:31:51
+   |
+LL | macro_rules! attr_dup_matcher_3 { attr($x:ident) {$x:ident} => {} }
+   |                                        --------   ^^^^^^^^ duplicate binding
+   |                                        |
+   |                                        previous binding
+
+error: aborting due to 10 previous errors
+
diff --git a/tests/ui/parser/macro/macro-attr-recovery.rs b/tests/ui/parser/macro/macro-attr-recovery.rs
new file mode 100644
index 00000000000..dbb795f57aa
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-recovery.rs
@@ -0,0 +1,19 @@
+#![crate_type = "lib"]
+#![feature(macro_attr)]
+
+macro_rules! attr {
+    attr[$($args:tt)*] { $($body:tt)* } => {
+        //~^ ERROR: macro attribute argument matchers require parentheses
+        //~v ERROR: attr:
+        compile_error!(concat!(
+            "attr: args=\"",
+            stringify!($($args)*),
+            "\" body=\"",
+            stringify!($($body)*),
+            "\"",
+        ));
+    };
+}
+
+#[attr]
+struct S;
diff --git a/tests/ui/parser/macro/macro-attr-recovery.stderr b/tests/ui/parser/macro/macro-attr-recovery.stderr
new file mode 100644
index 00000000000..ab3a0b7c607
--- /dev/null
+++ b/tests/ui/parser/macro/macro-attr-recovery.stderr
@@ -0,0 +1,31 @@
+error: macro attribute argument matchers require parentheses
+  --> $DIR/macro-attr-recovery.rs:5:9
+   |
+LL |     attr[$($args:tt)*] { $($body:tt)* } => {
+   |         ^^^^^^^^^^^^^^
+   |
+help: the delimiters should be `(` and `)`
+   |
+LL -     attr[$($args:tt)*] { $($body:tt)* } => {
+LL +     attr($($args:tt)*) { $($body:tt)* } => {
+   |
+
+error: attr: args="" body="struct S;"
+  --> $DIR/macro-attr-recovery.rs:8:9
+   |
+LL | /         compile_error!(concat!(
+LL | |             "attr: args=\"",
+LL | |             stringify!($($args)*),
+LL | |             "\" body=\"",
+LL | |             stringify!($($body)*),
+LL | |             "\"",
+LL | |         ));
+   | |__________^
+...
+LL |   #[attr]
+   |   ------- in this attribute macro expansion
+   |
+   = note: this error originates in the attribute macro `attr` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
index 704cae8bdbc..bab6308223e 100644
--- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.rs
@@ -15,7 +15,7 @@ fn main() {
     }
 
     match Box::new((true, Box::new(false))) {
-        //~^ ERROR non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+        //~^ ERROR non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
         (true, false) => {}
         (false, true) => {}
     }
diff --git a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
index 55fa84bafde..a1abd5f0e3f 100644
--- a/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
+++ b/tests/ui/pattern/deref-patterns/usefulness/non-exhaustive.stderr
@@ -28,11 +28,11 @@ LL ~         true => {},
 LL +         deref!(deref!(false)) => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+error[E0004]: non-exhaustive patterns: `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
   --> $DIR/non-exhaustive.rs:17:11
    |
 LL |     match Box::new((true, Box::new(false))) {
-   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((false, deref!(false)))` and `deref!((true, deref!(true)))` not covered
+   |           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ patterns `deref!((true, deref!(true)))` and `deref!((false, deref!(false)))` not covered
    |
 note: `Box<(bool, Box<bool>)>` defined here
   --> $SRC_DIR/alloc/src/boxed.rs:LL:COL
@@ -40,7 +40,7 @@ note: `Box<(bool, Box<bool>)>` defined here
 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 ~         (false, true) => {},
-LL +         deref!((false, deref!(false))) | deref!((true, deref!(true))) => todo!()
+LL +         deref!((true, deref!(true))) | deref!((false, deref!(false))) => todo!()
    |
 
 error[E0004]: non-exhaustive patterns: `deref!((deref!(T::C), _))` not covered
diff --git a/tests/ui/pattern/usefulness/unions.rs b/tests/ui/pattern/usefulness/unions.rs
index 80a7f36a09a..3de79c6f849 100644
--- a/tests/ui/pattern/usefulness/unions.rs
+++ b/tests/ui/pattern/usefulness/unions.rs
@@ -26,7 +26,7 @@ fn main() {
         }
         // Our approach can report duplicate witnesses sometimes.
         match (x, true) {
-            //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+            //~^ ERROR non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
             (U8AsBool { b: true }, true) => {}
             (U8AsBool { b: false }, true) => {}
             (U8AsBool { n: 1.. }, true) => {}
diff --git a/tests/ui/pattern/usefulness/unions.stderr b/tests/ui/pattern/usefulness/unions.stderr
index 4b397dc25db..98fb6a33ae4 100644
--- a/tests/ui/pattern/usefulness/unions.stderr
+++ b/tests/ui/pattern/usefulness/unions.stderr
@@ -16,11 +16,11 @@ LL ~             U8AsBool { n: 1.. } => {},
 LL +             U8AsBool { n: 0_u8 } | U8AsBool { b: false } => todo!()
    |
 
-error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+error[E0004]: non-exhaustive patterns: `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
   --> $DIR/unions.rs:28:15
    |
 LL |         match (x, true) {
-   |               ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: false }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
+   |               ^^^^^^^^^ patterns `(U8AsBool { n: 0_u8 }, false)`, `(U8AsBool { b: true }, false)`, `(U8AsBool { n: 0_u8 }, false)` and 1 more not covered
    |
    = note: the matched value is of type `(U8AsBool, bool)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
diff --git a/tests/ui/proc-macro/span-from-proc-macro.stderr b/tests/ui/proc-macro/span-from-proc-macro.stderr
index 452c04df877..c79ab04eadf 100644
--- a/tests/ui/proc-macro/span-from-proc-macro.stderr
+++ b/tests/ui/proc-macro/span-from-proc-macro.stderr
@@ -10,7 +10,7 @@ LL |             field: MissingType
   ::: $DIR/span-from-proc-macro.rs:8:1
    |
 LL | #[error_from_attribute]
-   | ----------------------- in this procedural macro expansion
+   | ----------------------- in this attribute macro expansion
 
 error[E0412]: cannot find type `OtherMissingType` in this scope
   --> $DIR/auxiliary/span-from-proc-macro.rs:42:21
diff --git a/tests/ui/recursion/issue-23122-2.rs b/tests/ui/recursion/issue-23122-2.rs
index 95e1f60d8b0..d4f13e9fa55 100644
--- a/tests/ui/recursion/issue-23122-2.rs
+++ b/tests/ui/recursion/issue-23122-2.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 trait Next {
     type Next: Next;
 }
diff --git a/tests/ui/recursion/issue-23122-2.stderr b/tests/ui/recursion/issue-23122-2.stderr
index c5774cc1888..de402d65e6d 100644
--- a/tests/ui/recursion/issue-23122-2.stderr
+++ b/tests/ui/recursion/issue-23122-2.stderr
@@ -1,17 +1,19 @@
 error[E0275]: overflow evaluating the requirement `<<<<<<<... as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next: Sized`
-  --> $DIR/issue-23122-2.rs:10:17
+  --> $DIR/issue-23122-2.rs:11:17
    |
 LL |     type Next = <GetNext<T::Next> as Next>::Next;
    |                 ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_23122_2`)
-note: required for `GetNext<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<T as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
-  --> $DIR/issue-23122-2.rs:9:15
+note: required for `GetNext<<<<... as Next>::Next as Next>::Next as Next>::Next>` to implement `Next`
+  --> $DIR/issue-23122-2.rs:10:15
    |
 LL | impl<T: Next> Next for GetNext<T> {
    |      -        ^^^^     ^^^^^^^^^^
    |      |
    |      unsatisfied trait bound introduced here
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-23122-2.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
index 7b7b1a9580b..c219a920bb4 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.rs
@@ -1,3 +1,4 @@
+//@ compile-flags: -Zwrite-long-types-to-disk=yes
 // `S` is infinitely recursing so it's not possible to generate a finite
 // drop impl.
 //
diff --git a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
index 409f63b91b6..cf3bc4578a7 100644
--- a/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
+++ b/tests/ui/recursion/issue-38591-non-regular-dropck-recursion.stderr
@@ -1,10 +1,12 @@
 error[E0320]: overflow while adding drop-check rules for `S<u32>`
-  --> $DIR/issue-38591-non-regular-dropck-recursion.rs:11:6
+  --> $DIR/issue-38591-non-regular-dropck-recursion.rs:12:6
    |
 LL | fn f(x: S<u32>) {}
    |      ^
    |
-   = note: overflowed on `S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(u32)))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))))>`
+   = note: overflowed on `S<fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(fn(...))))))))))))))))>`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-38591-non-regular-dropck-recursion.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/recursion/issue-83150.rs b/tests/ui/recursion/issue-83150.rs
index b720c168187..9194ce1ab17 100644
--- a/tests/ui/recursion/issue-83150.rs
+++ b/tests/ui/recursion/issue-83150.rs
@@ -1,6 +1,6 @@
 //~ ERROR overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
 //@ build-fail
-//@ compile-flags: -Copt-level=0
+//@ compile-flags: -Copt-level=0 -Zwrite-long-types-to-disk=yes
 
 fn main() {
     let mut iter = 0u8..1;
diff --git a/tests/ui/recursion/issue-83150.stderr b/tests/ui/recursion/issue-83150.stderr
index 600922f1e57..a245b001bad 100644
--- a/tests/ui/recursion/issue-83150.stderr
+++ b/tests/ui/recursion/issue-83150.stderr
@@ -13,9 +13,11 @@ LL |     func(&mut iter.map(|x| x + 1))
 error[E0275]: overflow evaluating the requirement `Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>: Iterator`
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`issue_83150`)
-   = note: required for `&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Range<u8>, {closure@issue-83150.rs:12:24}>` to implement `Iterator`
    = note: 65 redundant requirements hidden
-   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut Map<&mut std::ops::Range<u8>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>, {closure@$DIR/issue-83150.rs:12:24: 12:27}>` to implement `Iterator`
+   = note: required for `&mut Map<&mut Map<&mut Map<&mut Map<&mut ..., ...>, ...>, ...>, ...>` to implement `Iterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-83150.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
index b89c5e8dda8..020c2e6f241 100644
--- a/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
+++ b/tests/ui/rfcs/rfc-1937-termination-trait/termination-trait-test-wrong-type.stderr
@@ -2,7 +2,7 @@ error[E0277]: the trait bound `f32: Termination` is not satisfied
   --> $DIR/termination-trait-test-wrong-type.rs:6:31
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn can_parse_zero_as_f32() -> Result<f32, ParseFloatError> {
    |                               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ the trait `Termination` is not implemented for `f32`
    |
diff --git a/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
index 5e652efb364..2dadc5c2d33 100644
--- a/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
+++ b/tests/ui/self/arbitrary_self_type_infinite_recursion.stderr
@@ -32,7 +32,7 @@ LL |   p.method();
    |
    = help: consider increasing the recursion limit by adding a `#![recursion_limit = "256"]` attribute to your crate (`arbitrary_self_type_infinite_recursion`)
 
-error[E0599]: no method named `method` found for struct `MySmartPtr` in the current scope
+error[E0599]: no method named `method` found for struct `MySmartPtr<T>` in the current scope
   --> $DIR/arbitrary_self_type_infinite_recursion.rs:21:5
    |
 LL | struct MySmartPtr<T>(T);
diff --git a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
index a30cf605829..5d7f6142093 100644
--- a/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
+++ b/tests/ui/self/arbitrary_self_types_not_allow_call_with_no_deref.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `frobnicate_ref` found for struct `CppRef` in the current scope
+error[E0599]: no method named `frobnicate_ref` found for struct `CppRef<T>` in the current scope
   --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:29:17
    |
 LL | struct CppRef<T>(T);
@@ -16,7 +16,7 @@ help: there is a method `frobnicate_cpp_ref` with a similar name
 LL |     foo_cpp_ref.frobnicate_cpp_ref();
    |                            ++++
 
-error[E0599]: no method named `frobnicate_self` found for struct `CppRef` in the current scope
+error[E0599]: no method named `frobnicate_self` found for struct `CppRef<T>` in the current scope
   --> $DIR/arbitrary_self_types_not_allow_call_with_no_deref.rs:32:17
    |
 LL | struct CppRef<T>(T);
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
index d877dbe6075..28845890278 100644
--- a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.rs
@@ -9,5 +9,5 @@ impl S {
 fn main() {
     Pin::new(S).x();
     //~^ ERROR the trait bound `S: Deref` is not satisfied
-    //~| ERROR no method named `x` found for struct `Pin` in the current scope
+    //~| ERROR no method named `x` found for struct `Pin<Ptr>` in the current scope
 }
diff --git a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
index 1811cd6753f..df226a9366a 100644
--- a/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
+++ b/tests/ui/self/arbitrary_self_types_pin_needing_borrow.stderr
@@ -15,7 +15,7 @@ LL |     Pin::new(&S).x();
 LL |     Pin::new(&mut S).x();
    |              ++++
 
-error[E0599]: no method named `x` found for struct `Pin` in the current scope
+error[E0599]: no method named `x` found for struct `Pin<Ptr>` in the current scope
   --> $DIR/arbitrary_self_types_pin_needing_borrow.rs:10:17
    |
 LL |     Pin::new(S).x();
diff --git a/tests/ui/simd/libm_no_std_cant_float.stderr b/tests/ui/simd/libm_no_std_cant_float.stderr
index 97e0b7efe2a..cc9aefaad5e 100644
--- a/tests/ui/simd/libm_no_std_cant_float.stderr
+++ b/tests/ui/simd/libm_no_std_cant_float.stderr
@@ -1,34 +1,34 @@
-error[E0599]: no method named `ceil` found for struct `Simd` in the current scope
+error[E0599]: no method named `ceil` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:15:17
    |
 LL |     let _xc = x.ceil();
    |                 ^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `floor` found for struct `Simd` in the current scope
+error[E0599]: no method named `floor` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:16:17
    |
 LL |     let _xf = x.floor();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `round` found for struct `Simd` in the current scope
+error[E0599]: no method named `round` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:17:17
    |
 LL |     let _xr = x.round();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `trunc` found for struct `Simd` in the current scope
+error[E0599]: no method named `trunc` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:18:17
    |
 LL |     let _xt = x.trunc();
    |                 ^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `mul_add` found for struct `Simd` in the current scope
+error[E0599]: no method named `mul_add` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:19:19
    |
 LL |     let _xfma = x.mul_add(x, x);
    |                   ^^^^^^^ method not found in `Simd<f32, 4>`
 
-error[E0599]: no method named `sqrt` found for struct `Simd` in the current scope
+error[E0599]: no method named `sqrt` found for struct `Simd<T, N>` in the current scope
   --> $DIR/libm_no_std_cant_float.rs:20:20
    |
 LL |     let _xsqrt = x.sqrt();
diff --git a/tests/ui/structs/tuple-struct-field-naming-47073.stderr b/tests/ui/structs/tuple-struct-field-naming-47073.stderr
index efbdaeca4ea..09ba2fb406a 100644
--- a/tests/ui/structs/tuple-struct-field-naming-47073.stderr
+++ b/tests/ui/structs/tuple-struct-field-naming-47073.stderr
@@ -4,11 +4,7 @@ error[E0609]: no field `00` on type `Verdict`
 LL |     let _condemned = justice.00;
    |                              ^^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -     let _condemned = justice.00;
-LL +     let _condemned = justice.0;
-   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `001` on type `Verdict`
   --> $DIR/tuple-struct-field-naming-47073.rs:11:31
diff --git a/tests/ui/suggestions/enum-method-probe.fixed b/tests/ui/suggestions/enum-method-probe.fixed
index b7fd6f112d5..1ce6a943c5b 100644
--- a/tests/ui/suggestions/enum-method-probe.fixed
+++ b/tests/ui/suggestions/enum-method-probe.fixed
@@ -14,7 +14,7 @@ impl Foo {
 fn test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -22,7 +22,7 @@ fn test_result_in_result() -> Result<(), ()> {
 async fn async_test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -30,21 +30,21 @@ async fn async_test_result_in_result() -> Result<(), ()> {
 fn test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 async fn async_test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 fn test_option_in_option() -> Option<()> {
     let res: Option<_> = Some(Foo);
     res?.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP use the `?` operator
     Some(())
 }
@@ -52,7 +52,7 @@ fn test_option_in_option() -> Option<()> {
 fn test_option_in_unit_return() {
     let res: Option<_> = Some(Foo);
     res.expect("REASON").get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
 }
 
diff --git a/tests/ui/suggestions/enum-method-probe.rs b/tests/ui/suggestions/enum-method-probe.rs
index cbb819b7c8c..dd3addbd0a3 100644
--- a/tests/ui/suggestions/enum-method-probe.rs
+++ b/tests/ui/suggestions/enum-method-probe.rs
@@ -14,7 +14,7 @@ impl Foo {
 fn test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -22,7 +22,7 @@ fn test_result_in_result() -> Result<(), ()> {
 async fn async_test_result_in_result() -> Result<(), ()> {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP use the `?` operator
     Ok(())
 }
@@ -30,21 +30,21 @@ async fn async_test_result_in_result() -> Result<(), ()> {
 fn test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 async fn async_test_result_in_unit_return() {
     let res: Result<_, ()> = Ok(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Result` in the current scope
+    //~^ ERROR no method named `get` found for enum `Result<T, E>` in the current scope
     //~| HELP consider using `Result::expect` to unwrap the `Foo` value, panicking if the value is a `Result::Err`
 }
 
 fn test_option_in_option() -> Option<()> {
     let res: Option<_> = Some(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP use the `?` operator
     Some(())
 }
@@ -52,7 +52,7 @@ fn test_option_in_option() -> Option<()> {
 fn test_option_in_unit_return() {
     let res: Option<_> = Some(Foo);
     res.get();
-    //~^ ERROR no method named `get` found for enum `Option` in the current scope
+    //~^ ERROR no method named `get` found for enum `Option<T>` in the current scope
     //~| HELP consider using `Option::expect` to unwrap the `Foo` value, panicking if the value is an `Option::None`
 }
 
diff --git a/tests/ui/suggestions/enum-method-probe.stderr b/tests/ui/suggestions/enum-method-probe.stderr
index e66973d9d95..5aa0fc44c7b 100644
--- a/tests/ui/suggestions/enum-method-probe.stderr
+++ b/tests/ui/suggestions/enum-method-probe.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:24:9
    |
 LL |     res.get();
@@ -14,7 +14,7 @@ help: use the `?` operator to extract the `Foo` value, propagating a `Result::Er
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:39:9
    |
 LL |     res.get();
@@ -30,7 +30,7 @@ help: consider using `Result::expect` to unwrap the `Foo` value, panicking if th
 LL |     res.expect("REASON").get();
    |        +++++++++++++++++
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:16:9
    |
 LL |     res.get();
@@ -46,7 +46,7 @@ help: use the `?` operator to extract the `Foo` value, propagating a `Result::Er
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Result` in the current scope
+error[E0599]: no method named `get` found for enum `Result<T, E>` in the current scope
   --> $DIR/enum-method-probe.rs:32:9
    |
 LL |     res.get();
@@ -62,7 +62,7 @@ help: consider using `Result::expect` to unwrap the `Foo` value, panicking if th
 LL |     res.expect("REASON").get();
    |        +++++++++++++++++
 
-error[E0599]: no method named `get` found for enum `Option` in the current scope
+error[E0599]: no method named `get` found for enum `Option<T>` in the current scope
   --> $DIR/enum-method-probe.rs:46:9
    |
 LL |     res.get();
@@ -78,7 +78,7 @@ help: use the `?` operator to extract the `Foo` value, propagating an `Option::N
 LL |     res?.get();
    |        +
 
-error[E0599]: no method named `get` found for enum `Option` in the current scope
+error[E0599]: no method named `get` found for enum `Option<T>` in the current scope
   --> $DIR/enum-method-probe.rs:54:9
    |
 LL |     res.get();
diff --git a/tests/ui/suggestions/field-has-method.rs b/tests/ui/suggestions/field-has-method.rs
index d28b6ba546c..6e584d78338 100644
--- a/tests/ui/suggestions/field-has-method.rs
+++ b/tests/ui/suggestions/field-has-method.rs
@@ -17,7 +17,7 @@ struct InferOk<T> {
 
 fn foo(i: InferOk<Ty>) {
     let k = i.kind();
-    //~^ ERROR no method named `kind` found for struct `InferOk` in the current scope
+    //~^ ERROR no method named `kind` found for struct `InferOk<T>` in the current scope
 }
 
 fn main() {}
diff --git a/tests/ui/suggestions/field-has-method.stderr b/tests/ui/suggestions/field-has-method.stderr
index daff2db6418..adcb723e4f1 100644
--- a/tests/ui/suggestions/field-has-method.stderr
+++ b/tests/ui/suggestions/field-has-method.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `kind` found for struct `InferOk` in the current scope
+error[E0599]: no method named `kind` found for struct `InferOk<T>` in the current scope
   --> $DIR/field-has-method.rs:19:15
    |
 LL | struct InferOk<T> {
diff --git a/tests/ui/suggestions/inner_type.fixed b/tests/ui/suggestions/inner_type.fixed
index 175a2a02acd..8174f8e204e 100644
--- a/tests/ui/suggestions/inner_type.fixed
+++ b/tests/ui/suggestions/inner_type.fixed
@@ -15,26 +15,26 @@ fn main() {
     let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
 
     other_item.borrow().method();
-    //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
 
     other_item.borrow_mut().some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
 
     let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
 
     another_item.lock().unwrap().method();
-    //~^ ERROR no method named `method` found for struct `std::sync::Mutex` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `std::sync::Mutex<T>` in the current scope [E0599]
     //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
 
     another_item.read().unwrap().method();
-    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     another_item.write().unwrap().some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 }
diff --git a/tests/ui/suggestions/inner_type.rs b/tests/ui/suggestions/inner_type.rs
index ab021414f56..e4eaf07ca8b 100644
--- a/tests/ui/suggestions/inner_type.rs
+++ b/tests/ui/suggestions/inner_type.rs
@@ -15,26 +15,26 @@ fn main() {
     let other_item = std::cell::RefCell::new(Struct { p: 42_u32 });
 
     other_item.method();
-    //~^ ERROR no method named `method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow exists
 
     other_item.some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope [E0599]
     //~| HELP .borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any borrows exist
 
     let another_item = std::sync::Mutex::new(Struct { p: 42_u32 });
 
     another_item.method();
-    //~^ ERROR no method named `method` found for struct `std::sync::Mutex` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `std::sync::Mutex<T>` in the current scope [E0599]
     //~| HELP use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     let another_item = std::sync::RwLock::new(Struct { p: 42_u32 });
 
     another_item.method();
-    //~^ ERROR no method named `method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP  use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 
     another_item.some_mutable_method();
-    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock` in the current scope [E0599]
+    //~^ ERROR no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope [E0599]
     //~| HELP use `.write().unwrap()` to mutably borrow the `Struct<u32>`, blocking the current thread until it can be acquired
 }
diff --git a/tests/ui/suggestions/inner_type.stderr b/tests/ui/suggestions/inner_type.stderr
index 67ebb5789b7..017ddb5ad6d 100644
--- a/tests/ui/suggestions/inner_type.stderr
+++ b/tests/ui/suggestions/inner_type.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for struct `RefCell` in the current scope
+error[E0599]: no method named `method` found for struct `RefCell<T>` in the current scope
   --> $DIR/inner_type.rs:17:16
    |
 LL |     other_item.method();
@@ -14,7 +14,7 @@ help: use `.borrow()` to borrow the `Struct<u32>`, panicking if a mutable borrow
 LL |     other_item.borrow().method();
    |               +++++++++
 
-error[E0599]: no method named `some_mutable_method` found for struct `RefCell` in the current scope
+error[E0599]: no method named `some_mutable_method` found for struct `RefCell<T>` in the current scope
   --> $DIR/inner_type.rs:21:16
    |
 LL |     other_item.some_mutable_method();
@@ -30,7 +30,7 @@ help: use `.borrow_mut()` to mutably borrow the `Struct<u32>`, panicking if any
 LL |     other_item.borrow_mut().some_mutable_method();
    |               +++++++++++++
 
-error[E0599]: no method named `method` found for struct `std::sync::Mutex` in the current scope
+error[E0599]: no method named `method` found for struct `std::sync::Mutex<T>` in the current scope
   --> $DIR/inner_type.rs:27:18
    |
 LL |     another_item.method();
@@ -46,7 +46,7 @@ help: use `.lock().unwrap()` to borrow the `Struct<u32>`, blocking the current t
 LL |     another_item.lock().unwrap().method();
    |                 ++++++++++++++++
 
-error[E0599]: no method named `method` found for struct `RwLock` in the current scope
+error[E0599]: no method named `method` found for struct `RwLock<T>` in the current scope
   --> $DIR/inner_type.rs:33:18
    |
 LL |     another_item.method();
@@ -62,7 +62,7 @@ help: use `.read().unwrap()` to borrow the `Struct<u32>`, blocking the current t
 LL |     another_item.read().unwrap().method();
    |                 ++++++++++++++++
 
-error[E0599]: no method named `some_mutable_method` found for struct `RwLock` in the current scope
+error[E0599]: no method named `some_mutable_method` found for struct `RwLock<T>` in the current scope
   --> $DIR/inner_type.rs:37:18
    |
 LL |     another_item.some_mutable_method();
diff --git a/tests/ui/suggestions/inner_type2.rs b/tests/ui/suggestions/inner_type2.rs
index fac68c053eb..7082862f409 100644
--- a/tests/ui/suggestions/inner_type2.rs
+++ b/tests/ui/suggestions/inner_type2.rs
@@ -16,11 +16,11 @@ thread_local! {
 
 fn main() {
     STRUCT.method();
-    //~^ ERROR no method named `method` found for struct `LocalKey` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for struct `LocalKey<T>` in the current scope [E0599]
     //~| HELP use `with` or `try_with` to access thread local storage
 
     let item = std::mem::MaybeUninit::new(Struct { p: 42_u32 });
     item.method();
-    //~^ ERROR no method named `method` found for union `MaybeUninit` in the current scope [E0599]
+    //~^ ERROR no method named `method` found for union `MaybeUninit<T>` in the current scope [E0599]
     //~| HELP if this `MaybeUninit<Struct<u32>>` has been initialized, use one of the `assume_init` methods to access the inner value
 }
diff --git a/tests/ui/suggestions/inner_type2.stderr b/tests/ui/suggestions/inner_type2.stderr
index 984366123c8..e6cb2048522 100644
--- a/tests/ui/suggestions/inner_type2.stderr
+++ b/tests/ui/suggestions/inner_type2.stderr
@@ -1,4 +1,4 @@
-error[E0599]: no method named `method` found for struct `LocalKey` in the current scope
+error[E0599]: no method named `method` found for struct `LocalKey<T>` in the current scope
   --> $DIR/inner_type2.rs:18:12
    |
 LL |     STRUCT.method();
@@ -11,7 +11,7 @@ note: the method `method` exists on the type `Struct<u32>`
 LL |     pub fn method(&self) {}
    |     ^^^^^^^^^^^^^^^^^^^^
 
-error[E0599]: no method named `method` found for union `MaybeUninit` in the current scope
+error[E0599]: no method named `method` found for union `MaybeUninit<T>` in the current scope
   --> $DIR/inner_type2.rs:23:10
    |
 LL |     item.method();
diff --git a/tests/ui/test-attrs/issue-12997-2.stderr b/tests/ui/test-attrs/issue-12997-2.stderr
index 1123630a4a1..41d0074ad1a 100644
--- a/tests/ui/test-attrs/issue-12997-2.stderr
+++ b/tests/ui/test-attrs/issue-12997-2.stderr
@@ -2,7 +2,7 @@ error[E0308]: mismatched types
   --> $DIR/issue-12997-2.rs:8:1
    |
 LL | #[bench]
-   | -------- in this procedural macro expansion
+   | -------- in this attribute macro expansion
 LL | fn bar(x: isize) { }
    | ^^^^^^^^^^^^^^^^^^^^
    | |
diff --git a/tests/ui/test-attrs/test-function-signature.stderr b/tests/ui/test-attrs/test-function-signature.stderr
index c025163c0bd..55d09970b32 100644
--- a/tests/ui/test-attrs/test-function-signature.stderr
+++ b/tests/ui/test-attrs/test-function-signature.stderr
@@ -26,7 +26,7 @@ error[E0277]: the trait bound `i32: Termination` is not satisfied
   --> $DIR/test-function-signature.rs:9:13
    |
 LL | #[test]
-   | ------- in this procedural macro expansion
+   | ------- in this attribute macro expansion
 LL | fn bar() -> i32 {
    |             ^^^ the trait `Termination` is not implemented for `i32`
    |
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.rs b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
index 7c9ae09349a..434cf00fc4b 100644
--- a/tests/ui/traits/issue-91949-hangs-on-recursion.rs
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.rs
@@ -1,6 +1,6 @@
 //~ ERROR overflow evaluating the requirement `<std::iter::Empty<()> as Iterator>::Item == ()`
 //@ build-fail
-//@ compile-flags: -Zinline-mir=no
+//@ compile-flags: -Zinline-mir=no -Zwrite-long-types-to-disk=yes
 
 // Regression test for #91949.
 // This hanged *forever* on 1.56, fixed by #90423.
diff --git a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
index c2f09371cf7..a179107885a 100644
--- a/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
+++ b/tests/ui/traits/issue-91949-hangs-on-recursion.stderr
@@ -24,7 +24,9 @@ LL | impl<T, I: Iterator<Item = T>> Iterator for IteratorOfWrapped<T, I> {
    |                     |
    |                     unsatisfied trait bound introduced here
    = note: 256 redundant requirements hidden
-   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<IteratorOfWrapped<(), std::iter::Empty<()>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>, {closure@$DIR/issue-91949-hangs-on-recursion.rs:26:45: 26:48}>>` to implement `Iterator`
+   = note: required for `IteratorOfWrapped<(), Map<IteratorOfWrapped<(), Map<..., ...>>, ...>>` to implement `Iterator`
+   = note: the full name for the type has been written to '$TEST_BUILD_DIR/issue-91949-hangs-on-recursion.long-type-$LONG_TYPE_HASH.txt'
+   = note: consider using `--verbose` to print the full type name to the console
 
 error: aborting due to 1 previous error; 1 warning emitted
 
diff --git a/tests/ui/traits/well-formed-recursion-limit.stderr b/tests/ui/traits/well-formed-recursion-limit.stderr
index e0270ecabbd..a4c85c4fcbd 100644
--- a/tests/ui/traits/well-formed-recursion-limit.stderr
+++ b/tests/ui/traits/well-formed-recursion-limit.stderr
@@ -3,12 +3,16 @@ error[E0609]: no field `ab` on type `(Box<(dyn Fn(Option<A>) -> Option<B> + 'sta
    |
 LL |     let (ab, ba) = (i.ab, i.ba);
    |                       ^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `ba` on type `(Box<(dyn Fn(Option<A>) -> Option<B> + 'static)>, Box<(dyn Fn(Option<B>) -> Option<A> + 'static)>)`
   --> $DIR/well-formed-recursion-limit.rs:12:29
    |
 LL |     let (ab, ba) = (i.ab, i.ba);
    |                             ^^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error[E0275]: overflow assigning `_` to `Option<_>`
   --> $DIR/well-formed-recursion-limit.rs:15:33
diff --git a/tests/ui/tuple/index-invalid.stderr b/tests/ui/tuple/index-invalid.stderr
index ae2c275f52c..fee09b7947c 100644
--- a/tests/ui/tuple/index-invalid.stderr
+++ b/tests/ui/tuple/index-invalid.stderr
@@ -3,18 +3,24 @@ error[E0609]: no field `1` on type `(((),),)`
    |
 LL |     let _ = (((),),).1.0;
    |                      ^ unknown field
+   |
+   = note: available field is: `0`
 
 error[E0609]: no field `1` on type `((),)`
   --> $DIR/index-invalid.rs:4:24
    |
 LL |     let _ = (((),),).0.1;
    |                        ^ unknown field
+   |
+   = note: available field is: `0`
 
 error[E0609]: no field `000` on type `(((),),)`
   --> $DIR/index-invalid.rs:6:22
    |
 LL |     let _ = (((),),).000.000;
    |                      ^^^ unknown field
+   |
+   = note: available field is: `0`
 
 error: aborting due to 3 previous errors
 
diff --git a/tests/ui/tuple/missing-field-access.rs b/tests/ui/tuple/missing-field-access.rs
new file mode 100644
index 00000000000..b94b7cf977c
--- /dev/null
+++ b/tests/ui/tuple/missing-field-access.rs
@@ -0,0 +1,16 @@
+// Ensure that suggestions to search for missing intermediary field accesses are available for both
+// tuple structs *and* regular tuples.
+// Ensure that we do not suggest pinning the expression just because `Pin::get_ref` exists.
+// https://github.com/rust-lang/rust/issues/144602
+use std::{fs::File, io::BufReader};
+
+struct F(BufReader<File>);
+
+fn main() {
+    let f = F(BufReader::new(File::open("x").unwrap()));
+    let x = f.get_ref(); //~ ERROR E0599
+    //~^ HELP one of the expressions' fields has a method of the same name
+    let f = (BufReader::new(File::open("x").unwrap()), );
+    let x = f.get_ref(); //~ ERROR E0599
+    //~^ HELP one of the expressions' fields has a method of the same name
+}
diff --git a/tests/ui/tuple/missing-field-access.stderr b/tests/ui/tuple/missing-field-access.stderr
new file mode 100644
index 00000000000..fd9f01f8ff6
--- /dev/null
+++ b/tests/ui/tuple/missing-field-access.stderr
@@ -0,0 +1,28 @@
+error[E0599]: no method named `get_ref` found for struct `F` in the current scope
+  --> $DIR/missing-field-access.rs:11:15
+   |
+LL | struct F(BufReader<File>);
+   | -------- method `get_ref` not found for this struct
+...
+LL |     let x = f.get_ref();
+   |               ^^^^^^^ method not found in `F`
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     let x = f.0.get_ref();
+   |               ++
+
+error[E0599]: no method named `get_ref` found for tuple `(BufReader<File>,)` in the current scope
+  --> $DIR/missing-field-access.rs:14:15
+   |
+LL |     let x = f.get_ref();
+   |               ^^^^^^^ method not found in `(BufReader<File>,)`
+   |
+help: one of the expressions' fields has a method of the same name
+   |
+LL |     let x = f.0.get_ref();
+   |               ++
+
+error: aborting due to 2 previous errors
+
+For more information about this error, try `rustc --explain E0599`.
diff --git a/tests/ui/tuple/tuple-index-out-of-bounds.stderr b/tests/ui/tuple/tuple-index-out-of-bounds.stderr
index 8b3c835c3e3..2be9d5631f7 100644
--- a/tests/ui/tuple/tuple-index-out-of-bounds.stderr
+++ b/tests/ui/tuple/tuple-index-out-of-bounds.stderr
@@ -4,17 +4,15 @@ error[E0609]: no field `2` on type `Point`
 LL |     origin.2;
    |            ^ unknown field
    |
-help: a field with a similar name exists
-   |
-LL -     origin.2;
-LL +     origin.0;
-   |
+   = note: available fields are: `0`, `1`
 
 error[E0609]: no field `2` on type `({integer}, {integer})`
   --> $DIR/tuple-index-out-of-bounds.rs:12:11
    |
 LL |     tuple.2;
    |           ^ unknown field
+   |
+   = note: available fields are: `0`, `1`
 
 error: aborting due to 2 previous errors